MUSE Pipeline Reference Manual  1.0.2
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-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_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  muse_processing_prepare_property(aHeader, "ESO QC BIAS LEVEL[1234] MEAN",
154  CPL_TYPE_FLOAT,
155  "[adu] Average of the raw median values of all input files in quadrant n");
156  muse_processing_prepare_property(aHeader, "ESO QC BIAS LEVEL[1234] STDEV",
157  CPL_TYPE_FLOAT,
158  "[adu] Standard deviation of the raw median values of all input files in quadrant n");
159  muse_processing_prepare_property(aHeader, "ESO QC BIAS LEVEL[1234] MEDIAN",
160  CPL_TYPE_FLOAT,
161  "[adu] Median of the raw median values of all input files in quadrant n");
162  } else {
163  cpl_msg_warning(__func__, "Frame tag %s is not defined", aFrametag);
164  return CPL_ERROR_ILLEGAL_INPUT;
165  }
166  return CPL_ERROR_NONE;
167 } /* muse_bias_prepare_header() */
168 
169 /*----------------------------------------------------------------------------*/
178 /*----------------------------------------------------------------------------*/
179 static cpl_frame_level
180 muse_bias_get_frame_level(const char *aFrametag)
181 {
182  if (!aFrametag) {
183  return CPL_FRAME_LEVEL_NONE;
184  }
185  if (!strcmp(aFrametag, "MASTER_BIAS")) {
186  return CPL_FRAME_LEVEL_FINAL;
187  }
188  return CPL_FRAME_LEVEL_NONE;
189 } /* muse_bias_get_frame_level() */
190 
191 /*----------------------------------------------------------------------------*/
200 /*----------------------------------------------------------------------------*/
201 static muse_frame_mode
202 muse_bias_get_frame_mode(const char *aFrametag)
203 {
204  if (!aFrametag) {
205  return MUSE_FRAME_MODE_ALL;
206  }
207  if (!strcmp(aFrametag, "MASTER_BIAS")) {
208  return MUSE_FRAME_MODE_MASTER;
209  }
210  return MUSE_FRAME_MODE_ALL;
211 } /* muse_bias_get_frame_mode() */
212 
213 /*----------------------------------------------------------------------------*/
223 /*----------------------------------------------------------------------------*/
224 static int
225 muse_bias_create(cpl_plugin *aPlugin)
226 {
227  /* Check that the plugin is part of a valid recipe */
228  cpl_recipe *recipe;
229  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
230  recipe = (cpl_recipe *)aPlugin;
231  } else {
232  return -1;
233  }
234 
235  /* register the extended processing information (new FITS header creation, *
236  * getting of the frame level for a certain tag) */
238  muse_bias_new_recipeconfig(),
239  muse_bias_prepare_header,
240  muse_bias_get_frame_level,
241  muse_bias_get_frame_mode);
242 
243  /* XXX initialize timing in messages *
244  * since at least esorex is too stupid to turn it on, we have to do it */
246  cpl_msg_set_time_on();
247  }
248 
249  /* Create the parameter list in the cpl_recipe object */
250  recipe->parameters = cpl_parameterlist_new();
251  /* Fill the parameters list */
252  cpl_parameter *p;
253 
254  /* --nifu: IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel. */
255  p = cpl_parameter_new_range("muse.muse_bias.nifu",
256  CPL_TYPE_INT,
257  "IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel.",
258  "muse.muse_bias",
259  (int)0,
260  (int)-1,
261  (int)24);
262  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nifu");
263  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nifu");
264 
265  cpl_parameterlist_append(recipe->parameters, p);
266 
267  /* --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. */
268  p = cpl_parameter_new_value("muse.muse_bias.overscan",
269  CPL_TYPE_STRING,
270  "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.",
271  "muse.muse_bias",
272  (const char *)"vpoly");
273  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "overscan");
274  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "overscan");
275 
276  cpl_parameterlist_append(recipe->parameters, p);
277 
278  /* --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"). */
279  p = cpl_parameter_new_value("muse.muse_bias.ovscreject",
280  CPL_TYPE_STRING,
281  "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\").",
282  "muse.muse_bias",
283  (const char *)"dcr");
284  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscreject");
285  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscreject");
286 
287  cpl_parameterlist_append(recipe->parameters, p);
288 
289  /* --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". */
290  p = cpl_parameter_new_value("muse.muse_bias.ovscsigma",
291  CPL_TYPE_DOUBLE,
292  "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\".",
293  "muse.muse_bias",
294  (double)30.);
295  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscsigma");
296  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscsigma");
297 
298  cpl_parameterlist_append(recipe->parameters, p);
299 
300  /* --ovscignore: The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when computing statistics or fits. */
301  p = cpl_parameter_new_value("muse.muse_bias.ovscignore",
302  CPL_TYPE_INT,
303  "The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when computing statistics or fits.",
304  "muse.muse_bias",
305  (int)3);
306  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscignore");
307  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscignore");
308 
309  cpl_parameterlist_append(recipe->parameters, p);
310 
311  /* --combine: Type of image combination to use. */
312  p = cpl_parameter_new_enum("muse.muse_bias.combine",
313  CPL_TYPE_STRING,
314  "Type of image combination to use.",
315  "muse.muse_bias",
316  (const char *)"sigclip",
317  4,
318  (const char *)"average",
319  (const char *)"median",
320  (const char *)"minmax",
321  (const char *)"sigclip");
322  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "combine");
323  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "combine");
324 
325  cpl_parameterlist_append(recipe->parameters, p);
326 
327  /* --nlow: Number of minimum pixels to reject with minmax. */
328  p = cpl_parameter_new_value("muse.muse_bias.nlow",
329  CPL_TYPE_INT,
330  "Number of minimum pixels to reject with minmax.",
331  "muse.muse_bias",
332  (int)1);
333  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nlow");
334  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nlow");
335 
336  cpl_parameterlist_append(recipe->parameters, p);
337 
338  /* --nhigh: Number of maximum pixels to reject with minmax. */
339  p = cpl_parameter_new_value("muse.muse_bias.nhigh",
340  CPL_TYPE_INT,
341  "Number of maximum pixels to reject with minmax.",
342  "muse.muse_bias",
343  (int)1);
344  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nhigh");
345  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nhigh");
346 
347  cpl_parameterlist_append(recipe->parameters, p);
348 
349  /* --nkeep: Number of pixels to keep with minmax. */
350  p = cpl_parameter_new_value("muse.muse_bias.nkeep",
351  CPL_TYPE_INT,
352  "Number of pixels to keep with minmax.",
353  "muse.muse_bias",
354  (int)1);
355  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nkeep");
356  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nkeep");
357 
358  cpl_parameterlist_append(recipe->parameters, p);
359 
360  /* --lsigma: Low sigma for pixel rejection with sigclip. */
361  p = cpl_parameter_new_value("muse.muse_bias.lsigma",
362  CPL_TYPE_DOUBLE,
363  "Low sigma for pixel rejection with sigclip.",
364  "muse.muse_bias",
365  (double)3);
366  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lsigma");
367  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lsigma");
368 
369  cpl_parameterlist_append(recipe->parameters, p);
370 
371  /* --hsigma: High sigma for pixel rejection with sigclip. */
372  p = cpl_parameter_new_value("muse.muse_bias.hsigma",
373  CPL_TYPE_DOUBLE,
374  "High sigma for pixel rejection with sigclip.",
375  "muse.muse_bias",
376  (double)3);
377  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "hsigma");
378  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "hsigma");
379 
380  cpl_parameterlist_append(recipe->parameters, p);
381 
382  /* --losigmabadpix: Low sigma to find dark columns in the combined bias */
383  p = cpl_parameter_new_value("muse.muse_bias.losigmabadpix",
384  CPL_TYPE_DOUBLE,
385  "Low sigma to find dark columns in the combined bias",
386  "muse.muse_bias",
387  (double)30.);
388  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "losigmabadpix");
389  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "losigmabadpix");
390 
391  cpl_parameterlist_append(recipe->parameters, p);
392 
393  /* --hisigmabadpix: High sigma to find bright columns in the combined bias */
394  p = cpl_parameter_new_value("muse.muse_bias.hisigmabadpix",
395  CPL_TYPE_DOUBLE,
396  "High sigma to find bright columns in the combined bias",
397  "muse.muse_bias",
398  (double)3.);
399  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "hisigmabadpix");
400  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "hisigmabadpix");
401 
402  cpl_parameterlist_append(recipe->parameters, p);
403 
404  /* --merge: Merge output products from different IFUs into a common file. */
405  p = cpl_parameter_new_value("muse.muse_bias.merge",
406  CPL_TYPE_BOOL,
407  "Merge output products from different IFUs into a common file.",
408  "muse.muse_bias",
409  (int)FALSE);
410  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "merge");
411  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "merge");
412 
413  cpl_parameterlist_append(recipe->parameters, p);
414 
415  return 0;
416 } /* muse_bias_create() */
417 
418 /*----------------------------------------------------------------------------*/
429 /*----------------------------------------------------------------------------*/
430 static int
431 muse_bias_params_fill(muse_bias_params_t *aParams, cpl_parameterlist *aParameters)
432 {
433  cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
434  cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
435  cpl_parameter *p;
436 
437  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.nifu");
438  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
439  aParams->nifu = cpl_parameter_get_int(p);
440 
441  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.overscan");
442  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
443  aParams->overscan = cpl_parameter_get_string(p);
444 
445  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.ovscreject");
446  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
447  aParams->ovscreject = cpl_parameter_get_string(p);
448 
449  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.ovscsigma");
450  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
451  aParams->ovscsigma = cpl_parameter_get_double(p);
452 
453  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.ovscignore");
454  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
455  aParams->ovscignore = cpl_parameter_get_int(p);
456 
457  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.combine");
458  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
459  aParams->combine_s = cpl_parameter_get_string(p);
460  aParams->combine =
461  (!strcasecmp(aParams->combine_s, "average")) ? MUSE_BIAS_PARAM_COMBINE_AVERAGE :
462  (!strcasecmp(aParams->combine_s, "median")) ? MUSE_BIAS_PARAM_COMBINE_MEDIAN :
463  (!strcasecmp(aParams->combine_s, "minmax")) ? MUSE_BIAS_PARAM_COMBINE_MINMAX :
464  (!strcasecmp(aParams->combine_s, "sigclip")) ? MUSE_BIAS_PARAM_COMBINE_SIGCLIP :
465  MUSE_BIAS_PARAM_COMBINE_INVALID_VALUE;
466  cpl_ensure_code(aParams->combine != MUSE_BIAS_PARAM_COMBINE_INVALID_VALUE,
467  CPL_ERROR_ILLEGAL_INPUT);
468 
469  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.nlow");
470  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
471  aParams->nlow = cpl_parameter_get_int(p);
472 
473  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.nhigh");
474  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
475  aParams->nhigh = cpl_parameter_get_int(p);
476 
477  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.nkeep");
478  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
479  aParams->nkeep = cpl_parameter_get_int(p);
480 
481  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.lsigma");
482  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
483  aParams->lsigma = cpl_parameter_get_double(p);
484 
485  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.hsigma");
486  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
487  aParams->hsigma = cpl_parameter_get_double(p);
488 
489  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.losigmabadpix");
490  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
491  aParams->losigmabadpix = cpl_parameter_get_double(p);
492 
493  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.hisigmabadpix");
494  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
495  aParams->hisigmabadpix = cpl_parameter_get_double(p);
496 
497  p = cpl_parameterlist_find(aParameters, "muse.muse_bias.merge");
498  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
499  aParams->merge = cpl_parameter_get_bool(p);
500 
501  return 0;
502 } /* muse_bias_params_fill() */
503 
504 /*----------------------------------------------------------------------------*/
511 /*----------------------------------------------------------------------------*/
512 static int
513 muse_bias_exec(cpl_plugin *aPlugin)
514 {
515  if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
516  return -1;
517  }
518  cpl_recipe *recipe = (cpl_recipe *)aPlugin;
519  cpl_msg_set_threadid_on();
520 
521  cpl_frameset *usedframes = cpl_frameset_new(),
522  *outframes = cpl_frameset_new();
523  muse_bias_params_t params;
524  muse_bias_params_fill(&params, recipe->parameters);
525 
526  cpl_errorstate prestate = cpl_errorstate_get();
527 
528  if (params.nifu < -1 || params.nifu > kMuseNumIFUs) {
529  cpl_msg_error(__func__, "Please specify a valid IFU number (between 1 and "
530  "%d), 0 (to process all IFUs consecutively), or -1 (to "
531  "process all IFUs in parallel) using --nifu.", kMuseNumIFUs);
532  return -1;
533  } /* if invalid params.nifu */
534 
535  cpl_boolean donotmerge = CPL_FALSE; /* depending on nifu we may not merge */
536  int rc = 0;
537  if (params.nifu > 0) {
538  muse_processing *proc = muse_processing_new("muse_bias",
539  recipe);
540  rc = muse_bias_compute(proc, &params);
541  cpl_frameset_join(usedframes, proc->usedframes);
542  cpl_frameset_join(outframes, proc->outframes);
544  donotmerge = CPL_TRUE; /* after processing one IFU, merging cannot work */
545  } else if (params.nifu < 0) { /* parallel processing */
546  int *rcs = cpl_calloc(kMuseNumIFUs, sizeof(int));
547  int nifu;
548  #pragma omp parallel for default(none) \
549  shared(outframes, params, rcs, recipe, usedframes)
550  for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
551  muse_processing *proc = muse_processing_new("muse_bias",
552  recipe);
553  muse_bias_params_t *pars = cpl_malloc(sizeof(muse_bias_params_t));
554  memcpy(pars, &params, sizeof(muse_bias_params_t));
555  pars->nifu = nifu;
556  int *rci = rcs + (nifu - 1);
557  *rci = muse_bias_compute(proc, pars);
558  if (rci && cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
559  *rci = 0;
560  }
561  cpl_free(pars);
562  #pragma omp critical(muse_processing_used_frames)
563  cpl_frameset_join(usedframes, proc->usedframes);
564  #pragma omp critical(muse_processing_output_frames)
565  cpl_frameset_join(outframes, proc->outframes);
567  } /* for nifu */
568  /* non-parallel loop to propagate the "worst" return code; *
569  * since we only ever return -1, any non-zero code is propagated */
570  for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
571  if (rcs[nifu-1] != 0) {
572  rc = rcs[nifu-1];
573  } /* if */
574  } /* for nifu */
575  cpl_free(rcs);
576  } else { /* serial processing */
577  for (params.nifu = 1; params.nifu <= kMuseNumIFUs && !rc; params.nifu++) {
578  muse_processing *proc = muse_processing_new("muse_bias",
579  recipe);
580  rc = muse_bias_compute(proc, &params);
581  if (rc && cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
582  rc = 0;
583  }
584  cpl_frameset_join(usedframes, proc->usedframes);
585  cpl_frameset_join(outframes, proc->outframes);
587  } /* for nifu */
588  } /* else */
589  UNUSED_ARGUMENT(donotmerge); /* maybe this is not going to be used below */
590 
591  if (!cpl_errorstate_is_equal(prestate)) {
592  /* dump all errors from this recipe in chronological order */
593  cpl_errorstate_dump(prestate, CPL_FALSE, muse_cplerrorstate_dump_some);
594  /* reset message level to not get the same errors displayed again by esorex */
595  cpl_msg_set_level(CPL_MSG_INFO);
596  }
597  /* clean up duplicates in framesets of used and output frames */
600 
601  /* merge output products from the up to 24 IFUs */
602  if (params.merge && !donotmerge) {
603  muse_utils_frameset_merge_frames(outframes);
604  }
605 
606  /* to get esorex to see our classification (frame groups etc.), *
607  * replace the original frameset with the list of used frames *
608  * before appending product output frames */
609  /* keep the same pointer, so just erase all frames, not delete the frameset */
610  muse_cplframeset_erase_all(recipe->frames);
611  cpl_frameset_join(recipe->frames, usedframes);
612  cpl_frameset_join(recipe->frames, outframes);
613  cpl_frameset_delete(usedframes);
614  cpl_frameset_delete(outframes);
615  return rc;
616 } /* muse_bias_exec() */
617 
618 /*----------------------------------------------------------------------------*/
625 /*----------------------------------------------------------------------------*/
626 static int
627 muse_bias_destroy(cpl_plugin *aPlugin)
628 {
629  /* Get the recipe from the plugin */
630  cpl_recipe *recipe;
631  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
632  recipe = (cpl_recipe *)aPlugin;
633  } else {
634  return -1;
635  }
636 
637  /* Clean up */
638  cpl_parameterlist_delete(recipe->parameters);
640  return 0;
641 } /* muse_bias_destroy() */
642 
643 /*----------------------------------------------------------------------------*/
653 /*----------------------------------------------------------------------------*/
654 int
655 cpl_plugin_get_info(cpl_pluginlist *aList)
656 {
657  cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
658  cpl_plugin *plugin = &recipe->interface;
659 
660  char *helptext;
662  helptext = cpl_sprintf("%s%s", muse_bias_help,
663  muse_bias_help_esorex);
664  } else {
665  helptext = cpl_sprintf("%s", muse_bias_help);
666  }
667 
668  /* Initialize the CPL plugin stuff for this module */
669  cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
670  CPL_PLUGIN_TYPE_RECIPE,
671  "muse_bias",
672  "Combine several separate bias images into one master bias file.",
673  helptext,
674  "Peter Weilbacher",
675  "usd-help@eso.org",
677  muse_bias_create,
678  muse_bias_exec,
679  muse_bias_destroy);
680  cpl_pluginlist_append(aList, plugin);
681  cpl_free(helptext);
682 
683  return 0;
684 } /* cpl_plugin_get_info() */
685 
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:84
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 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.
int merge
Merge output products from different IFUs into a common file.
Definition: muse_bias_z.h:91
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.