MUSE Pipeline Reference Manual  0.18.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-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_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 . 1 Bad pixel table"
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  const char *tag;
91 
92  tag = "BIAS";
93  cpl_recipeconfig_set_tag(recipeconfig, tag, 3, -1);
94  cpl_recipeconfig_set_input(recipeconfig, tag, "BADPIX_TABLE", -1, 1);
95  cpl_recipeconfig_set_output(recipeconfig, tag, "MASTER_BIAS");
96 
97  return recipeconfig;
98 } /* muse_bias_new_recipeconfig() */
99 
100 /*----------------------------------------------------------------------------*/
110 /*----------------------------------------------------------------------------*/
111 static cpl_error_code
112 muse_bias_prepare_header(const char *aFrametag, cpl_propertylist *aHeader)
113 {
114  cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
115  cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
116  if (!strcmp(aFrametag, "MASTER_BIAS")) {
117  muse_processing_prepare_property(aHeader, "ESO QC BIAS INPUT[0-9]+ NSATURATED",
118  CPL_TYPE_INT,
119  "Number of saturated pixels in raw bias i in input list");
120  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] MEDIAN",
121  CPL_TYPE_FLOAT,
122  "Median value of master bias in quadrant n");
123  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] MEAN",
124  CPL_TYPE_FLOAT,
125  "Mean value of master bias in quadrant n");
126  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] STDEV",
127  CPL_TYPE_FLOAT,
128  "Standard deviation value of master bias in quadrant n");
129  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] MIN",
130  CPL_TYPE_FLOAT,
131  "Minimum value of master bias in quadrant n");
132  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] MAX",
133  CPL_TYPE_FLOAT,
134  "Maximum value of master bias in quadrant n");
135  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] RON",
136  CPL_TYPE_FLOAT,
137  "[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");
138  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] RONERR",
139  CPL_TYPE_FLOAT,
140  "[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");
141  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] SLOPE X",
142  CPL_TYPE_FLOAT,
143  "[adu/pix] Average horizontal slope of master bias in quadrant n");
144  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER[1234] SLOPE Y",
145  CPL_TYPE_FLOAT,
146  "[adu/pix] Average vertical slope of master bias in quadrant n");
147  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER NBADPIX",
148  CPL_TYPE_INT,
149  "Bad pixels found as part of the bad column search in the master bias");
150  muse_processing_prepare_property(aHeader, "ESO QC BIAS MASTER NSATURATED",
151  CPL_TYPE_INT,
152  "Number of saturated pixels in output data");
153  } else {
154  cpl_msg_warning(__func__, "Frame tag %s is not defined", aFrametag);
155  return CPL_ERROR_ILLEGAL_INPUT;
156  }
157  return CPL_ERROR_NONE;
158 } /* muse_bias_prepare_header() */
159 
160 /*----------------------------------------------------------------------------*/
169 /*----------------------------------------------------------------------------*/
170 static cpl_frame_level
171 muse_bias_get_frame_level(const char *aFrametag)
172 {
173  if (!aFrametag) {
174  return CPL_FRAME_LEVEL_NONE;
175  }
176  if (!strcmp(aFrametag, "MASTER_BIAS")) {
177  return CPL_FRAME_LEVEL_FINAL;
178  }
179  return CPL_FRAME_LEVEL_NONE;
180 } /* muse_bias_get_frame_level() */
181 
182 /*----------------------------------------------------------------------------*/
191 /*----------------------------------------------------------------------------*/
192 static muse_frame_mode
193 muse_bias_get_frame_mode(const char *aFrametag)
194 {
195  if (!aFrametag) {
196  return MUSE_FRAME_MODE_ALL;
197  }
198  if (!strcmp(aFrametag, "MASTER_BIAS")) {
199  return MUSE_FRAME_MODE_MASTER;
200  }
201  return MUSE_FRAME_MODE_ALL;
202 } /* muse_bias_get_frame_mode() */
203 
204 /*----------------------------------------------------------------------------*/
214 /*----------------------------------------------------------------------------*/
215 static int
216 muse_bias_create(cpl_plugin *aPlugin)
217 {
218  /* Check that the plugin is part of a valid recipe */
219  cpl_recipe *recipe;
220  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
221  recipe = (cpl_recipe *)aPlugin;
222  } else {
223  return -1;
224  }
225 
226  /* register the extended processing information (new FITS header creation, *
227  * getting of the frame level for a certain tag) */
229  muse_bias_new_recipeconfig(),
230  muse_bias_prepare_header,
231  muse_bias_get_frame_level,
232  muse_bias_get_frame_mode);
233 
234  /* XXX initialize timing in messages *
235  * since at least esorex is too stupid to turn it on, we have to do it */
237  cpl_msg_set_time_on();
238  }
239 
240  /* Create the parameter list in the cpl_recipe object */
241  recipe->parameters = cpl_parameterlist_new();
242  /* Fill the parameters list */
243  cpl_parameter *p;
244 
245  /* --nifu: IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel. */
246  p = cpl_parameter_new_range("muse.muse_bias.nifu",
247  CPL_TYPE_INT,
248  "IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel.",
249  "muse.muse_bias",
250  (int)0,
251  (int)-1,
252  (int)24);
253  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nifu");
254  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nifu");
255 
256  cpl_parameterlist_append(recipe->parameters, p);
257 
258  /* --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. */
259  p = cpl_parameter_new_value("muse.muse_bias.overscan",
260  CPL_TYPE_STRING,
261  "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.",
262  "muse.muse_bias",
263  (const char *)"vpoly");
264  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "overscan");
265  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "overscan");
266 
267  cpl_parameterlist_append(recipe->parameters, p);
268 
269  /* --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"). */
270  p = cpl_parameter_new_value("muse.muse_bias.ovscreject",
271  CPL_TYPE_STRING,
272  "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\").",
273  "muse.muse_bias",
274  (const char *)"dcr");
275  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscreject");
276  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscreject");
277 
278  cpl_parameterlist_append(recipe->parameters, p);
279 
280  /* --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". */
281  p = cpl_parameter_new_value("muse.muse_bias.ovscsigma",
282  CPL_TYPE_DOUBLE,
283  "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\".",
284  "muse.muse_bias",
285  (double)3.);
286  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscsigma");
287  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscsigma");
288 
289  cpl_parameterlist_append(recipe->parameters, p);
290 
291  /* --ovscignore: The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when computing statistics or fits. */
292  p = cpl_parameter_new_value("muse.muse_bias.ovscignore",
293  CPL_TYPE_INT,
294  "The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when computing statistics or fits.",
295  "muse.muse_bias",
296  (int)3);
297  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscignore");
298  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscignore");
299 
300  cpl_parameterlist_append(recipe->parameters, p);
301 
302  /* --combine: Type of image combination to use. */
303  p = cpl_parameter_new_enum("muse.muse_bias.combine",
304  CPL_TYPE_STRING,
305  "Type of image combination to use.",
306  "muse.muse_bias",
307  (const char *)"sigclip",
308  4,
309  (const char *)"average",
310  (const char *)"median",
311  (const char *)"minmax",
312  (const char *)"sigclip");
313  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "combine");
314  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "combine");
315 
316  cpl_parameterlist_append(recipe->parameters, p);
317 
318  /* --nlow: Number of minimum pixels to reject with minmax. */
319  p = cpl_parameter_new_value("muse.muse_bias.nlow",
320  CPL_TYPE_INT,
321  "Number of minimum pixels to reject with minmax.",
322  "muse.muse_bias",
323  (int)1);
324  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nlow");
325  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nlow");
326 
327  cpl_parameterlist_append(recipe->parameters, p);
328 
329  /* --nhigh: Number of maximum pixels to reject with minmax. */
330  p = cpl_parameter_new_value("muse.muse_bias.nhigh",
331  CPL_TYPE_INT,
332  "Number of maximum pixels to reject with minmax.",
333  "muse.muse_bias",
334  (int)1);
335  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nhigh");
336  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nhigh");
337 
338  cpl_parameterlist_append(recipe->parameters, p);
339 
340  /* --nkeep: Number of pixels to keep with minmax. */
341  p = cpl_parameter_new_value("muse.muse_bias.nkeep",
342  CPL_TYPE_INT,
343  "Number of pixels to keep with minmax.",
344  "muse.muse_bias",
345  (int)1);
346  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nkeep");
347  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nkeep");
348 
349  cpl_parameterlist_append(recipe->parameters, p);
350 
351  /* --lsigma: Low sigma for pixel rejection with sigclip. */
352  p = cpl_parameter_new_value("muse.muse_bias.lsigma",
353  CPL_TYPE_DOUBLE,
354  "Low sigma for pixel rejection with sigclip.",
355  "muse.muse_bias",
356  (double)3);
357  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lsigma");
358  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lsigma");
359 
360  cpl_parameterlist_append(recipe->parameters, p);
361 
362  /* --hsigma: High sigma for pixel rejection with sigclip. */
363  p = cpl_parameter_new_value("muse.muse_bias.hsigma",
364  CPL_TYPE_DOUBLE,
365  "High sigma for pixel rejection with sigclip.",
366  "muse.muse_bias",
367  (double)3);
368  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "hsigma");
369  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "hsigma");
370 
371  cpl_parameterlist_append(recipe->parameters, p);
372 
373  /* --losigmabadpix: Low sigma to find dark columns in the combined bias */
374  p = cpl_parameter_new_value("muse.muse_bias.losigmabadpix",
375  CPL_TYPE_DOUBLE,
376  "Low sigma to find dark columns in the combined bias",
377  "muse.muse_bias",
378  (double)30.);
379  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "losigmabadpix");
380  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "losigmabadpix");
381 
382  cpl_parameterlist_append(recipe->parameters, p);
383 
384  /* --hisigmabadpix: High sigma to find bright columns in the combined bias */
385  p = cpl_parameter_new_value("muse.muse_bias.hisigmabadpix",
386  CPL_TYPE_DOUBLE,
387  "High sigma to find bright columns in the combined bias",
388  "muse.muse_bias",
389  (double)3.);
390  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "hisigmabadpix");
391  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "hisigmabadpix");
392 
393  cpl_parameterlist_append(recipe->parameters, p);
394 
395  return 0;
396 } /* muse_bias_create() */
397 
398 /*----------------------------------------------------------------------------*/
409 /*----------------------------------------------------------------------------*/
410 static int
411 muse_bias_params_fill(muse_bias_params_t *aParams, cpl_parameterlist *aParameters)
412 {
413  cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
414  cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
415  cpl_parameter *p;
416 
417  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.nifu");
418  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
419  aParams->nifu = cpl_parameter_get_int(p);
420 
421  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.overscan");
422  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
423  aParams->overscan = cpl_parameter_get_string(p);
424 
425  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.ovscreject");
426  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
427  aParams->ovscreject = cpl_parameter_get_string(p);
428 
429  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.ovscsigma");
430  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
431  aParams->ovscsigma = cpl_parameter_get_double(p);
432 
433  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.ovscignore");
434  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
435  aParams->ovscignore = cpl_parameter_get_int(p);
436 
437  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.combine");
438  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
439  aParams->combine_s = cpl_parameter_get_string(p);
440  aParams->combine =
441  (!strcasecmp(aParams->combine_s, "average")) ? MUSE_BIAS_PARAM_COMBINE_AVERAGE :
442  (!strcasecmp(aParams->combine_s, "median")) ? MUSE_BIAS_PARAM_COMBINE_MEDIAN :
443  (!strcasecmp(aParams->combine_s, "minmax")) ? MUSE_BIAS_PARAM_COMBINE_MINMAX :
444  (!strcasecmp(aParams->combine_s, "sigclip")) ? MUSE_BIAS_PARAM_COMBINE_SIGCLIP :
445  MUSE_BIAS_PARAM_COMBINE_INVALID_VALUE;
446  cpl_ensure_code(aParams->combine != MUSE_BIAS_PARAM_COMBINE_INVALID_VALUE,
447  CPL_ERROR_ILLEGAL_INPUT);
448 
449  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.nlow");
450  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
451  aParams->nlow = cpl_parameter_get_int(p);
452 
453  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.nhigh");
454  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
455  aParams->nhigh = cpl_parameter_get_int(p);
456 
457  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.nkeep");
458  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
459  aParams->nkeep = cpl_parameter_get_int(p);
460 
461  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.lsigma");
462  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
463  aParams->lsigma = cpl_parameter_get_double(p);
464 
465  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.hsigma");
466  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
467  aParams->hsigma = cpl_parameter_get_double(p);
468 
469  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.losigmabadpix");
470  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
471  aParams->losigmabadpix = cpl_parameter_get_double(p);
472 
473  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.hisigmabadpix");
474  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
475  aParams->hisigmabadpix = cpl_parameter_get_double(p);
476 
477  return 0;
478 } /* muse_bias_params_fill() */
479 
480 /*----------------------------------------------------------------------------*/
487 /*----------------------------------------------------------------------------*/
488 static int
489 muse_bias_exec(cpl_plugin *aPlugin)
490 {
491  if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
492  return -1;
493  }
494  cpl_recipe *recipe = (cpl_recipe *)aPlugin;
495  cpl_msg_set_threadid_on();
496 
497  cpl_frameset *usedframes = cpl_frameset_new(),
498  *outframes = cpl_frameset_new();
499  muse_bias_params_t params;
500  muse_bias_params_fill(&params, recipe->parameters);
501 
502  cpl_errorstate prestate = cpl_errorstate_get();
503 
504  if (params.nifu < -1 || params.nifu > kMuseNumIFUs) {
505  cpl_msg_error(__func__, "Please specify a valid IFU number (between 1 and "
506  "%d), 0 (to process all IFUs consecutively), or -1 (to "
507  "process all IFUs in parallel) using --nifu.", kMuseNumIFUs);
508  return -1;
509  } /* if invalid params.nifu */
510 
511  int rc = 0;
512  if (params.nifu > 0) {
513  muse_processing *proc = muse_processing_new("muse_bias",
514  recipe);
515  rc = muse_bias_compute(proc, &params);
516  cpl_frameset_join(usedframes, proc->usedFrames);
517  cpl_frameset_join(outframes, proc->outputFrames);
519  } else if (params.nifu < 0) { /* parallel processing */
520  int *rcs = cpl_calloc(kMuseNumIFUs, sizeof(int));
521  int nifu;
522  #pragma omp parallel for default(none) \
523  shared(outframes, params, rcs, recipe, usedframes)
524  for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
525  muse_processing *proc = muse_processing_new("muse_bias",
526  recipe);
527  muse_bias_params_t *pars = cpl_malloc(sizeof(muse_bias_params_t));
528  memcpy(pars, &params, sizeof(muse_bias_params_t));
529  pars->nifu = nifu;
530  int *rci = rcs + (nifu - 1);
531  *rci = muse_bias_compute(proc, pars);
532  if (rci && cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
533  *rci = 0;
534  }
535  cpl_free(pars);
536  #pragma omp critical(muse_processing_used_frames)
537  cpl_frameset_join(usedframes, proc->usedFrames);
538  #pragma omp critical(muse_processing_output_frames)
539  cpl_frameset_join(outframes, proc->outputFrames);
541  } /* for nifu */
542  /* non-parallel loop to propagate the "worst" return code; *
543  * since we only ever return -1, any non-zero code is propagated */
544  for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
545  if (rcs[nifu-1] != 0) {
546  rc = rcs[nifu-1];
547  } /* if */
548  } /* for nifu */
549  cpl_free(rcs);
550  } else { /* serial processing */
551  for (params.nifu = 1; params.nifu <= kMuseNumIFUs && !rc; params.nifu++) {
552  muse_processing *proc = muse_processing_new("muse_bias",
553  recipe);
554  rc = muse_bias_compute(proc, &params);
555  if (rc && cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
556  rc = 0;
557  }
558  cpl_frameset_join(usedframes, proc->usedFrames);
559  cpl_frameset_join(outframes, proc->outputFrames);
561  } /* for nifu */
562  } /* else */
563 
564  if (!cpl_errorstate_is_equal(prestate)) {
565  /* dump all errors from this recipe in chronological order */
566  cpl_errorstate_dump(prestate, CPL_FALSE, muse_cplerrorstate_dump_some);
567  /* reset message level to not get the same errors displayed again by esorex */
568  cpl_msg_set_level(CPL_MSG_INFO);
569  }
570  /* clean up duplicates in framesets of used and output frames */
573  /* to get esorex to see our classification (frame groups etc.), *
574  * replace the original frameset with the list of used frames *
575  * before appending product output frames */
576  /* keep the same pointer, so just erase all frames, not delete the frameset */
577  muse_cplframeset_erase_all(recipe->frames);
578  cpl_frameset_join(recipe->frames, usedframes);
579  cpl_frameset_join(recipe->frames, outframes);
580  cpl_frameset_delete(usedframes);
581  cpl_frameset_delete(outframes);
582  return rc;
583 } /* muse_bias_exec() */
584 
585 /*----------------------------------------------------------------------------*/
592 /*----------------------------------------------------------------------------*/
593 static int
594 muse_bias_destroy(cpl_plugin *aPlugin)
595 {
596  /* Get the recipe from the plugin */
597  cpl_recipe *recipe;
598  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
599  recipe = (cpl_recipe *)aPlugin;
600  } else {
601  return -1;
602  }
603 
604  /* Clean up */
605  cpl_parameterlist_delete(recipe->parameters);
607  return 0;
608 } /* muse_bias_destroy() */
609 
610 /*----------------------------------------------------------------------------*/
620 /*----------------------------------------------------------------------------*/
621 int
622 cpl_plugin_get_info(cpl_pluginlist *aList)
623 {
624  cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
625  cpl_plugin *plugin = &recipe->interface;
626 
627  char *helptext;
629  helptext = cpl_sprintf("%s%s", muse_bias_help,
630  muse_bias_help_esorex);
631  } else {
632  helptext = cpl_sprintf("%s", muse_bias_help);
633  }
634 
635  /* Initialize the CPL plugin stuff for this module */
636  cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
637  CPL_PLUGIN_TYPE_RECIPE,
638  "muse_bias",
639  "Combine several separate bias images into one master bias file.",
640  helptext,
641  "Peter Weilbacher",
642  "usd-help@eso.org",
644  muse_bias_create,
645  muse_bias_exec,
646  muse_bias_destroy);
647  cpl_pluginlist_append(aList, plugin);
648  cpl_free(helptext);
649 
650  return 0;
651 } /* cpl_plugin_get_info() */
652 
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
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:80
muse_processing * muse_processing_new(const char *aRecipeName, cpl_recipe *aRecipe)
Create a new processing structure.
muse_frame_mode
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
cpl_frameset * outputFrames
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 region of the CCD that are ignored when com...
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.
cpl_frameset * usedFrames
int nlow
Number of minimum pixels to reject with minmax.
Definition: muse_bias_z.h:70
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.