MUSE Pipeline Reference Manual  2.1.1
muse_bias_z.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set sw=2 sts=2 et cin: */
3 /*
4  * This file is part of the MUSE Instrument Pipeline
5  * Copyright (C) 2005-2015 European Southern Observatory
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 /* This file was automatically generated */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 /*----------------------------------------------------------------------------*
29  * Includes *
30  *----------------------------------------------------------------------------*/
31 #include <string.h> /* strcmp(), strstr() */
32 #include <strings.h> /* strcasecmp() */
33 #include <cpl.h>
34 
35 #include "muse_bias_z.h" /* in turn includes muse.h */
36 
37 /*----------------------------------------------------------------------------*/
57 /*----------------------------------------------------------------------------*/
60 /*----------------------------------------------------------------------------*
61  * Static variables *
62  *----------------------------------------------------------------------------*/
63 static const char *muse_bias_help =
64  "This recipe combines several separate bias images into one master bias file. The master bias contains the combined pixel values, in adu, of the raw bias exposures, with respect to the image combination method used. Processing trims the raw data and records the overscan statistics, corrects the data levels using the overscan (if overscan is not \"none\") and combines the exposures using input parameters. The read-out noise is computed for each quadrant of the raw input images and stored as QC parameter. The variance extension is filled with an initial value accordingly, before image combination. Further QC statistics are computed on the output master bias. Additionally, bad columns are searched for and marked in the data quality extension.";
65 
66 static const char *muse_bias_help_esorex =
67  "\n\nInput frames for raw frame tag \"BIAS\":\n"
68  "\n Frame tag Type Req #Fr Description"
69  "\n -------------------- ---- --- --- ------------"
70  "\n BIAS raw Y >=3 Raw bias"
71  "\n BADPIX_TABLE calib . Known bad pixels"
72  "\n\nProduct frames for raw frame tag \"BIAS\":\n"
73  "\n Frame tag Level Description"
74  "\n -------------------- -------- ------------"
75  "\n MASTER_BIAS final Master bias";
76 
77 /*----------------------------------------------------------------------------*/
85 /*----------------------------------------------------------------------------*/
86 static cpl_recipeconfig *
87 muse_bias_new_recipeconfig(void)
88 {
89  cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
90 
91  cpl_recipeconfig_set_tag(recipeconfig, "BIAS", 3, -1);
92  cpl_recipeconfig_set_input(recipeconfig, "BIAS", "BADPIX_TABLE", -1, -1);
93  cpl_recipeconfig_set_output(recipeconfig, "BIAS", "MASTER_BIAS");
94 
95  return recipeconfig;
96 } /* muse_bias_new_recipeconfig() */
97 
98 /*----------------------------------------------------------------------------*/
108 /*----------------------------------------------------------------------------*/
109 static cpl_error_code
110 muse_bias_prepare_header(const char *aFrametag, cpl_propertylist *aHeader)
111 {
112  cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
113  cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
114  if (!strcmp(aFrametag, "MASTER_BIAS")) {
115  muse_processing_prepare_property(aHeader, "ESO QC BIAS INPUT[0-9]+ NSATURATED",
116  CPL_TYPE_INT,
117  "Number of saturated pixels in raw bias i in input list");
118  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] MEDIAN",
119  CPL_TYPE_FLOAT,
120  "Median value of master bias in quadrant n");
121  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] MEAN",
122  CPL_TYPE_FLOAT,
123  "Mean value of master bias in quadrant n");
124  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] STDEV",
125  CPL_TYPE_FLOAT,
126  "Standard deviation value of master bias in quadrant n");
127  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] MIN",
128  CPL_TYPE_FLOAT,
129  "Minimum value of master bias in quadrant n");
130  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] MAX",
131  CPL_TYPE_FLOAT,
132  "Maximum value of master bias in quadrant n");
133  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] RON",
134  CPL_TYPE_FLOAT,
135  "[count] Read-out noise in quadrant n determined from difference images of each adjacent pair of biases in the input dataset in randomly placed windows");
136  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] RONERR",
137  CPL_TYPE_FLOAT,
138  "[count] Read-out noise error in quadrant n determined from difference images of each adjacent pair of biases in the input dataset in randomly placed windows");
139  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] SLOPE X",
140  CPL_TYPE_FLOAT,
141  "[adu/pix] Average horizontal slope of master bias in quadrant n");
142  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] SLOPE Y",
143  CPL_TYPE_FLOAT,
144  "[adu/pix] Average vertical slope of master bias in quadrant n");
145  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER NBADPIX",
146  CPL_TYPE_INT,
147  "Bad pixels found as part of the bad column search in the master bias");
148  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER NSATURATED",
149  CPL_TYPE_INT,
150  "Number of saturated pixels in output data");
151  muse_processing_prepare_property(aHeader, "ESO QC BIAS LEVEL[1234] MEAN",
152  CPL_TYPE_FLOAT,
153  "[adu] Average of the raw median values of all input files in quadrant n");
154  muse_processing_prepare_property(aHeader, "ESO QC BIAS LEVEL[1234] STDEV",
155  CPL_TYPE_FLOAT,
156  "[adu] Standard deviation of the raw median values of all input files in quadrant n");
157  muse_processing_prepare_property(aHeader, "ESO QC BIAS LEVEL[1234] MEDIAN",
158  CPL_TYPE_FLOAT,
159  "[adu] Median of the raw median values of all input files in quadrant n");
160  } else {
161  cpl_msg_warning(__func__, "Frame tag %s is not defined", aFrametag);
162  return CPL_ERROR_ILLEGAL_INPUT;
163  }
164  return CPL_ERROR_NONE;
165 } /* muse_bias_prepare_header() */
166 
167 /*----------------------------------------------------------------------------*/
176 /*----------------------------------------------------------------------------*/
177 static cpl_frame_level
178 muse_bias_get_frame_level(const char *aFrametag)
179 {
180  if (!aFrametag) {
181  return CPL_FRAME_LEVEL_NONE;
182  }
183  if (!strcmp(aFrametag, "MASTER_BIAS")) {
184  return CPL_FRAME_LEVEL_FINAL;
185  }
186  return CPL_FRAME_LEVEL_NONE;
187 } /* muse_bias_get_frame_level() */
188 
189 /*----------------------------------------------------------------------------*/
198 /*----------------------------------------------------------------------------*/
199 static muse_frame_mode
200 muse_bias_get_frame_mode(const char *aFrametag)
201 {
202  if (!aFrametag) {
203  return MUSE_FRAME_MODE_ALL;
204  }
205  if (!strcmp(aFrametag, "MASTER_BIAS")) {
206  return MUSE_FRAME_MODE_MASTER;
207  }
208  return MUSE_FRAME_MODE_ALL;
209 } /* muse_bias_get_frame_mode() */
210 
211 /*----------------------------------------------------------------------------*/
221 /*----------------------------------------------------------------------------*/
222 static int
223 muse_bias_create(cpl_plugin *aPlugin)
224 {
225  /* Check that the plugin is part of a valid recipe */
226  cpl_recipe *recipe;
227  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
228  recipe = (cpl_recipe *)aPlugin;
229  } else {
230  return -1;
231  }
232 
233  /* register the extended processing information (new FITS header creation, *
234  * getting of the frame level for a certain tag) */
236  muse_bias_new_recipeconfig(),
237  muse_bias_prepare_header,
238  muse_bias_get_frame_level,
239  muse_bias_get_frame_mode);
240 
241  /* XXX initialize timing in messages *
242  * since at least esorex is too stupid to turn it on, we have to do it */
244  cpl_msg_set_time_on();
245  }
246 
247  /* Create the parameter list in the cpl_recipe object */
248  recipe->parameters = cpl_parameterlist_new();
249  /* Fill the parameters list */
250  cpl_parameter *p;
251 
252  /* --nifu: IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel. */
253  p = cpl_parameter_new_range("muse.muse_bias.nifu",
254  CPL_TYPE_INT,
255  "IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel.",
256  "muse.muse_bias",
257  (int)0,
258  (int)-1,
259  (int)24);
260  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nifu");
261  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nifu");
262 
263  cpl_parameterlist_append(recipe->parameters, p);
264 
265  /* --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. */
266  p = cpl_parameter_new_value("muse.muse_bias.overscan",
267  CPL_TYPE_STRING,
268  "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.",
269  "muse.muse_bias",
270  (const char *)"vpoly");
271  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "overscan");
272  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "overscan");
273 
274  cpl_parameterlist_append(recipe->parameters, p);
275 
276  /* --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"). */
277  p = cpl_parameter_new_value("muse.muse_bias.ovscreject",
278  CPL_TYPE_STRING,
279  "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\").",
280  "muse.muse_bias",
281  (const char *)"dcr");
282  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscreject");
283  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscreject");
284 
285  cpl_parameterlist_append(recipe->parameters, p);
286 
287  /* --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". */
288  p = cpl_parameter_new_value("muse.muse_bias.ovscsigma",
289  CPL_TYPE_DOUBLE,
290  "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\".",
291  "muse.muse_bias",
292  (double)30.);
293  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscsigma");
294  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscsigma");
295 
296  cpl_parameterlist_append(recipe->parameters, p);
297 
298  /* --ovscignore: The number of pixels of the overscan adjacent to the data section of the CCD that are ignored when computing statistics or fits. */
299  p = cpl_parameter_new_value("muse.muse_bias.ovscignore",
300  CPL_TYPE_INT,
301  "The number of pixels of the overscan adjacent to the data section of the CCD that are ignored when computing statistics or fits.",
302  "muse.muse_bias",
303  (int)3);
304  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscignore");
305  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscignore");
306 
307  cpl_parameterlist_append(recipe->parameters, p);
308 
309  /* --combine: Type of image combination to use. */
310  p = cpl_parameter_new_enum("muse.muse_bias.combine",
311  CPL_TYPE_STRING,
312  "Type of image combination to use.",
313  "muse.muse_bias",
314  (const char *)"sigclip",
315  4,
316  (const char *)"average",
317  (const char *)"median",
318  (const char *)"minmax",
319  (const char *)"sigclip");
320  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "combine");
321  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "combine");
322 
323  cpl_parameterlist_append(recipe->parameters, p);
324 
325  /* --nlow: Number of minimum pixels to reject with minmax. */
326  p = cpl_parameter_new_value("muse.muse_bias.nlow",
327  CPL_TYPE_INT,
328  "Number of minimum pixels to reject with minmax.",
329  "muse.muse_bias",
330  (int)1);
331  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nlow");
332  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nlow");
333 
334  cpl_parameterlist_append(recipe->parameters, p);
335 
336  /* --nhigh: Number of maximum pixels to reject with minmax. */
337  p = cpl_parameter_new_value("muse.muse_bias.nhigh",
338  CPL_TYPE_INT,
339  "Number of maximum pixels to reject with minmax.",
340  "muse.muse_bias",
341  (int)1);
342  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nhigh");
343  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nhigh");
344 
345  cpl_parameterlist_append(recipe->parameters, p);
346 
347  /* --nkeep: Number of pixels to keep with minmax. */
348  p = cpl_parameter_new_value("muse.muse_bias.nkeep",
349  CPL_TYPE_INT,
350  "Number of pixels to keep with minmax.",
351  "muse.muse_bias",
352  (int)1);
353  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nkeep");
354  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nkeep");
355 
356  cpl_parameterlist_append(recipe->parameters, p);
357 
358  /* --lsigma: Low sigma for pixel rejection with sigclip. */
359  p = cpl_parameter_new_value("muse.muse_bias.lsigma",
360  CPL_TYPE_DOUBLE,
361  "Low sigma for pixel rejection with sigclip.",
362  "muse.muse_bias",
363  (double)3);
364  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lsigma");
365  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lsigma");
366 
367  cpl_parameterlist_append(recipe->parameters, p);
368 
369  /* --hsigma: High sigma for pixel rejection with sigclip. */
370  p = cpl_parameter_new_value("muse.muse_bias.hsigma",
371  CPL_TYPE_DOUBLE,
372  "High sigma for pixel rejection with sigclip.",
373  "muse.muse_bias",
374  (double)3);
375  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "hsigma");
376  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "hsigma");
377 
378  cpl_parameterlist_append(recipe->parameters, p);
379 
380  /* --losigmabadpix: Low sigma to find dark columns in the combined bias */
381  p = cpl_parameter_new_value("muse.muse_bias.losigmabadpix",
382  CPL_TYPE_DOUBLE,
383  "Low sigma to find dark columns in the combined bias",
384  "muse.muse_bias",
385  (double)30.);
386  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "losigmabadpix");
387  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "losigmabadpix");
388 
389  cpl_parameterlist_append(recipe->parameters, p);
390 
391  /* --hisigmabadpix: High sigma to find bright columns in the combined bias */
392  p = cpl_parameter_new_value("muse.muse_bias.hisigmabadpix",
393  CPL_TYPE_DOUBLE,
394  "High sigma to find bright columns in the combined bias",
395  "muse.muse_bias",
396  (double)3.);
397  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "hisigmabadpix");
398  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "hisigmabadpix");
399 
400  cpl_parameterlist_append(recipe->parameters, p);
401 
402  /* --merge: Merge output products from different IFUs into a common file. */
403  p = cpl_parameter_new_value("muse.muse_bias.merge",
404  CPL_TYPE_BOOL,
405  "Merge output products from different IFUs into a common file.",
406  "muse.muse_bias",
407  (int)FALSE);
408  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "merge");
409  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "merge");
410 
411  cpl_parameterlist_append(recipe->parameters, p);
412 
413  return 0;
414 } /* muse_bias_create() */
415 
416 /*----------------------------------------------------------------------------*/
427 /*----------------------------------------------------------------------------*/
428 static int
429 muse_bias_params_fill(muse_bias_params_t *aParams, cpl_parameterlist *aParameters)
430 {
431  cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
432  cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
433  cpl_parameter *p;
434 
435  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.nifu");
436  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
437  aParams->nifu = cpl_parameter_get_int(p);
438 
439  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.overscan");
440  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
441  aParams->overscan = cpl_parameter_get_string(p);
442 
443  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.ovscreject");
444  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
445  aParams->ovscreject = cpl_parameter_get_string(p);
446 
447  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.ovscsigma");
448  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
449  aParams->ovscsigma = cpl_parameter_get_double(p);
450 
451  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.ovscignore");
452  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
453  aParams->ovscignore = cpl_parameter_get_int(p);
454 
455  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.combine");
456  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
457  aParams->combine_s = cpl_parameter_get_string(p);
458  aParams->combine =
459  (!strcasecmp(aParams->combine_s, "average")) ? MUSE_BIAS_PARAM_COMBINE_AVERAGE :
460  (!strcasecmp(aParams->combine_s, "median")) ? MUSE_BIAS_PARAM_COMBINE_MEDIAN :
461  (!strcasecmp(aParams->combine_s, "minmax")) ? MUSE_BIAS_PARAM_COMBINE_MINMAX :
462  (!strcasecmp(aParams->combine_s, "sigclip")) ? MUSE_BIAS_PARAM_COMBINE_SIGCLIP :
463  MUSE_BIAS_PARAM_COMBINE_INVALID_VALUE;
464  cpl_ensure_code(aParams->combine != MUSE_BIAS_PARAM_COMBINE_INVALID_VALUE,
465  CPL_ERROR_ILLEGAL_INPUT);
466 
467  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.nlow");
468  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
469  aParams->nlow = cpl_parameter_get_int(p);
470 
471  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.nhigh");
472  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
473  aParams->nhigh = cpl_parameter_get_int(p);
474 
475  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.nkeep");
476  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
477  aParams->nkeep = cpl_parameter_get_int(p);
478 
479  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.lsigma");
480  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
481  aParams->lsigma = cpl_parameter_get_double(p);
482 
483  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.hsigma");
484  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
485  aParams->hsigma = cpl_parameter_get_double(p);
486 
487  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.losigmabadpix");
488  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
489  aParams->losigmabadpix = cpl_parameter_get_double(p);
490 
491  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.hisigmabadpix");
492  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
493  aParams->hisigmabadpix = cpl_parameter_get_double(p);
494 
495  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.merge");
496  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
497  aParams->merge = cpl_parameter_get_bool(p);
498 
499  return 0;
500 } /* muse_bias_params_fill() */
501 
502 /*----------------------------------------------------------------------------*/
509 /*----------------------------------------------------------------------------*/
510 static int
511 muse_bias_exec(cpl_plugin *aPlugin)
512 {
513  if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
514  return -1;
515  }
517  cpl_recipe *recipe = (cpl_recipe *)aPlugin;
518  cpl_msg_set_threadid_on();
519 
520  cpl_frameset *usedframes = cpl_frameset_new(),
521  *outframes = cpl_frameset_new();
522  muse_bias_params_t params;
523  muse_bias_params_fill(&params, recipe->parameters);
524 
525  cpl_errorstate prestate = cpl_errorstate_get();
526 
527  if (params.nifu < -1 || params.nifu > kMuseNumIFUs) {
528  cpl_msg_error(__func__, "Please specify a valid IFU number (between 1 and "
529  "%d), 0 (to process all IFUs consecutively), or -1 (to "
530  "process all IFUs in parallel) using --nifu.", kMuseNumIFUs);
531  return -1;
532  } /* if invalid params.nifu */
533 
534  cpl_boolean donotmerge = CPL_FALSE; /* depending on nifu we may not merge */
535  int rc = 0;
536  if (params.nifu > 0) {
537  muse_processing *proc = muse_processing_new("muse_bias",
538  recipe);
539  rc = muse_bias_compute(proc, &params);
540  cpl_frameset_join(usedframes, proc->usedframes);
541  cpl_frameset_join(outframes, proc->outframes);
543  donotmerge = CPL_TRUE; /* after processing one IFU, merging cannot work */
544  } else if (params.nifu < 0) { /* parallel processing */
545  int *rcs = cpl_calloc(kMuseNumIFUs, sizeof(int));
546  int nifu;
547  #pragma omp parallel for default(none) \
548  shared(outframes, params, rcs, recipe, usedframes)
549  for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
550  muse_processing *proc = muse_processing_new("muse_bias",
551  recipe);
552  muse_bias_params_t *pars = cpl_malloc(sizeof(muse_bias_params_t));
553  memcpy(pars, &params, sizeof(muse_bias_params_t));
554  pars->nifu = nifu;
555  int *rci = rcs + (nifu - 1);
556  *rci = muse_bias_compute(proc, pars);
557  if (rci && (int)cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
558  *rci = 0;
559  }
560  cpl_free(pars);
561  #pragma omp critical(muse_processing_used_frames)
562  cpl_frameset_join(usedframes, proc->usedframes);
563  #pragma omp critical(muse_processing_output_frames)
564  cpl_frameset_join(outframes, proc->outframes);
566  } /* for nifu */
567  /* non-parallel loop to propagate the "worst" return code; *
568  * since we only ever return -1, any non-zero code is propagated */
569  for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
570  if (rcs[nifu-1] != 0) {
571  rc = rcs[nifu-1];
572  } /* if */
573  } /* for nifu */
574  cpl_free(rcs);
575  } else { /* serial processing */
576  for (params.nifu = 1; params.nifu <= kMuseNumIFUs && !rc; params.nifu++) {
577  muse_processing *proc = muse_processing_new("muse_bias",
578  recipe);
579  rc = muse_bias_compute(proc, &params);
580  if (rc && (int)cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
581  rc = 0;
582  }
583  cpl_frameset_join(usedframes, proc->usedframes);
584  cpl_frameset_join(outframes, proc->outframes);
586  } /* for nifu */
587  } /* else */
588  UNUSED_ARGUMENT(donotmerge); /* maybe this is not going to be used below */
589 
590  if (!cpl_errorstate_is_equal(prestate)) {
591  /* dump all errors from this recipe in chronological order */
592  cpl_errorstate_dump(prestate, CPL_FALSE, muse_cplerrorstate_dump_some);
593  /* reset message level to not get the same errors displayed again by esorex */
594  cpl_msg_set_level(CPL_MSG_INFO);
595  }
596  /* clean up duplicates in framesets of used and output frames */
599 
600  /* merge output products from the up to 24 IFUs */
601  if (params.merge && !donotmerge) {
602  muse_utils_frameset_merge_frames(outframes, CPL_TRUE);
603  }
604 
605  /* to get esorex to see our classification (frame groups etc.), *
606  * replace the original frameset with the list of used frames *
607  * before appending product output frames */
608  /* keep the same pointer, so just erase all frames, not delete the frameset */
609  muse_cplframeset_erase_all(recipe->frames);
610  cpl_frameset_join(recipe->frames, usedframes);
611  cpl_frameset_join(recipe->frames, outframes);
612  cpl_frameset_delete(usedframes);
613  cpl_frameset_delete(outframes);
614  return rc;
615 } /* muse_bias_exec() */
616 
617 /*----------------------------------------------------------------------------*/
624 /*----------------------------------------------------------------------------*/
625 static int
626 muse_bias_destroy(cpl_plugin *aPlugin)
627 {
628  /* Get the recipe from the plugin */
629  cpl_recipe *recipe;
630  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
631  recipe = (cpl_recipe *)aPlugin;
632  } else {
633  return -1;
634  }
635 
636  /* Clean up */
637  cpl_parameterlist_delete(recipe->parameters);
639  return 0;
640 } /* muse_bias_destroy() */
641 
642 /*----------------------------------------------------------------------------*/
652 /*----------------------------------------------------------------------------*/
653 int
654 cpl_plugin_get_info(cpl_pluginlist *aList)
655 {
656  cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
657  cpl_plugin *plugin = &recipe->interface;
658 
659  char *helptext;
661  helptext = cpl_sprintf("%s%s", muse_bias_help,
662  muse_bias_help_esorex);
663  } else {
664  helptext = cpl_sprintf("%s", muse_bias_help);
665  }
666 
667  /* Initialize the CPL plugin stuff for this module */
668  cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
669  CPL_PLUGIN_TYPE_RECIPE,
670  "muse_bias",
671  "Combine several separate bias images into one master bias file.",
672  helptext,
673  "Peter Weilbacher",
674  "usd-help@eso.org",
676  muse_bias_create,
677  muse_bias_exec,
678  muse_bias_destroy);
679  cpl_pluginlist_append(aList, plugin);
680  cpl_free(helptext);
681 
682  return 0;
683 } /* cpl_plugin_get_info() */
684 
const char * combine_s
Type of image combination to use. (as string)
Definition: muse_bias_z.h:67
double lsigma
Low sigma for pixel rejection with sigclip.
Definition: muse_bias_z.h:79
void muse_processing_delete(muse_processing *aProcessing)
Free the muse_processing structure.
int nhigh
Number of maximum pixels to reject with minmax.
Definition: muse_bias_z.h:73
double hisigmabadpix
High sigma to find bright columns in the combined bias.
Definition: muse_bias_z.h:88
muse_cplframework_type muse_cplframework(void)
Return the CPL framework the recipe is run under.
int combine
Type of image combination to use.
Definition: muse_bias_z.h:65
int nifu
IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in ...
Definition: muse_bias_z.h:50
const char * ovscreject
This influences how values are rejected when computing overscan statistics. Either no rejection at al...
Definition: muse_bias_z.h:56
cpl_frameset * usedframes
muse_processing * muse_processing_new(const char *aName, cpl_recipe *aRecipe)
Create a new processing structure.
int nkeep
Number of pixels to keep with minmax.
Definition: muse_bias_z.h:76
double losigmabadpix
Low sigma to find dark columns in the combined bias.
Definition: muse_bias_z.h:85
const char * muse_get_license(void)
Get the pipeline copyright and license.
Definition: muse_utils.c:83
muse_frame_mode
cpl_frameset * outframes
double ovscsigma
If the deviation of mean overscan levels between a raw input image and the reference image is higher ...
Definition: muse_bias_z.h:59
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.
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.
Definition: muse_bias_z.h:53
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 ovscignore
The number of pixels of the overscan adjacent to the data section of the CCD that are ignored when co...
Definition: muse_bias_z.h:62
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 merge
Merge output products from different IFUs into a common file.
Definition: muse_bias_z.h:91
void muse_processing_recipeinfo(cpl_plugin *)
Output main pipeline configuration, inputs, and parameters.
int nlow
Number of minimum pixels to reject with minmax.
Definition: muse_bias_z.h:70
cpl_error_code muse_utils_frameset_merge_frames(cpl_frameset *aFrames, cpl_boolean aDelete)
Merge IFU-specific files from a frameset to create multi-IFU outputs.
Definition: muse_utils.c:589
Structure to hold the parameters of the muse_bias recipe.
Definition: muse_bias_z.h:48
double hsigma
High sigma for pixel rejection with sigclip.
Definition: muse_bias_z.h:82
cpl_error_code muse_processing_prepare_property(cpl_propertylist *, const char *, cpl_type, const char *)
Prepare and check the specified property.