MUSE Pipeline Reference Manual  0.18.1
muse_wavecal_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-2013 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_wavecal_z.h" /* in turn includes muse.h */
36 
37 /*----------------------------------------------------------------------------*/
79 /*----------------------------------------------------------------------------*/
82 /*----------------------------------------------------------------------------*
83  * Static variables *
84  *----------------------------------------------------------------------------*/
85 static const char *muse_wavecal_help =
86  "This recipe detects arc emission lines and fits a wavelength solution to each slice of the instrument. The wavelength calibration table contains polynomials defining the wavelength solution of the slices on the CCD. Processing trims the raw data and records the overscan statistics, subtracts the bias (taking account of the overscan, if --overscan is not &none&) and converts them from adu to count. Optionally, the dark can be subtracted and the data can be divided by the flat-field, but this is not recommended. The data is then combined using input parameters, first into separate images for each lamp. If --lampwise is not given or if --lsf or --resample are given, these lamp-separate exposures are summed to create a single combined master arc. To compute the wavelength solution, arc lines are detected at the center of each slice (using threshold detection on a S/N image) and subsequently assigned wavelengths, using pattern matching to identify lines from the input line catalog. Each line is then traced to the edges of the slice, using Gaussian centering in each CCD column. The Gaussians not only yield center, but also centering error, and line properties (e.g. FWHM). Deviant fits are detected using polynomial fits to each arc line (using the xorder parameter) and rejected. If --lampwise is switched on, these analysis and measuring steps are carried out separately on images exposed by the different arc lamps, reducing the amount of blending, that can otherwise influence line identification and Gaussian centering. The final two-dimensional fit uses all positions (of all lamps), their wavelengths, and the given polynomial orders to compute the final wavelength solution for each slice, iteratively rejecting outliers. This final fit can be either unweighted (fitweighting=&uniform&, for fastest processing) or weighted (other values of fitweighting, for higher accuracy). If --lsf is switched on, the line spread function is determined for each slice and saved in the LSF table for later use with sky subtraction.";
87 
88 static const char *muse_wavecal_help_esorex =
89  "\n\nInput frames for raw frame tag \"ARC\":\n"
90  "\n Frame tag Type Req #Fr Description"
91  "\n -------------------- ---- --- --- ------------"
92  "\n ARC raw Y Raw arc lamp exposures"
93  "\n MASTER_BIAS calib Y 1 Master bias"
94  "\n MASTER_DARK calib . 1 Master dark"
95  "\n MASTER_FLAT calib . 1 Master flat"
96  "\n TRACE_TABLE calib Y 1 Trace table"
97  "\n LINE_CATALOG calib Y 1 Arc line catalog"
98  "\n BADPIX_TABLE calib . 1 Bad pixel table"
99  "\n LSF_TABLE calib . First guess for LSF parameters"
100  "\n\nProduct frames for raw frame tag \"ARC\":\n"
101  "\n Frame tag Level Description"
102  "\n -------------------- -------- ------------"
103  "\n WAVECAL_TABLE final Wavelength calibration table"
104  "\n WAVECAL_RESIDUALS final Fit residuals of all arc lines (if --residuals=true)"
105  "\n ARC_RED_LAMP final Reduced ARC image, per lamp"
106  "\n ARC_RED final Reduced master ARC image"
107  "\n ARC_RESAMPLED final Resampled arc images (if --resampled=true)"
108  "\n WAVE_MAP final Wavelength map of the input images"
109  "\n LSF_TABLE final Slice specific LSF parameters (if --lsf=true)"
110  "\n LSF_RESIDUALS final Subtracted pixel table after LSF fit (if --lsf=true and --lsf_residuals=true)";
111 
112 /*----------------------------------------------------------------------------*/
120 /*----------------------------------------------------------------------------*/
121 static cpl_recipeconfig *
122 muse_wavecal_new_recipeconfig(void)
123 {
124  cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
125  const char *tag;
126 
127  tag = "ARC";
128  cpl_recipeconfig_set_tag(recipeconfig, tag, 1, -1);
129  cpl_recipeconfig_set_input(recipeconfig, tag, "MASTER_BIAS", 1, 1);
130  cpl_recipeconfig_set_input(recipeconfig, tag, "MASTER_DARK", -1, 1);
131  cpl_recipeconfig_set_input(recipeconfig, tag, "MASTER_FLAT", -1, 1);
132  cpl_recipeconfig_set_input(recipeconfig, tag, "TRACE_TABLE", 1, 1);
133  cpl_recipeconfig_set_input(recipeconfig, tag, "LINE_CATALOG", 1, 1);
134  cpl_recipeconfig_set_input(recipeconfig, tag, "BADPIX_TABLE", -1, 1);
135  cpl_recipeconfig_set_input(recipeconfig, tag, "LSF_TABLE", 0, -1);
136  cpl_recipeconfig_set_output(recipeconfig, tag, "WAVECAL_TABLE");
137  cpl_recipeconfig_set_output(recipeconfig, tag, "WAVECAL_RESIDUALS");
138  cpl_recipeconfig_set_output(recipeconfig, tag, "ARC_RED_LAMP");
139  cpl_recipeconfig_set_output(recipeconfig, tag, "ARC_RED");
140  cpl_recipeconfig_set_output(recipeconfig, tag, "ARC_RESAMPLED");
141  cpl_recipeconfig_set_output(recipeconfig, tag, "WAVE_MAP");
142  cpl_recipeconfig_set_output(recipeconfig, tag, "LSF_TABLE");
143  cpl_recipeconfig_set_output(recipeconfig, tag, "LSF_RESIDUALS");
144 
145  return recipeconfig;
146 } /* muse_wavecal_new_recipeconfig() */
147 
148 /*----------------------------------------------------------------------------*/
158 /*----------------------------------------------------------------------------*/
159 static cpl_error_code
160 muse_wavecal_prepare_header(const char *aFrametag, cpl_propertylist *aHeader)
161 {
162  cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
163  cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
164  if (!strcmp(aFrametag, "WAVECAL_TABLE")) {
165  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ LINES NDET",
166  CPL_TYPE_INT,
167  "Number of detected arc lines in slice j");
168  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ LINES NID",
169  CPL_TYPE_INT,
170  "Number of identified arc lines in slice j");
171  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ LINES PEAK MEAN",
172  CPL_TYPE_FLOAT,
173  "[count] Mean peak count level above background of detected arc lines in slice j");
174  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ LINES PEAK STDEV",
175  CPL_TYPE_FLOAT,
176  "[count] Standard deviation of peak count level above background of detected arc lines in slice j");
177  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ LINES PEAK MIN",
178  CPL_TYPE_FLOAT,
179  "[count] Peak count level above background of the faintest line in slice j");
180  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ LINES PEAK MAX",
181  CPL_TYPE_FLOAT,
182  "[count] Peak count level above background of the brightest line in slice j");
183  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ LAMP[0-9] LINES PEAK MEAN",
184  CPL_TYPE_FLOAT,
185  "[count] Mean peak count level of lines of lamp l above background of detected arc lines in slice j. Not produced with --lampwise=FALSE!");
186  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ LAMP[0-9] LINES PEAK STDEV",
187  CPL_TYPE_FLOAT,
188  "[count] Standard deviation of peak count level of lines of lamp l above background of detected arc lines in slice j. Not produced with --lampwise=FALSE!");
189  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ LAMP[0-9] LINES PEAK MAX",
190  CPL_TYPE_FLOAT,
191  "[count] Peak count level above background of the brightest line of lamp l in slice j. Not produced with --lampwise=FALSE!");
192  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ LINES FWHM MEAN",
193  CPL_TYPE_FLOAT,
194  "Mean FWHM of detected arc lines in slice j");
195  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ LINES FWHM STDEV",
196  CPL_TYPE_FLOAT,
197  "Standard deviation of FWHM of detected arc lines in slice j");
198  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ LINES FWHM MIN",
199  CPL_TYPE_FLOAT,
200  "Minimum FWHM of detected arc lines in slice j");
201  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ LINES FWHM MAX",
202  CPL_TYPE_FLOAT,
203  "Maximum FWHM of detected arc lines in slice j");
204  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ RESOL",
205  CPL_TYPE_FLOAT,
206  "Mean spectral resolution R determined in slice j");
207  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ FIT NLINES",
208  CPL_TYPE_INT,
209  "Number of arc lines used in calibration solution fit in slice j");
210  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ FIT RMS",
211  CPL_TYPE_FLOAT,
212  "[Angstrom] RMS of the wavelength calibration fit in slice j");
213  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ DWLEN BOTTOM",
214  CPL_TYPE_FLOAT,
215  "[Angstrom] Difference in wavelength computed for the bottom left and bottom right corners of the slice on the CCD");
216  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ DWLEN TOP",
217  CPL_TYPE_FLOAT,
218  "[Angstrom] Difference in wavelength computed for the top left and top right corners of the slice on the CCD");
219  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ WLPOS",
220  CPL_TYPE_FLOAT,
221  "[pix] Position of wavelength given in WLEN in slice j");
222  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL SLICE[0-9]+ WLEN",
223  CPL_TYPE_FLOAT,
224  "[Angstrom] Wavelength associated to WLPOS in slice j");
225  } else if (!strcmp(aFrametag, "WAVECAL_RESIDUALS")) {
226  } else if (!strcmp(aFrametag, "ARC_RED_LAMP")) {
227  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL INPUT[0-9]+ NSATURATED",
228  CPL_TYPE_INT,
229  "Number of saturated pixels in raw arc i in input list");
230  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL NSATURATED",
231  CPL_TYPE_INT,
232  "Number of saturated pixels in output data");
233  } else if (!strcmp(aFrametag, "ARC_RED")) {
234  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL LAMP[0-9]+ INPUT[0-9]+ NSATURATED",
235  CPL_TYPE_INT,
236  "Number of saturated pixels in raw arc i of lamp l in input list");
237  muse_processing_prepare_property(aHeader, "ESO QC WAVECAL NSATURATED",
238  CPL_TYPE_INT,
239  "Number of saturated pixels in output data");
240  } else if (!strcmp(aFrametag, "ARC_RESAMPLED")) {
241  } else if (!strcmp(aFrametag, "WAVE_MAP")) {
242  } else if (!strcmp(aFrametag, "LSF_TABLE")) {
243  muse_processing_prepare_property(aHeader, "ESO QC LSF[0-9]+ AWAV",
244  CPL_TYPE_DOUBLE,
245  "[Angstrom] Wavelength of line l");
246  muse_processing_prepare_property(aHeader, "ESO QC IFU[0-9]+ SLICE[0-9]+ LSF[0-9]+ WIDTH",
247  CPL_TYPE_DOUBLE,
248  "[Angstrom] LSF width in IFU i, slice j at the wavelength of line l");
249  muse_processing_prepare_property(aHeader, "ESO QC IFU[0-9]+ SLICE[0-9]+ LSF[0-9]+ OFFSET",
250  CPL_TYPE_DOUBLE,
251  "[Angstrom] Wavelength calibration offset in IFU i, slice j at the wavelength of line l");
252  muse_processing_prepare_property(aHeader, "ESO QC IFU[0-9]+ SLICE[0-9]+ LSF[0-9]+ FWHM",
253  CPL_TYPE_FLOAT,
254  "[Angstrom] FWHM of the LSF in IFU i, slice j at the wavelength of line l");
255  muse_processing_prepare_property(aHeader, "ESO QC IFU[0-9]+ SLICE[0-9]+ WAVECAL ERROR",
256  CPL_TYPE_DOUBLE,
257  "Relative error of wavelength calibration of IFU i, slice j");
258  } else if (!strcmp(aFrametag, "LSF_RESIDUALS")) {
259  } else {
260  cpl_msg_warning(__func__, "Frame tag %s is not defined", aFrametag);
261  return CPL_ERROR_ILLEGAL_INPUT;
262  }
263  return CPL_ERROR_NONE;
264 } /* muse_wavecal_prepare_header() */
265 
266 /*----------------------------------------------------------------------------*/
275 /*----------------------------------------------------------------------------*/
276 static cpl_frame_level
277 muse_wavecal_get_frame_level(const char *aFrametag)
278 {
279  if (!aFrametag) {
280  return CPL_FRAME_LEVEL_NONE;
281  }
282  if (!strcmp(aFrametag, "WAVECAL_TABLE")) {
283  return CPL_FRAME_LEVEL_FINAL;
284  }
285  if (!strcmp(aFrametag, "WAVECAL_RESIDUALS")) {
286  return CPL_FRAME_LEVEL_FINAL;
287  }
288  if (!strcmp(aFrametag, "ARC_RED_LAMP")) {
289  return CPL_FRAME_LEVEL_FINAL;
290  }
291  if (!strcmp(aFrametag, "ARC_RED")) {
292  return CPL_FRAME_LEVEL_FINAL;
293  }
294  if (!strcmp(aFrametag, "ARC_RESAMPLED")) {
295  return CPL_FRAME_LEVEL_FINAL;
296  }
297  if (!strcmp(aFrametag, "WAVE_MAP")) {
298  return CPL_FRAME_LEVEL_FINAL;
299  }
300  if (!strcmp(aFrametag, "LSF_TABLE")) {
301  return CPL_FRAME_LEVEL_FINAL;
302  }
303  if (!strcmp(aFrametag, "LSF_RESIDUALS")) {
304  return CPL_FRAME_LEVEL_FINAL;
305  }
306  return CPL_FRAME_LEVEL_NONE;
307 } /* muse_wavecal_get_frame_level() */
308 
309 /*----------------------------------------------------------------------------*/
318 /*----------------------------------------------------------------------------*/
319 static muse_frame_mode
320 muse_wavecal_get_frame_mode(const char *aFrametag)
321 {
322  if (!aFrametag) {
323  return MUSE_FRAME_MODE_ALL;
324  }
325  if (!strcmp(aFrametag, "WAVECAL_TABLE")) {
326  return MUSE_FRAME_MODE_MASTER;
327  }
328  if (!strcmp(aFrametag, "WAVECAL_RESIDUALS")) {
329  return MUSE_FRAME_MODE_MASTER;
330  }
331  if (!strcmp(aFrametag, "ARC_RED_LAMP")) {
332  return MUSE_FRAME_MODE_SUBSET;
333  }
334  if (!strcmp(aFrametag, "ARC_RED")) {
335  return MUSE_FRAME_MODE_MASTER;
336  }
337  if (!strcmp(aFrametag, "ARC_RESAMPLED")) {
338  return MUSE_FRAME_MODE_MASTER;
339  }
340  if (!strcmp(aFrametag, "WAVE_MAP")) {
341  return MUSE_FRAME_MODE_MASTER;
342  }
343  if (!strcmp(aFrametag, "LSF_TABLE")) {
344  return MUSE_FRAME_MODE_MASTER;
345  }
346  if (!strcmp(aFrametag, "LSF_RESIDUALS")) {
347  return MUSE_FRAME_MODE_MASTER;
348  }
349  return MUSE_FRAME_MODE_ALL;
350 } /* muse_wavecal_get_frame_mode() */
351 
352 /*----------------------------------------------------------------------------*/
362 /*----------------------------------------------------------------------------*/
363 static int
364 muse_wavecal_create(cpl_plugin *aPlugin)
365 {
366  /* Check that the plugin is part of a valid recipe */
367  cpl_recipe *recipe;
368  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
369  recipe = (cpl_recipe *)aPlugin;
370  } else {
371  return -1;
372  }
373 
374  /* register the extended processing information (new FITS header creation, *
375  * getting of the frame level for a certain tag) */
377  muse_wavecal_new_recipeconfig(),
378  muse_wavecal_prepare_header,
379  muse_wavecal_get_frame_level,
380  muse_wavecal_get_frame_mode);
381 
382  /* XXX initialize timing in messages *
383  * since at least esorex is too stupid to turn it on, we have to do it */
385  cpl_msg_set_time_on();
386  }
387 
388  /* Create the parameter list in the cpl_recipe object */
389  recipe->parameters = cpl_parameterlist_new();
390  /* Fill the parameters list */
391  cpl_parameter *p;
392 
393  /* --nifu: IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel. */
394  p = cpl_parameter_new_range("muse.muse_wavecal.nifu",
395  CPL_TYPE_INT,
396  "IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel.",
397  "muse.muse_wavecal",
398  (int)0,
399  (int)-1,
400  (int)24);
401  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nifu");
402  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nifu");
403 
404  cpl_parameterlist_append(recipe->parameters, p);
405 
406  /* --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. */
407  p = cpl_parameter_new_value("muse.muse_wavecal.overscan",
408  CPL_TYPE_STRING,
409  "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.",
410  "muse.muse_wavecal",
411  (const char *)"vpoly");
412  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "overscan");
413  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "overscan");
414 
415  cpl_parameterlist_append(recipe->parameters, p);
416 
417  /* --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"). */
418  p = cpl_parameter_new_value("muse.muse_wavecal.ovscreject",
419  CPL_TYPE_STRING,
420  "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\").",
421  "muse.muse_wavecal",
422  (const char *)"dcr");
423  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscreject");
424  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscreject");
425 
426  cpl_parameterlist_append(recipe->parameters, p);
427 
428  /* --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. Has no effect for overscan="offset". */
429  p = cpl_parameter_new_value("muse.muse_wavecal.ovscsigma",
430  CPL_TYPE_DOUBLE,
431  "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. Has no effect for overscan=\"offset\".",
432  "muse.muse_wavecal",
433  (double)3.);
434  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscsigma");
435  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscsigma");
436 
437  cpl_parameterlist_append(recipe->parameters, p);
438 
439  /* --ovscignore: The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when computing statistics or fits. */
440  p = cpl_parameter_new_value("muse.muse_wavecal.ovscignore",
441  CPL_TYPE_INT,
442  "The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when computing statistics or fits.",
443  "muse.muse_wavecal",
444  (int)3);
445  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscignore");
446  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscignore");
447 
448  cpl_parameterlist_append(recipe->parameters, p);
449 
450  /* --combine: Type of lampwise image combination to use. */
451  p = cpl_parameter_new_enum("muse.muse_wavecal.combine",
452  CPL_TYPE_STRING,
453  "Type of lampwise image combination to use.",
454  "muse.muse_wavecal",
455  (const char *)"sigclip",
456  4,
457  (const char *)"average",
458  (const char *)"median",
459  (const char *)"minmax",
460  (const char *)"sigclip");
461  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "combine");
462  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "combine");
463 
464  cpl_parameterlist_append(recipe->parameters, p);
465 
466  /* --lampwise: Identify and measure the arc emission lines on images separately for each lamp setup. */
467  p = cpl_parameter_new_value("muse.muse_wavecal.lampwise",
468  CPL_TYPE_BOOL,
469  "Identify and measure the arc emission lines on images separately for each lamp setup.",
470  "muse.muse_wavecal",
471  (int)TRUE);
472  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lampwise");
473  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lampwise");
474 
475  cpl_parameterlist_append(recipe->parameters, p);
476 
477  /* --sigma: Sigma level used to detect arc emission lines above the median background level in the S/N image of the central column of each slice */
478  p = cpl_parameter_new_value("muse.muse_wavecal.sigma",
479  CPL_TYPE_DOUBLE,
480  "Sigma level used to detect arc emission lines above the median background level in the S/N image of the central column of each slice",
481  "muse.muse_wavecal",
482  (double)1.0);
483  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "sigma");
484  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sigma");
485 
486  cpl_parameterlist_append(recipe->parameters, p);
487 
488  /* --dres: The allowed range of resolutions for pattern matching (of detected arc lines to line list) in fractions relative to the expected value */
489  p = cpl_parameter_new_value("muse.muse_wavecal.dres",
490  CPL_TYPE_DOUBLE,
491  "The allowed range of resolutions for pattern matching (of detected arc lines to line list) in fractions relative to the expected value",
492  "muse.muse_wavecal",
493  (double)0.05);
494  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "dres");
495  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dres");
496 
497  cpl_parameterlist_append(recipe->parameters, p);
498 
499  /* --tolerance: Tolerance for pattern matching (of detected arc lines to line list) */
500  p = cpl_parameter_new_value("muse.muse_wavecal.tolerance",
501  CPL_TYPE_DOUBLE,
502  "Tolerance for pattern matching (of detected arc lines to line list)",
503  "muse.muse_wavecal",
504  (double)0.1);
505  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "tolerance");
506  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "tolerance");
507 
508  cpl_parameterlist_append(recipe->parameters, p);
509 
510  /* --xorder: Order of the polynomial for the horizontal curvature within each slice */
511  p = cpl_parameter_new_value("muse.muse_wavecal.xorder",
512  CPL_TYPE_INT,
513  "Order of the polynomial for the horizontal curvature within each slice",
514  "muse.muse_wavecal",
515  (int)2);
516  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "xorder");
517  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xorder");
518 
519  cpl_parameterlist_append(recipe->parameters, p);
520 
521  /* --yorder: Order of the polynomial used to fit the dispersion relation */
522  p = cpl_parameter_new_value("muse.muse_wavecal.yorder",
523  CPL_TYPE_INT,
524  "Order of the polynomial used to fit the dispersion relation",
525  "muse.muse_wavecal",
526  (int)6);
527  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "yorder");
528  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "yorder");
529 
530  cpl_parameterlist_append(recipe->parameters, p);
531 
532  /* --linesigma: Sigma level for iterative rejection of deviant fits for each arc line within each slice, a negative value means to use the default (2.5). */
533  p = cpl_parameter_new_value("muse.muse_wavecal.linesigma",
534  CPL_TYPE_DOUBLE,
535  "Sigma level for iterative rejection of deviant fits for each arc line within each slice, a negative value means to use the default (2.5).",
536  "muse.muse_wavecal",
537  (double)-1.0);
538  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "linesigma");
539  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "linesigma");
540 
541  cpl_parameterlist_append(recipe->parameters, p);
542 
543  /* --residuals: Create a table containing residuals of the fits to the data of all arc lines. This is useful to assess the quality of the wavelength solution in detail. */
544  p = cpl_parameter_new_value("muse.muse_wavecal.residuals",
545  CPL_TYPE_BOOL,
546  "Create a table containing residuals of the fits to the data of all arc lines. This is useful to assess the quality of the wavelength solution in detail.",
547  "muse.muse_wavecal",
548  (int)FALSE);
549  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "residuals");
550  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "residuals");
551 
552  cpl_parameterlist_append(recipe->parameters, p);
553 
554  /* --fitsigma: Sigma level for iterative rejection of deviant datapoints during the final polynomial wavelength solution within each slice, a negative value means to use the default (3.0). */
555  p = cpl_parameter_new_value("muse.muse_wavecal.fitsigma",
556  CPL_TYPE_DOUBLE,
557  "Sigma level for iterative rejection of deviant datapoints during the final polynomial wavelength solution within each slice, a negative value means to use the default (3.0).",
558  "muse.muse_wavecal",
559  (double)-1.0);
560  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "fitsigma");
561  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fitsigma");
562 
563  cpl_parameterlist_append(recipe->parameters, p);
564 
565  /* --fitweighting: Type of weighting to use in the final polynomial wavelength solution fit, using centroiding error estimate and/or scatter of each single line as estimates of its accuracy. */
566  p = cpl_parameter_new_enum("muse.muse_wavecal.fitweighting",
567  CPL_TYPE_STRING,
568  "Type of weighting to use in the final polynomial wavelength solution fit, using centroiding error estimate and/or scatter of each single line as estimates of its accuracy.",
569  "muse.muse_wavecal",
570  (const char *)"cerrscatter",
571  4,
572  (const char *)"uniform",
573  (const char *)"cerr",
574  (const char *)"scatter",
575  (const char *)"cerrscatter");
576  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "fitweighting");
577  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fitweighting");
578 
579  cpl_parameterlist_append(recipe->parameters, p);
580 
581  /* --resample: Resample the input arc images onto 2D images for a visual check using tracing and wavelength calibration solutions. Note that the image produced will show small wiggles even when the calibration was successful! */
582  p = cpl_parameter_new_value("muse.muse_wavecal.resample",
583  CPL_TYPE_BOOL,
584  "Resample the input arc images onto 2D images for a visual check using tracing and wavelength calibration solutions. Note that the image produced will show small wiggles even when the calibration was successful!",
585  "muse.muse_wavecal",
586  (int)FALSE);
587  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "resample");
588  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "resample");
589 
590  cpl_parameterlist_append(recipe->parameters, p);
591 
592  /* --wavemap: Create a wavelength map of the input images */
593  p = cpl_parameter_new_value("muse.muse_wavecal.wavemap",
594  CPL_TYPE_BOOL,
595  "Create a wavelength map of the input images",
596  "muse.muse_wavecal",
597  (int)FALSE);
598  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "wavemap");
599  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wavemap");
600 
601  cpl_parameterlist_append(recipe->parameters, p);
602 
603  /* --lsf: Fit the line spread function for each slice and save the result in the output LSF_TABLE. */
604  p = cpl_parameter_new_value("muse.muse_wavecal.lsf",
605  CPL_TYPE_BOOL,
606  "Fit the line spread function for each slice and save the result in the output LSF_TABLE.",
607  "muse.muse_wavecal",
608  (int)FALSE);
609  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lsf");
610  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lsf");
611 
612  cpl_parameterlist_append(recipe->parameters, p);
613 
614  /* --lsf-residuals: Store the residual pixel table after the LSF fit. */
615  p = cpl_parameter_new_value("muse.muse_wavecal.lsf-residuals",
616  CPL_TYPE_BOOL,
617  "Store the residual pixel table after the LSF fit.",
618  "muse.muse_wavecal",
619  (int)FALSE);
620  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lsf-residuals");
621  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lsf-residuals");
622 
623  cpl_parameterlist_append(recipe->parameters, p);
624 
625  return 0;
626 } /* muse_wavecal_create() */
627 
628 /*----------------------------------------------------------------------------*/
639 /*----------------------------------------------------------------------------*/
640 static int
641 muse_wavecal_params_fill(muse_wavecal_params_t *aParams, cpl_parameterlist *aParameters)
642 {
643  cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
644  cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
645  cpl_parameter *p;
646 
647  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.nifu");
648  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
649  aParams->nifu = cpl_parameter_get_int(p);
650 
651  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.overscan");
652  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
653  aParams->overscan = cpl_parameter_get_string(p);
654 
655  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.ovscreject");
656  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
657  aParams->ovscreject = cpl_parameter_get_string(p);
658 
659  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.ovscsigma");
660  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
661  aParams->ovscsigma = cpl_parameter_get_double(p);
662 
663  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.ovscignore");
664  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
665  aParams->ovscignore = cpl_parameter_get_int(p);
666 
667  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.combine");
668  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
669  aParams->combine_s = cpl_parameter_get_string(p);
670  aParams->combine =
671  (!strcasecmp(aParams->combine_s, "average")) ? MUSE_WAVECAL_PARAM_COMBINE_AVERAGE :
672  (!strcasecmp(aParams->combine_s, "median")) ? MUSE_WAVECAL_PARAM_COMBINE_MEDIAN :
673  (!strcasecmp(aParams->combine_s, "minmax")) ? MUSE_WAVECAL_PARAM_COMBINE_MINMAX :
674  (!strcasecmp(aParams->combine_s, "sigclip")) ? MUSE_WAVECAL_PARAM_COMBINE_SIGCLIP :
675  MUSE_WAVECAL_PARAM_COMBINE_INVALID_VALUE;
676  cpl_ensure_code(aParams->combine != MUSE_WAVECAL_PARAM_COMBINE_INVALID_VALUE,
677  CPL_ERROR_ILLEGAL_INPUT);
678 
679  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.lampwise");
680  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
681  aParams->lampwise = cpl_parameter_get_bool(p);
682 
683  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.sigma");
684  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
685  aParams->sigma = cpl_parameter_get_double(p);
686 
687  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.dres");
688  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
689  aParams->dres = cpl_parameter_get_double(p);
690 
691  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.tolerance");
692  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
693  aParams->tolerance = cpl_parameter_get_double(p);
694 
695  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.xorder");
696  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
697  aParams->xorder = cpl_parameter_get_int(p);
698 
699  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.yorder");
700  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
701  aParams->yorder = cpl_parameter_get_int(p);
702 
703  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.linesigma");
704  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
705  aParams->linesigma = cpl_parameter_get_double(p);
706 
707  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.residuals");
708  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
709  aParams->residuals = cpl_parameter_get_bool(p);
710 
711  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.fitsigma");
712  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
713  aParams->fitsigma = cpl_parameter_get_double(p);
714 
715  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.fitweighting");
716  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
717  aParams->fitweighting_s = cpl_parameter_get_string(p);
718  aParams->fitweighting =
719  (!strcasecmp(aParams->fitweighting_s, "uniform")) ? MUSE_WAVECAL_PARAM_FITWEIGHTING_UNIFORM :
720  (!strcasecmp(aParams->fitweighting_s, "cerr")) ? MUSE_WAVECAL_PARAM_FITWEIGHTING_CERR :
721  (!strcasecmp(aParams->fitweighting_s, "scatter")) ? MUSE_WAVECAL_PARAM_FITWEIGHTING_SCATTER :
722  (!strcasecmp(aParams->fitweighting_s, "cerrscatter")) ? MUSE_WAVECAL_PARAM_FITWEIGHTING_CERRSCATTER :
723  MUSE_WAVECAL_PARAM_FITWEIGHTING_INVALID_VALUE;
724  cpl_ensure_code(aParams->fitweighting != MUSE_WAVECAL_PARAM_FITWEIGHTING_INVALID_VALUE,
725  CPL_ERROR_ILLEGAL_INPUT);
726 
727  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.resample");
728  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
729  aParams->resample = cpl_parameter_get_bool(p);
730 
731  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.wavemap");
732  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
733  aParams->wavemap = cpl_parameter_get_bool(p);
734 
735  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.lsf");
736  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
737  aParams->lsf = cpl_parameter_get_bool(p);
738 
739  p = cpl_parameterlist_find(aParameters, "muse.muse_wavecal.lsf-residuals");
740  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
741  aParams->lsf_residuals = cpl_parameter_get_bool(p);
742 
743  return 0;
744 } /* muse_wavecal_params_fill() */
745 
746 /*----------------------------------------------------------------------------*/
753 /*----------------------------------------------------------------------------*/
754 static int
755 muse_wavecal_exec(cpl_plugin *aPlugin)
756 {
757  if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
758  return -1;
759  }
760  cpl_recipe *recipe = (cpl_recipe *)aPlugin;
761  cpl_msg_set_threadid_on();
762 
763  cpl_frameset *usedframes = cpl_frameset_new(),
764  *outframes = cpl_frameset_new();
765  muse_wavecal_params_t params;
766  muse_wavecal_params_fill(&params, recipe->parameters);
767 
768  cpl_errorstate prestate = cpl_errorstate_get();
769 
770  if (params.nifu < -1 || params.nifu > kMuseNumIFUs) {
771  cpl_msg_error(__func__, "Please specify a valid IFU number (between 1 and "
772  "%d), 0 (to process all IFUs consecutively), or -1 (to "
773  "process all IFUs in parallel) using --nifu.", kMuseNumIFUs);
774  return -1;
775  } /* if invalid params.nifu */
776 
777  int rc = 0;
778  if (params.nifu > 0) {
779  muse_processing *proc = muse_processing_new("muse_wavecal",
780  recipe);
781  rc = muse_wavecal_compute(proc, &params);
782  cpl_frameset_join(usedframes, proc->usedFrames);
783  cpl_frameset_join(outframes, proc->outputFrames);
785  } else if (params.nifu < 0) { /* parallel processing */
786  int *rcs = cpl_calloc(kMuseNumIFUs, sizeof(int));
787  int nifu;
788  #pragma omp parallel for default(none) \
789  shared(outframes, params, rcs, recipe, usedframes)
790  for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
791  muse_processing *proc = muse_processing_new("muse_wavecal",
792  recipe);
793  muse_wavecal_params_t *pars = cpl_malloc(sizeof(muse_wavecal_params_t));
794  memcpy(pars, &params, sizeof(muse_wavecal_params_t));
795  pars->nifu = nifu;
796  int *rci = rcs + (nifu - 1);
797  *rci = muse_wavecal_compute(proc, pars);
798  if (rci && cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
799  *rci = 0;
800  }
801  cpl_free(pars);
802  #pragma omp critical(muse_processing_used_frames)
803  cpl_frameset_join(usedframes, proc->usedFrames);
804  #pragma omp critical(muse_processing_output_frames)
805  cpl_frameset_join(outframes, proc->outputFrames);
807  } /* for nifu */
808  /* non-parallel loop to propagate the "worst" return code; *
809  * since we only ever return -1, any non-zero code is propagated */
810  for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
811  if (rcs[nifu-1] != 0) {
812  rc = rcs[nifu-1];
813  } /* if */
814  } /* for nifu */
815  cpl_free(rcs);
816  } else { /* serial processing */
817  for (params.nifu = 1; params.nifu <= kMuseNumIFUs && !rc; params.nifu++) {
818  muse_processing *proc = muse_processing_new("muse_wavecal",
819  recipe);
820  rc = muse_wavecal_compute(proc, &params);
821  if (rc && cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
822  rc = 0;
823  }
824  cpl_frameset_join(usedframes, proc->usedFrames);
825  cpl_frameset_join(outframes, proc->outputFrames);
827  } /* for nifu */
828  } /* else */
829 
830  if (!cpl_errorstate_is_equal(prestate)) {
831  /* dump all errors from this recipe in chronological order */
832  cpl_errorstate_dump(prestate, CPL_FALSE, muse_cplerrorstate_dump_some);
833  /* reset message level to not get the same errors displayed again by esorex */
834  cpl_msg_set_level(CPL_MSG_INFO);
835  }
836  /* clean up duplicates in framesets of used and output frames */
839  /* to get esorex to see our classification (frame groups etc.), *
840  * replace the original frameset with the list of used frames *
841  * before appending product output frames */
842  /* keep the same pointer, so just erase all frames, not delete the frameset */
843  muse_cplframeset_erase_all(recipe->frames);
844  cpl_frameset_join(recipe->frames, usedframes);
845  cpl_frameset_join(recipe->frames, outframes);
846  cpl_frameset_delete(usedframes);
847  cpl_frameset_delete(outframes);
848  return rc;
849 } /* muse_wavecal_exec() */
850 
851 /*----------------------------------------------------------------------------*/
858 /*----------------------------------------------------------------------------*/
859 static int
860 muse_wavecal_destroy(cpl_plugin *aPlugin)
861 {
862  /* Get the recipe from the plugin */
863  cpl_recipe *recipe;
864  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
865  recipe = (cpl_recipe *)aPlugin;
866  } else {
867  return -1;
868  }
869 
870  /* Clean up */
871  cpl_parameterlist_delete(recipe->parameters);
873  return 0;
874 } /* muse_wavecal_destroy() */
875 
876 /*----------------------------------------------------------------------------*/
886 /*----------------------------------------------------------------------------*/
887 int
888 cpl_plugin_get_info(cpl_pluginlist *aList)
889 {
890  cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
891  cpl_plugin *plugin = &recipe->interface;
892 
893  char *helptext;
895  helptext = cpl_sprintf("%s%s", muse_wavecal_help,
896  muse_wavecal_help_esorex);
897  } else {
898  helptext = cpl_sprintf("%s", muse_wavecal_help);
899  }
900 
901  /* Initialize the CPL plugin stuff for this module */
902  cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
903  CPL_PLUGIN_TYPE_RECIPE,
904  "muse_wavecal",
905  "Detect arc emission lines and determine the wavelength solution, and optionally the LSF, for each slice.",
906  helptext,
907  "Peter Weilbacher",
908  "usd-help@eso.org",
910  muse_wavecal_create,
911  muse_wavecal_exec,
912  muse_wavecal_destroy);
913  cpl_pluginlist_append(aList, plugin);
914  cpl_free(helptext);
915 
916  return 0;
917 } /* cpl_plugin_get_info() */
918 
void muse_processing_delete(muse_processing *aProcessing)
Free the muse_processing structure.
double fitsigma
Sigma level for iterative rejection of deviant datapoints during the final polynomial wavelength solu...
double linesigma
Sigma level for iterative rejection of deviant fits for each arc line within each slice...
const char * ovscreject
This influences how values are rejected when computing overscan statistics. Either no rejection at al...
double ovscsigma
If the deviation of mean overscan levels between a raw input image and the reference image is higher ...
muse_cplframework_type muse_cplframework(void)
Return the CPL framework the recipe is run under.
int ovscignore
The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when com...
double dres
The allowed range of resolutions for pattern matching (of detected arc lines to line list) in fractio...
int lsf
Fit the line spread function for each slice and save the result in the output LSF_TABLE.
const char * muse_get_license(void)
Get the pipeline copyright and license.
Definition: muse_utils.c:80
muse_processing * muse_processing_new(const char *aRecipeName, cpl_recipe *aRecipe)
Create a new processing structure.
muse_frame_mode
int nifu
IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in ...
const char * overscan
If this is "none", stop when detecting discrepant overscan levels (see ovscsigma), for "offset" it assumes that the mean overscan level represents the real offset in the bias levels of the exposures involved, and adjusts the data accordingly; for "vpoly", a polynomial is fit to the vertical overscan and subtracted from the whole quadrant.
cpl_frameset * outputFrames
void muse_cplerrorstate_dump_some(unsigned aCurrent, unsigned aFirst, unsigned aLast)
Dump some CPL errors.
int wavemap
Create a wavelength map of the input images.
int lampwise
Identify and measure the arc emission lines on images separately for each lamp setup.
int residuals
Create a table containing residuals of the fits to the data of all arc lines. This is useful to asses...
void muse_processinginfo_delete(cpl_recipe *)
Clear all information from the processing info and from the recipe config.
int resample
Resample the input arc images onto 2D images for a visual check using tracing and wavelength calibrat...
int yorder
Order of the polynomial used to fit the dispersion relation.
int lsf_residuals
Store the residual pixel table after the LSF fit.
cpl_error_code muse_cplframeset_erase_duplicate(cpl_frameset *aFrames)
Erase all duplicate frames from a frameset.
cpl_error_code muse_cplframeset_erase_all(cpl_frameset *aFrames)
Erase all frames in a frameset.
int fitweighting
Type of weighting to use in the final polynomial wavelength solution fit, using centroiding error est...
const char * combine_s
Type of lampwise image combination to use. (as string)
void muse_processinginfo_register(cpl_recipe *, cpl_recipeconfig *, muse_processing_prepare_header_func *, muse_processing_get_frame_level_func *, muse_processing_get_frame_mode_func *)
Register extended functionalities for MUSE recipes.
int combine
Type of lampwise image combination to use.
Structure to hold the parameters of the muse_wavecal recipe.
double tolerance
Tolerance for pattern matching (of detected arc lines to line list)
cpl_frameset * usedFrames
const char * fitweighting_s
Type of weighting to use in the final polynomial wavelength solution fit, using centroiding error est...
double sigma
Sigma level used to detect arc emission lines above the median background level in the S/N image of t...
int xorder
Order of the polynomial for the horizontal curvature within each slice.
cpl_error_code muse_processing_prepare_property(cpl_propertylist *, const char *, cpl_type, const char *)
Prepare and check the specified property.