MUSE Pipeline Reference Manual  1.0.2
muse_twilight_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_twilight_z.h" /* in turn includes muse.h */
36 
37 /*----------------------------------------------------------------------------*/
82 /*----------------------------------------------------------------------------*/
85 /*----------------------------------------------------------------------------*
86  * Static variables *
87  *----------------------------------------------------------------------------*/
88 static const char *muse_twilight_help =
89  "Processing first 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&), converts the images from adu to count, subtracts the dark, divides by the flat-field and combines all the exposures using input parameters. 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 from the master sky-flat. These pixel tables are then cut in wavelength using the --lambdamin and --lambdamax parameters. The integrated flux in each IFU is computed as the sum of the data in the pixel table, and saved in the header, to be used later as estimate for the relative throughput of each IFU. The pixel tables of all IFUs are then merged, using the integrated fluxes as inverse scaling factors, and a cube is reconstructed from the merged dataset, using given parameters. A white-light image is created from the cube. This skyflat cube is then saved to disk, with the white-light image as one extension. To construct a smooth 3D illumination correction, the cube is post-processed in the following way: the white-light image is used to create a mask of the illuminated area. From this area, the optional vignetting mask is removed. The smoothing is then computed for each plane of the cube: the illuminated area is smoothed (by a 5x7 median filter), normalized, fit with a 2D polynomial (of given polynomial orders), and normalized again. A smooth white image is then created by collapsing the smooth cube. If a vignetting mask was given, the corner area given by the mask is used to compute a 2D correction for the vignetted area: the original unsmoothed white-light image is corrected for large scale gradients by dividing it with the smooth white image. The residuals in the corner area then smoothed using input parameters. This smoothed vignetting correction is the multiplied onto each plane of the smooth cube, normalizing each plane again. This twilight cube is then saved to disk.";
90 
91 static const char *muse_twilight_help_esorex =
92  "\n\nInput frames for raw frame tag \"SKYFLAT\":\n"
93  "\n Frame tag Type Req #Fr Description"
94  "\n -------------------- ---- --- --- ------------"
95  "\n SKYFLAT raw Y >=3 Raw twilight skyflat"
96  "\n MASTER_BIAS calib Y 1 Master bias"
97  "\n MASTER_DARK calib . 1 Master dark"
98  "\n MASTER_FLAT calib Y 1 Master flat"
99  "\n BADPIX_TABLE calib . 1 Known bad pixels"
100  "\n TRACE_TABLE calib Y 1 Tracing table for all slices"
101  "\n WAVECAL_TABLE calib Y 1 Wavelength calibration table"
102  "\n GEOMETRY_TABLE calib Y 1 Relative positions of the slices in the field of view"
103  "\n VIGNETTING_MASK calib . 1 Mask to mark vignetted regions in the MUSE field of view"
104  "\n\nProduct frames for raw frame tag \"SKYFLAT\":\n"
105  "\n Frame tag Level Description"
106  "\n -------------------- -------- ------------"
107  "\n DATACUBE_SKYFLAT final Cube of combined twilight skyflat exposures"
108  "\n TWILIGHT_CUBE final Smoothed cube of twilight sky";
109 
110 /*----------------------------------------------------------------------------*/
118 /*----------------------------------------------------------------------------*/
119 static cpl_recipeconfig *
120 muse_twilight_new_recipeconfig(void)
121 {
122  cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
123  const char *tag;
124 
125  tag = "SKYFLAT";
126  cpl_recipeconfig_set_tag(recipeconfig, tag, 3, -1);
127  cpl_recipeconfig_set_input(recipeconfig, tag, "MASTER_BIAS", 1, 1);
128  cpl_recipeconfig_set_input(recipeconfig, tag, "MASTER_DARK", -1, 1);
129  cpl_recipeconfig_set_input(recipeconfig, tag, "MASTER_FLAT", 1, 1);
130  cpl_recipeconfig_set_input(recipeconfig, tag, "BADPIX_TABLE", -1, 1);
131  cpl_recipeconfig_set_input(recipeconfig, tag, "TRACE_TABLE", 1, 1);
132  cpl_recipeconfig_set_input(recipeconfig, tag, "WAVECAL_TABLE", 1, 1);
133  cpl_recipeconfig_set_input(recipeconfig, tag, "GEOMETRY_TABLE", 1, 1);
134  cpl_recipeconfig_set_input(recipeconfig, tag, "VIGNETTING_MASK", -1, 1);
135  cpl_recipeconfig_set_output(recipeconfig, tag, "DATACUBE_SKYFLAT");
136  cpl_recipeconfig_set_output(recipeconfig, tag, "TWILIGHT_CUBE");
137 
138  return recipeconfig;
139 } /* muse_twilight_new_recipeconfig() */
140 
141 /*----------------------------------------------------------------------------*/
151 /*----------------------------------------------------------------------------*/
152 static cpl_error_code
153 muse_twilight_prepare_header(const char *aFrametag, cpl_propertylist *aHeader)
154 {
155  cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
156  cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
157  if (!strcmp(aFrametag, "DATACUBE_SKYFLAT")) {
158  muse_processing_prepare_property(aHeader, "ESO QC TWILIGHT[0-9]+ INPUT[0-9]+ MEDIAN",
159  CPL_TYPE_FLOAT,
160  "Median value of raw exposure i of IFU m in input list");
161  muse_processing_prepare_property(aHeader, "ESO QC TWILIGHT[0-9]+ INPUT[0-9]+ MEAN",
162  CPL_TYPE_FLOAT,
163  "Mean value of raw exposure i of IFU m in input list");
164  muse_processing_prepare_property(aHeader, "ESO QC TWILIGHT[0-9]+ INPUT[0-9]+ STDEV",
165  CPL_TYPE_FLOAT,
166  "Standard deviation of raw exposure i of IFU m in input list");
167  muse_processing_prepare_property(aHeader, "ESO QC TWILIGHT[0-9]+ INPUT[0-9]+ MIN",
168  CPL_TYPE_FLOAT,
169  "Minimum value of raw exposure i of IFU m in input list");
170  muse_processing_prepare_property(aHeader, "ESO QC TWILIGHT[0-9]+ INPUT[0-9]+ MAX",
171  CPL_TYPE_FLOAT,
172  "Maximum value of raw exposure i of IFU m in input list");
173  muse_processing_prepare_property(aHeader, "ESO QC TWILIGHT[0-9]+ INPUT[0-9]+ NSATURATED",
174  CPL_TYPE_INT,
175  "Number of saturated pixels in raw exposure i of IFU m in input list");
176  muse_processing_prepare_property(aHeader, "ESO QC TWILIGHT[0-9]+ MASTER MEDIAN",
177  CPL_TYPE_FLOAT,
178  "Median value of the combined exposures in IFU m");
179  muse_processing_prepare_property(aHeader, "ESO QC TWILIGHT[0-9]+ MASTER MEAN",
180  CPL_TYPE_FLOAT,
181  "Mean value of the combined exposures in IFU m");
182  muse_processing_prepare_property(aHeader, "ESO QC TWILIGHT[0-9]+ MASTER STDEV",
183  CPL_TYPE_FLOAT,
184  "Standard deviation of the combined exposures in IFU m");
185  muse_processing_prepare_property(aHeader, "ESO QC TWILIGHT[0-9]+ MASTER MIN",
186  CPL_TYPE_FLOAT,
187  "Minimum value of the combined exposures in IFU m");
188  muse_processing_prepare_property(aHeader, "ESO QC TWILIGHT[0-9]+ MASTER MAX",
189  CPL_TYPE_FLOAT,
190  "Maximum value of the combined exposures in IFU m");
191  muse_processing_prepare_property(aHeader, "ESO QC TWILIGHT[0-9]+ MASTER INTFLUX",
192  CPL_TYPE_FLOAT,
193  "Flux integrated over the whole CCD of the combined exposures of IFU m");
194  muse_processing_prepare_property(aHeader, "ESO QC TWILIGHT[0-9]+ INTFLUX",
195  CPL_TYPE_FLOAT,
196  "Flux integrated over all slices of IFU m. Computed using the pixel table of the exposure.");
197  } else if (!strcmp(aFrametag, "TWILIGHT_CUBE")) {
198  } else {
199  cpl_msg_warning(__func__, "Frame tag %s is not defined", aFrametag);
200  return CPL_ERROR_ILLEGAL_INPUT;
201  }
202  return CPL_ERROR_NONE;
203 } /* muse_twilight_prepare_header() */
204 
205 /*----------------------------------------------------------------------------*/
214 /*----------------------------------------------------------------------------*/
215 static cpl_frame_level
216 muse_twilight_get_frame_level(const char *aFrametag)
217 {
218  if (!aFrametag) {
219  return CPL_FRAME_LEVEL_NONE;
220  }
221  if (!strcmp(aFrametag, "DATACUBE_SKYFLAT")) {
222  return CPL_FRAME_LEVEL_FINAL;
223  }
224  if (!strcmp(aFrametag, "TWILIGHT_CUBE")) {
225  return CPL_FRAME_LEVEL_FINAL;
226  }
227  return CPL_FRAME_LEVEL_NONE;
228 } /* muse_twilight_get_frame_level() */
229 
230 /*----------------------------------------------------------------------------*/
239 /*----------------------------------------------------------------------------*/
240 static muse_frame_mode
241 muse_twilight_get_frame_mode(const char *aFrametag)
242 {
243  if (!aFrametag) {
244  return MUSE_FRAME_MODE_ALL;
245  }
246  if (!strcmp(aFrametag, "DATACUBE_SKYFLAT")) {
247  return MUSE_FRAME_MODE_MASTER;
248  }
249  if (!strcmp(aFrametag, "TWILIGHT_CUBE")) {
250  return MUSE_FRAME_MODE_MASTER;
251  }
252  return MUSE_FRAME_MODE_ALL;
253 } /* muse_twilight_get_frame_mode() */
254 
255 /*----------------------------------------------------------------------------*/
265 /*----------------------------------------------------------------------------*/
266 static int
267 muse_twilight_create(cpl_plugin *aPlugin)
268 {
269  /* Check that the plugin is part of a valid recipe */
270  cpl_recipe *recipe;
271  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
272  recipe = (cpl_recipe *)aPlugin;
273  } else {
274  return -1;
275  }
276 
277  /* register the extended processing information (new FITS header creation, *
278  * getting of the frame level for a certain tag) */
280  muse_twilight_new_recipeconfig(),
281  muse_twilight_prepare_header,
282  muse_twilight_get_frame_level,
283  muse_twilight_get_frame_mode);
284 
285  /* XXX initialize timing in messages *
286  * since at least esorex is too stupid to turn it on, we have to do it */
288  cpl_msg_set_time_on();
289  }
290 
291  /* Create the parameter list in the cpl_recipe object */
292  recipe->parameters = cpl_parameterlist_new();
293  /* Fill the parameters list */
294  cpl_parameter *p;
295 
296  /* --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. */
297  p = cpl_parameter_new_value("muse.muse_twilight.overscan",
298  CPL_TYPE_STRING,
299  "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.",
300  "muse.muse_twilight",
301  (const char *)"vpoly");
302  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "overscan");
303  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "overscan");
304 
305  cpl_parameterlist_append(recipe->parameters, p);
306 
307  /* --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"). */
308  p = cpl_parameter_new_value("muse.muse_twilight.ovscreject",
309  CPL_TYPE_STRING,
310  "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\").",
311  "muse.muse_twilight",
312  (const char *)"dcr");
313  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscreject");
314  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscreject");
315 
316  cpl_parameterlist_append(recipe->parameters, p);
317 
318  /* --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". */
319  p = cpl_parameter_new_value("muse.muse_twilight.ovscsigma",
320  CPL_TYPE_DOUBLE,
321  "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\".",
322  "muse.muse_twilight",
323  (double)30.);
324  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscsigma");
325  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscsigma");
326 
327  cpl_parameterlist_append(recipe->parameters, p);
328 
329  /* --ovscignore: The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when computing statistics or fits. */
330  p = cpl_parameter_new_value("muse.muse_twilight.ovscignore",
331  CPL_TYPE_INT,
332  "The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when computing statistics or fits.",
333  "muse.muse_twilight",
334  (int)3);
335  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscignore");
336  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscignore");
337 
338  cpl_parameterlist_append(recipe->parameters, p);
339 
340  /* --combine: Type of combination to use */
341  p = cpl_parameter_new_enum("muse.muse_twilight.combine",
342  CPL_TYPE_STRING,
343  "Type of combination to use",
344  "muse.muse_twilight",
345  (const char *)"sigclip",
346  4,
347  (const char *)"average",
348  (const char *)"median",
349  (const char *)"minmax",
350  (const char *)"sigclip");
351  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "combine");
352  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "combine");
353 
354  cpl_parameterlist_append(recipe->parameters, p);
355 
356  /* --nlow: Number of minimum pixels to reject with minmax */
357  p = cpl_parameter_new_value("muse.muse_twilight.nlow",
358  CPL_TYPE_INT,
359  "Number of minimum pixels to reject with minmax",
360  "muse.muse_twilight",
361  (int)1);
362  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nlow");
363  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nlow");
364 
365  cpl_parameterlist_append(recipe->parameters, p);
366 
367  /* --nhigh: Number of maximum pixels to reject with minmax */
368  p = cpl_parameter_new_value("muse.muse_twilight.nhigh",
369  CPL_TYPE_INT,
370  "Number of maximum pixels to reject with minmax",
371  "muse.muse_twilight",
372  (int)1);
373  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nhigh");
374  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nhigh");
375 
376  cpl_parameterlist_append(recipe->parameters, p);
377 
378  /* --nkeep: Number of pixels to keep with minmax */
379  p = cpl_parameter_new_value("muse.muse_twilight.nkeep",
380  CPL_TYPE_INT,
381  "Number of pixels to keep with minmax",
382  "muse.muse_twilight",
383  (int)1);
384  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nkeep");
385  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nkeep");
386 
387  cpl_parameterlist_append(recipe->parameters, p);
388 
389  /* --lsigma: Low sigma for pixel rejection with sigclip */
390  p = cpl_parameter_new_value("muse.muse_twilight.lsigma",
391  CPL_TYPE_DOUBLE,
392  "Low sigma for pixel rejection with sigclip",
393  "muse.muse_twilight",
394  (double)3);
395  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lsigma");
396  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lsigma");
397 
398  cpl_parameterlist_append(recipe->parameters, p);
399 
400  /* --hsigma: High sigma for pixel rejection with sigclip */
401  p = cpl_parameter_new_value("muse.muse_twilight.hsigma",
402  CPL_TYPE_DOUBLE,
403  "High sigma for pixel rejection with sigclip",
404  "muse.muse_twilight",
405  (double)3);
406  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "hsigma");
407  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "hsigma");
408 
409  cpl_parameterlist_append(recipe->parameters, p);
410 
411  /* --scale: Scale the individual images to a common exposure time before combining them. */
412  p = cpl_parameter_new_value("muse.muse_twilight.scale",
413  CPL_TYPE_BOOL,
414  "Scale the individual images to a common exposure time before combining them.",
415  "muse.muse_twilight",
416  (int)FALSE);
417  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "scale");
418  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scale");
419 
420  cpl_parameterlist_append(recipe->parameters, p);
421 
422  /* --resample: The resampling technique to use for the final output cube. */
423  p = cpl_parameter_new_enum("muse.muse_twilight.resample",
424  CPL_TYPE_STRING,
425  "The resampling technique to use for the final output cube.",
426  "muse.muse_twilight",
427  (const char *)"drizzle",
428  6,
429  (const char *)"nearest",
430  (const char *)"linear",
431  (const char *)"quadratic",
432  (const char *)"renka",
433  (const char *)"drizzle",
434  (const char *)"lanczos");
435  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "resample");
436  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "resample");
437 
438  cpl_parameterlist_append(recipe->parameters, p);
439 
440  /* --crtype: Type of statistics used for detection of cosmic rays during final resampling. "iraf" uses the variance information, "mean" uses standard (mean/stdev) statistics, "median" uses median and the median median of the absolute median deviation. */
441  p = cpl_parameter_new_enum("muse.muse_twilight.crtype",
442  CPL_TYPE_STRING,
443  "Type of statistics used for detection of cosmic rays during final resampling. \"iraf\" uses the variance information, \"mean\" uses standard (mean/stdev) statistics, \"median\" uses median and the median median of the absolute median deviation.",
444  "muse.muse_twilight",
445  (const char *)"median",
446  3,
447  (const char *)"iraf",
448  (const char *)"mean",
449  (const char *)"median");
450  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "crtype");
451  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "crtype");
452 
453  cpl_parameterlist_append(recipe->parameters, p);
454 
455  /* --crsigma: Sigma rejection factor to use for cosmic ray rejection during final resampling. A zero or negative value switches cosmic ray rejection off. */
456  p = cpl_parameter_new_value("muse.muse_twilight.crsigma",
457  CPL_TYPE_DOUBLE,
458  "Sigma rejection factor to use for cosmic ray rejection during final resampling. A zero or negative value switches cosmic ray rejection off.",
459  "muse.muse_twilight",
460  (double)50.);
461  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "crsigma");
462  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "crsigma");
463 
464  cpl_parameterlist_append(recipe->parameters, p);
465 
466  /* --lambdamin: Minimum wavelength for twilight reconstruction. */
467  p = cpl_parameter_new_value("muse.muse_twilight.lambdamin",
468  CPL_TYPE_DOUBLE,
469  "Minimum wavelength for twilight reconstruction.",
470  "muse.muse_twilight",
471  (double)5000.);
472  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lambdamin");
473  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lambdamin");
474 
475  cpl_parameterlist_append(recipe->parameters, p);
476 
477  /* --lambdamax: Maximum wavelength for twilight reconstruction. */
478  p = cpl_parameter_new_value("muse.muse_twilight.lambdamax",
479  CPL_TYPE_DOUBLE,
480  "Maximum wavelength for twilight reconstruction.",
481  "muse.muse_twilight",
482  (double)9000.);
483  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lambdamax");
484  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lambdamax");
485 
486  cpl_parameterlist_append(recipe->parameters, p);
487 
488  /* --dlambda: Sampling for twilight reconstruction, this should result in planes of equal wavelength coverage. */
489  p = cpl_parameter_new_value("muse.muse_twilight.dlambda",
490  CPL_TYPE_DOUBLE,
491  "Sampling for twilight reconstruction, this should result in planes of equal wavelength coverage.",
492  "muse.muse_twilight",
493  (double)250.);
494  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "dlambda");
495  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dlambda");
496 
497  cpl_parameterlist_append(recipe->parameters, p);
498 
499  /* --xorder: Polynomial order to use in x direction to fit the full field of view. */
500  p = cpl_parameter_new_value("muse.muse_twilight.xorder",
501  CPL_TYPE_INT,
502  "Polynomial order to use in x direction to fit the full field of view.",
503  "muse.muse_twilight",
504  (int)2);
505  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "xorder");
506  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xorder");
507 
508  cpl_parameterlist_append(recipe->parameters, p);
509 
510  /* --yorder: Polynomial order to use in y direction to fit the full field of view. */
511  p = cpl_parameter_new_value("muse.muse_twilight.yorder",
512  CPL_TYPE_INT,
513  "Polynomial order to use in y direction to fit the full field of view.",
514  "muse.muse_twilight",
515  (int)2);
516  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "yorder");
517  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "yorder");
518 
519  cpl_parameterlist_append(recipe->parameters, p);
520 
521  /* --vignmaskedges: Pixels on edges stronger than this fraction in the normalized image are excluded from the fit to the vignetted area. Set to non-positive number to include them in the fit. */
522  p = cpl_parameter_new_value("muse.muse_twilight.vignmaskedges",
523  CPL_TYPE_DOUBLE,
524  "Pixels on edges stronger than this fraction in the normalized image are excluded from the fit to the vignetted area. Set to non-positive number to include them in the fit.",
525  "muse.muse_twilight",
526  (double)0.02);
527  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "vignmaskedges");
528  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "vignmaskedges");
529 
530  cpl_parameterlist_append(recipe->parameters, p);
531 
532  /* --vignsmooth: Type of smoothing to use for the vignetted region given by the VIGNETTING_MASK; gaussian uses (vignxpar + vignypar)/2 as FWHM. */
533  p = cpl_parameter_new_enum("muse.muse_twilight.vignsmooth",
534  CPL_TYPE_STRING,
535  "Type of smoothing to use for the vignetted region given by the VIGNETTING_MASK; gaussian uses (vignxpar + vignypar)/2 as FWHM.",
536  "muse.muse_twilight",
537  (const char *)"polyfit",
538  3,
539  (const char *)"polyfit",
540  (const char *)"gaussian",
541  (const char *)"median");
542  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "vignsmooth");
543  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "vignsmooth");
544 
545  cpl_parameterlist_append(recipe->parameters, p);
546 
547  /* --vignxpar: Parameter used by the vignetting smoothing: x order for polyfit (default, recommended 4), parameter that influences the FWHM for the gaussian (recommended: 10), or x dimension of median filter (recommended 5). */
548  p = cpl_parameter_new_value("muse.muse_twilight.vignxpar",
549  CPL_TYPE_INT,
550  "Parameter used by the vignetting smoothing: x order for polyfit (default, recommended 4), parameter that influences the FWHM for the gaussian (recommended: 10), or x dimension of median filter (recommended 5).",
551  "muse.muse_twilight",
552  (int)4);
553  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "vignxpar");
554  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "vignxpar");
555 
556  cpl_parameterlist_append(recipe->parameters, p);
557 
558  /* --vignypar: Parameter used by the vignetting smoothing: y order for polyfit (default, recommended 4), parameter that influences the FWHM for the gaussian (recommended: 10), or y dimension of median filter (recommended 5). */
559  p = cpl_parameter_new_value("muse.muse_twilight.vignypar",
560  CPL_TYPE_INT,
561  "Parameter used by the vignetting smoothing: y order for polyfit (default, recommended 4), parameter that influences the FWHM for the gaussian (recommended: 10), or y dimension of median filter (recommended 5).",
562  "muse.muse_twilight",
563  (int)4);
564  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "vignypar");
565  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "vignypar");
566 
567  cpl_parameterlist_append(recipe->parameters, p);
568 
569  return 0;
570 } /* muse_twilight_create() */
571 
572 /*----------------------------------------------------------------------------*/
583 /*----------------------------------------------------------------------------*/
584 static int
585 muse_twilight_params_fill(muse_twilight_params_t *aParams, cpl_parameterlist *aParameters)
586 {
587  cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
588  cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
589  cpl_parameter *p;
590 
591  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.overscan");
592  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
593  aParams->overscan = cpl_parameter_get_string(p);
594 
595  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.ovscreject");
596  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
597  aParams->ovscreject = cpl_parameter_get_string(p);
598 
599  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.ovscsigma");
600  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
601  aParams->ovscsigma = cpl_parameter_get_double(p);
602 
603  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.ovscignore");
604  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
605  aParams->ovscignore = cpl_parameter_get_int(p);
606 
607  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.combine");
608  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
609  aParams->combine_s = cpl_parameter_get_string(p);
610  aParams->combine =
611  (!strcasecmp(aParams->combine_s, "average")) ? MUSE_TWILIGHT_PARAM_COMBINE_AVERAGE :
612  (!strcasecmp(aParams->combine_s, "median")) ? MUSE_TWILIGHT_PARAM_COMBINE_MEDIAN :
613  (!strcasecmp(aParams->combine_s, "minmax")) ? MUSE_TWILIGHT_PARAM_COMBINE_MINMAX :
614  (!strcasecmp(aParams->combine_s, "sigclip")) ? MUSE_TWILIGHT_PARAM_COMBINE_SIGCLIP :
615  MUSE_TWILIGHT_PARAM_COMBINE_INVALID_VALUE;
616  cpl_ensure_code(aParams->combine != MUSE_TWILIGHT_PARAM_COMBINE_INVALID_VALUE,
617  CPL_ERROR_ILLEGAL_INPUT);
618 
619  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.nlow");
620  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
621  aParams->nlow = cpl_parameter_get_int(p);
622 
623  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.nhigh");
624  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
625  aParams->nhigh = cpl_parameter_get_int(p);
626 
627  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.nkeep");
628  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
629  aParams->nkeep = cpl_parameter_get_int(p);
630 
631  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.lsigma");
632  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
633  aParams->lsigma = cpl_parameter_get_double(p);
634 
635  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.hsigma");
636  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
637  aParams->hsigma = cpl_parameter_get_double(p);
638 
639  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.scale");
640  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
641  aParams->scale = cpl_parameter_get_bool(p);
642 
643  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.resample");
644  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
645  aParams->resample_s = cpl_parameter_get_string(p);
646  aParams->resample =
647  (!strcasecmp(aParams->resample_s, "nearest")) ? MUSE_TWILIGHT_PARAM_RESAMPLE_NEAREST :
648  (!strcasecmp(aParams->resample_s, "linear")) ? MUSE_TWILIGHT_PARAM_RESAMPLE_LINEAR :
649  (!strcasecmp(aParams->resample_s, "quadratic")) ? MUSE_TWILIGHT_PARAM_RESAMPLE_QUADRATIC :
650  (!strcasecmp(aParams->resample_s, "renka")) ? MUSE_TWILIGHT_PARAM_RESAMPLE_RENKA :
651  (!strcasecmp(aParams->resample_s, "drizzle")) ? MUSE_TWILIGHT_PARAM_RESAMPLE_DRIZZLE :
652  (!strcasecmp(aParams->resample_s, "lanczos")) ? MUSE_TWILIGHT_PARAM_RESAMPLE_LANCZOS :
653  MUSE_TWILIGHT_PARAM_RESAMPLE_INVALID_VALUE;
654  cpl_ensure_code(aParams->resample != MUSE_TWILIGHT_PARAM_RESAMPLE_INVALID_VALUE,
655  CPL_ERROR_ILLEGAL_INPUT);
656 
657  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.crtype");
658  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
659  aParams->crtype_s = cpl_parameter_get_string(p);
660  aParams->crtype =
661  (!strcasecmp(aParams->crtype_s, "iraf")) ? MUSE_TWILIGHT_PARAM_CRTYPE_IRAF :
662  (!strcasecmp(aParams->crtype_s, "mean")) ? MUSE_TWILIGHT_PARAM_CRTYPE_MEAN :
663  (!strcasecmp(aParams->crtype_s, "median")) ? MUSE_TWILIGHT_PARAM_CRTYPE_MEDIAN :
664  MUSE_TWILIGHT_PARAM_CRTYPE_INVALID_VALUE;
665  cpl_ensure_code(aParams->crtype != MUSE_TWILIGHT_PARAM_CRTYPE_INVALID_VALUE,
666  CPL_ERROR_ILLEGAL_INPUT);
667 
668  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.crsigma");
669  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
670  aParams->crsigma = cpl_parameter_get_double(p);
671 
672  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.lambdamin");
673  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
674  aParams->lambdamin = cpl_parameter_get_double(p);
675 
676  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.lambdamax");
677  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
678  aParams->lambdamax = cpl_parameter_get_double(p);
679 
680  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.dlambda");
681  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
682  aParams->dlambda = cpl_parameter_get_double(p);
683 
684  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.xorder");
685  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
686  aParams->xorder = cpl_parameter_get_int(p);
687 
688  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.yorder");
689  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
690  aParams->yorder = cpl_parameter_get_int(p);
691 
692  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.vignmaskedges");
693  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
694  aParams->vignmaskedges = cpl_parameter_get_double(p);
695 
696  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.vignsmooth");
697  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
698  aParams->vignsmooth_s = cpl_parameter_get_string(p);
699  aParams->vignsmooth =
700  (!strcasecmp(aParams->vignsmooth_s, "polyfit")) ? MUSE_TWILIGHT_PARAM_VIGNSMOOTH_POLYFIT :
701  (!strcasecmp(aParams->vignsmooth_s, "gaussian")) ? MUSE_TWILIGHT_PARAM_VIGNSMOOTH_GAUSSIAN :
702  (!strcasecmp(aParams->vignsmooth_s, "median")) ? MUSE_TWILIGHT_PARAM_VIGNSMOOTH_MEDIAN :
703  MUSE_TWILIGHT_PARAM_VIGNSMOOTH_INVALID_VALUE;
704  cpl_ensure_code(aParams->vignsmooth != MUSE_TWILIGHT_PARAM_VIGNSMOOTH_INVALID_VALUE,
705  CPL_ERROR_ILLEGAL_INPUT);
706 
707  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.vignxpar");
708  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
709  aParams->vignxpar = cpl_parameter_get_int(p);
710 
711  p = cpl_parameterlist_find(aParameters, "muse.muse_twilight.vignypar");
712  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
713  aParams->vignypar = cpl_parameter_get_int(p);
714 
715  return 0;
716 } /* muse_twilight_params_fill() */
717 
718 /*----------------------------------------------------------------------------*/
725 /*----------------------------------------------------------------------------*/
726 static int
727 muse_twilight_exec(cpl_plugin *aPlugin)
728 {
729  if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
730  return -1;
731  }
732  cpl_recipe *recipe = (cpl_recipe *)aPlugin;
733  cpl_msg_set_threadid_on();
734 
735  cpl_frameset *usedframes = cpl_frameset_new(),
736  *outframes = cpl_frameset_new();
737  muse_twilight_params_t params;
738  muse_twilight_params_fill(&params, recipe->parameters);
739 
740  cpl_errorstate prestate = cpl_errorstate_get();
741 
742  muse_processing *proc = muse_processing_new("muse_twilight",
743  recipe);
744  int rc = muse_twilight_compute(proc, &params);
745  cpl_frameset_join(usedframes, proc->usedframes);
746  cpl_frameset_join(outframes, proc->outframes);
748 
749  if (!cpl_errorstate_is_equal(prestate)) {
750  /* dump all errors from this recipe in chronological order */
751  cpl_errorstate_dump(prestate, CPL_FALSE, muse_cplerrorstate_dump_some);
752  /* reset message level to not get the same errors displayed again by esorex */
753  cpl_msg_set_level(CPL_MSG_INFO);
754  }
755  /* clean up duplicates in framesets of used and output frames */
758 
759  /* to get esorex to see our classification (frame groups etc.), *
760  * replace the original frameset with the list of used frames *
761  * before appending product output frames */
762  /* keep the same pointer, so just erase all frames, not delete the frameset */
763  muse_cplframeset_erase_all(recipe->frames);
764  cpl_frameset_join(recipe->frames, usedframes);
765  cpl_frameset_join(recipe->frames, outframes);
766  cpl_frameset_delete(usedframes);
767  cpl_frameset_delete(outframes);
768  return rc;
769 } /* muse_twilight_exec() */
770 
771 /*----------------------------------------------------------------------------*/
778 /*----------------------------------------------------------------------------*/
779 static int
780 muse_twilight_destroy(cpl_plugin *aPlugin)
781 {
782  /* Get the recipe from the plugin */
783  cpl_recipe *recipe;
784  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
785  recipe = (cpl_recipe *)aPlugin;
786  } else {
787  return -1;
788  }
789 
790  /* Clean up */
791  cpl_parameterlist_delete(recipe->parameters);
793  return 0;
794 } /* muse_twilight_destroy() */
795 
796 /*----------------------------------------------------------------------------*/
806 /*----------------------------------------------------------------------------*/
807 int
808 cpl_plugin_get_info(cpl_pluginlist *aList)
809 {
810  cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
811  cpl_plugin *plugin = &recipe->interface;
812 
813  char *helptext;
815  helptext = cpl_sprintf("%s%s", muse_twilight_help,
816  muse_twilight_help_esorex);
817  } else {
818  helptext = cpl_sprintf("%s", muse_twilight_help);
819  }
820 
821  /* Initialize the CPL plugin stuff for this module */
822  cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
823  CPL_PLUGIN_TYPE_RECIPE,
824  "muse_twilight",
825  "Combine several twilight skyflats into one cube, compute correction factors for each IFU, and create a smooth 3D illumination correction.",
826  helptext,
827  "Peter Weilbacher",
828  "usd-help@eso.org",
830  muse_twilight_create,
831  muse_twilight_exec,
832  muse_twilight_destroy);
833  cpl_pluginlist_append(aList, plugin);
834  cpl_free(helptext);
835 
836  return 0;
837 } /* cpl_plugin_get_info() */
838 
double crsigma
Sigma rejection factor to use for cosmic ray rejection during final resampling. A zero or negative va...
void muse_processing_delete(muse_processing *aProcessing)
Free the muse_processing structure.
const char * vignsmooth_s
Type of smoothing to use for the vignetted region given by the VIGNETTING_MASK; gaussian uses (vignxp...
int scale
Scale the individual images to a common exposure time before combining them.
double lsigma
Low sigma for pixel rejection with sigclip.
int nkeep
Number of pixels to keep with minmax.
muse_cplframework_type muse_cplframework(void)
Return the CPL framework the recipe is run under.
double ovscsigma
If the deviation of mean overscan levels between a raw input image and the reference image is higher ...
const char * crtype_s
Type of statistics used for detection of cosmic rays during final resampling. "iraf" uses the varianc...
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 * usedframes
muse_processing * muse_processing_new(const char *aName, cpl_recipe *aRecipe)
Create a new processing structure.
int nhigh
Number of maximum pixels to reject with minmax.
const char * muse_get_license(void)
Get the pipeline copyright and license.
Definition: muse_utils.c:84
int vignxpar
Parameter used by the vignetting smoothing: x order for polyfit (default, recommended 4)...
double vignmaskedges
Pixels on edges stronger than this fraction in the normalized image are excluded from the fit to the ...
muse_frame_mode
int vignypar
Parameter used by the vignetting smoothing: y order for polyfit (default, recommended 4)...
cpl_frameset * outframes
const char * combine_s
Type of combination to use (as string)
Structure to hold the parameters of the muse_twilight recipe.
double dlambda
Sampling for twilight reconstruction, this should result in planes of equal wavelength coverage...
int vignsmooth
Type of smoothing to use for the vignetted region given by the VIGNETTING_MASK; gaussian uses (vignxp...
int resample
The resampling technique to use for the final output cube.
void muse_cplerrorstate_dump_some(unsigned aCurrent, unsigned aFirst, unsigned aLast)
Dump some CPL errors.
double lambdamin
Minimum wavelength for twilight reconstruction.
void muse_processinginfo_delete(cpl_recipe *)
Clear all information from the processing info and from the recipe config.
int combine
Type of combination to use.
double hsigma
High sigma for pixel rejection with sigclip.
int yorder
Polynomial order to use in y direction to fit the full field of view.
int xorder
Polynomial order to use in x direction to fit the full field of view.
const char * ovscreject
This influences how values are rejected when computing overscan statistics. Either no rejection at al...
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.
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 ovscignore
The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when com...
double lambdamax
Maximum wavelength for twilight reconstruction.
int nlow
Number of minimum pixels to reject with minmax.
int crtype
Type of statistics used for detection of cosmic rays during final resampling. "iraf" uses the varianc...
cpl_error_code muse_processing_prepare_property(cpl_propertylist *, const char *, cpl_type, const char *)
Prepare and check the specified property.
const char * resample_s
The resampling technique to use for the final output cube. (as string)