OMEGA Pipeline Reference Manual  1.0.6
omega_readnoise.c
1 /* $Id: omega_readnoise.c,v 1.3 2012-03-26 08:42:09 agabasch Exp $
2  *
3  * This file is part of the OMEGA Pipeline
4  * Copyright (C) 2002,2003 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: agabasch $
23  * $Date: 2012-03-26 08:42:09 $
24  * $Revision: 1.3 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 /*-----------------------------------------------------------------------------
33  Includes
34  -----------------------------------------------------------------------------*/
35 
36 #include "omega_recipe.h"
37 
38 /*----------------------------------------------------------------------------*/
59 /*----------------------------------------------------------------------------*/
62 /*-----------------------------------------------------------------------------
63  Functions prototypes
64  -----------------------------------------------------------------------------*/
65 
66 static int omega_readnoise_create(cpl_plugin *) ;
67 static int omega_readnoise_exec(cpl_plugin *) ;
68 static int omega_readnoise_destroy(cpl_plugin *) ;
69 static int omega_readnoise(cpl_frameset *,cpl_parameterlist *) ;
70 
71 /*-----------------------------------------------------------------------------
72  Private Functions
73  -----------------------------------------------------------------------------*/
74 int omega_readnoise_save(cpl_frameset *set, cpl_parameterlist *parlist);
75 static void omega_readnoise_init(void);
76 static void omega_readnoise_tidy(void);
77 
78 static struct {
79  /* Inputs. Parameters */
80  float rej_sig;
81  int niter;
82  int extnum;
83  int paf;
84 
85  /* Outputs. QC parameters */
86  double rnoise;
87  double mean_diff;
88  double median_diff;
89  double RawBias1Min;
90  double RawBias1Max;
91  double RawBias1Mean;
92  double RawBias1Median;
93  double RawBias1Stdev;
94 
95  double RawBias2Min;
96  double RawBias2Max;
97  double RawBias2Mean;
98  double RawBias2Median;
99  double RawBias2Stdev;
100 
101 }omega_readnoise_config;
102 
103 static struct {
104  cpl_size *labels;
105  cpl_frameset *biaslist;
106  omega_fits *biasfits1;
107  omega_fits *biasfits2;
108  cpl_stats *stats;
109 
110  /*Products*/
111  cpl_table *table;
112 } ps;
113 
114 /* Static variables */
115 
116 /* Static variables */
117 #define RECIPE "omega_readnoise"
118 
119 static cpl_frame *product_frame = NULL;
120 static int isfirst;
121 static char outfile[100];
122 static char outpaf[100];
123 static const char *PROCATG = OMEGA_CALIB_RDNOISE;
124 
125 
126 /*----------------------------------------------------------------------------*/
134 /*----------------------------------------------------------------------------*/
135 int cpl_plugin_get_info(cpl_pluginlist * list)
136 {
137  cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe)) ;
138  cpl_plugin * plugin = &recipe->interface ;
139 
140  cpl_plugin_init(plugin,
141  CPL_PLUGIN_API,
142  OMEGA_BINARY_VERSION,
143  CPL_PLUGIN_TYPE_RECIPE,
144  "omega_readnoise",
145  "OMEGA - Calculate the read noise of the detector.",
146  "The read_noise is computed by subtracting two raw bias images, \n"
147  "and dividing the standard deviation by sqrt(2). The descriptor \n"
148  "value read_noise will be set to the computed value. The statistics \n"
149  "of the difference between the raw biases is computed iteratively. Bad \n"
150  "pixels are rejected if they differ more than process_params.REJECTION_THRESHOLD \n"
151  "sigma from the median. The maximum number of iteration is \n"
152  "process_params.MAXIMUM_ITERATIONS.",
153  "Sandra Castro",
154  "scastro@eso.org",
156  omega_readnoise_create,
157  omega_readnoise_exec,
158  omega_readnoise_destroy) ;
159 
160  cpl_pluginlist_append(list, plugin) ;
161 
162  return 0;
163 }
164 
165 /*----------------------------------------------------------------------------*/
174 /*----------------------------------------------------------------------------*/
175 static int omega_readnoise_create(cpl_plugin * plugin)
176 {
177  cpl_recipe * recipe;
178  cpl_parameter * p ;
179 
180  /* Do not create the recipe if an error code is already set */
181  if (cpl_error_get_code() != CPL_ERROR_NONE) {
182  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
183  cpl_func, __LINE__, cpl_error_get_where());
184  return (int)cpl_error_get_code();
185  }
186 
187  if (plugin == NULL) {
188  cpl_msg_error(cpl_func, "Null plugin");
189  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
190  }
191 
192  /* Verify plugin type */
193  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
194  cpl_msg_error(cpl_func, "Plugin is not a recipe");
195  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
196  }
197 
198  /* Get the recipe */
199  recipe = (cpl_recipe *)plugin;
200 
201  /* Create the parameters list in the cpl_recipe object */
202  recipe->parameters = cpl_parameterlist_new() ;
203 
204  if (recipe->parameters == NULL) {
205  cpl_msg_error(cpl_func, "Parameter list allocation failed");
206  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
207  }
208 
209  /* Fill the parameters list */
210  p = cpl_parameter_new_value("omega.omega_readnoise.ExtensionNumber",
211  CPL_TYPE_INT,
212  "FITS extension number to load (1 to 32). (-1 = all)",
213  "omega_readnoise",
214  -1) ;
215 
216  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"ext") ;
217  cpl_parameterlist_append(recipe->parameters, p) ;
218 
219  p = cpl_parameter_new_value("omega.omega_readnoise.PAF",
220  CPL_TYPE_BOOL,
221  "Boolean value to create PAF files. 1(Yes), 0(No)",
222  "omega_readnoise",
223  0) ;
224 
225  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "paf") ;
226  cpl_parameterlist_append(recipe->parameters, p) ;
227 
228  p = cpl_parameter_new_range("omega.omega_readnoise.NumberIter",
229  CPL_TYPE_INT,
230  "Maximum number of iterations",
231  "omega_readnoise",
232  5, 2, 10) ;
233 
234  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"niter") ;
235  cpl_parameterlist_append(recipe->parameters, p) ;
236 
237 
238  p = cpl_parameter_new_range("omega.omega_readnoise.RejSigma",
239  CPL_TYPE_DOUBLE,
240  "Sigma Clipping Threshold",
241  "omega_readnoise",
242  5.0, 1.0, 10.0) ;
243 
244  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sig-clip") ;
245  cpl_parameterlist_append(recipe->parameters, p) ;
246 
247 
248  /* Return */
249  return 0;
250 }
251 
252 
253 /*----------------------------------------------------------------------------*/
259 /*----------------------------------------------------------------------------*/
260 static int omega_readnoise_exec(cpl_plugin * plugin)
261 {
262  cpl_recipe * recipe;
263  int recipe_status;
264 
265  /* Return immediately if an error code is already set */
266  if (cpl_error_get_code() != CPL_ERROR_NONE) {
267  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
268  cpl_func, __LINE__, cpl_error_get_where());
269  return (int)cpl_error_get_code();
270  }
271 
272  if (plugin == NULL) {
273  cpl_msg_error(cpl_func, "Null plugin");
274  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
275  }
276 
277  /* Verify plugin type */
278  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
279  cpl_msg_error(cpl_func, "Plugin is not a recipe");
280  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
281  }
282 
283  /* Get the recipe */
284  recipe = (cpl_recipe *)plugin;
285 
286  /* Verify parameter and frame lists */
287  if (recipe->parameters == NULL) {
288  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
289  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
290  }
291  if (recipe->frames == NULL) {
292  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
293  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
294  }
295 
296  /* Invoke the recipe */
297  recipe_status = omega_readnoise(recipe->frames, recipe->parameters);
298 
299  /* Ensure DFS-compliance of the products */
300  if (cpl_dfs_update_product_header(recipe->frames)) {
301  if (!recipe_status) recipe_status = (int)cpl_error_get_code();
302  }
303 
304  return recipe_status;
305 
306 }
307 
308 /*----------------------------------------------------------------------------*/
314 /*----------------------------------------------------------------------------*/
315 static int omega_readnoise_destroy(cpl_plugin * plugin)
316 {
317  cpl_recipe *recipe;
318 
319  if (plugin == NULL) {
320  cpl_msg_error(cpl_func, "Null plugin");
321  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
322  }
323 
324  /* Verify plugin type */
325  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
326  cpl_msg_error(cpl_func, "Plugin is not a recipe");
327  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
328  }
329 
330  /* Get the recipe */
331  recipe = (cpl_recipe *)plugin;
332 
333  cpl_parameterlist_delete(recipe->parameters);
334 
335  return 0 ;
336 }
337 
338 
339 /**********************************************************************/
347 /*--------------------------------------------------------------------------*/
348 
349 static int omega_readnoise(cpl_frameset *set,cpl_parameterlist *pars)
350 {
351 
352  int j,jst,jfn,live;
353  cpl_size nlab;
354  float stdev = 0.0;
355 
356  const char *_id = "omega_readnoise";
357  const char *chipid = NULL;
358 
359  const cpl_frame *bias1, *bias2;
360  const cpl_image *rawbiasfits1, *rawbiasfits2=NULL;
361  cpl_image *biasim;
362  cpl_parameter *par;
363  cpl_propertylist *plist;
364 
365 
366  /*Start the recipe */
367 
368  if (pars == NULL) {
369  cpl_msg_error (_id, "Parameters list not found");
370  return -1;
371  }
372 
373  if (cpl_frameset_is_empty(set) == 1) {
374  cpl_msg_error (_id, "Frameset not found");
375  return -1;
376  }
377 
378 /* Initialise a few things */
379 
380  omega_readnoise_init();
381 
382 
383 /* Retrieve input parameters */
384 
385  par = cpl_parameterlist_find(pars, "omega.omega_readnoise.ExtensionNumber") ;
386  omega_readnoise_config.extnum = cpl_parameter_get_int(par) ;
387 
388  par = cpl_parameterlist_find(pars, "omega.omega_readnoise.NumberIter") ;
389  omega_readnoise_config.niter = cpl_parameter_get_int(par) ;
390 
391  par = cpl_parameterlist_find(pars, "omega.omega_readnoise.RejSigma") ;
392  omega_readnoise_config.rej_sig = cpl_parameter_get_double(par) ;
393 
394  par = cpl_parameterlist_find(pars, "omega.omega_readnoise.PAF") ;
395  omega_readnoise_config.paf = cpl_parameter_get_bool(par) ;
396 
397 /* Identify the RAW and CALIB frames in the input frameset */
398  if (oc_dfs_set_groups(set)) {
399  cpl_msg_error(_id, "Cannot identify RAW and CALIB frames") ;
400  omega_readnoise_tidy();
401  return -1 ;
402  }
403 
404 /* Verify the frameset contents. */
405 /*Make sure there are at least 2 bias */
406 
407  if ((ps.labels = cpl_frameset_labelise(set,omega_compare_tags,
408  &nlab)) == NULL) {
409  cpl_msg_error(_id,"Cannot labelise the input frameset");
410  omega_readnoise_tidy();
411  return -1;
412  }
413  if ((ps.biaslist = omega_frameset_subgroup(set,ps.labels,nlab,
414  RNOISE_RAW)) == NULL) {
415  cpl_msg_error(_id,"Cannot find bias frames in input frameset");
416  omega_readnoise_tidy();
417  return -1;
418  }
419  if (cpl_frameset_get_size(ps.biaslist) < 2) {
420  cpl_msg_error(_id,"Need exactly 2 (%s) frames to run this recipe",RNOISE_RAW);
421  omega_readnoise_tidy();
422  return -1;
423  }
424 
425  /* Set up some convenience variables */
426  bias1 = cpl_frameset_get_position_const(ps.biaslist,0);
427  bias2 = cpl_frameset_get_position_const(ps.biaslist,1);
428 
429  cpl_msg_info (_id,"Using %s frames: %s and %s",RNOISE_RAW,cpl_frame_get_filename(bias1),
430  cpl_frame_get_filename(bias2));
431 
432 /* Loop for each of the image extensions */
433  omega_exten_range(omega_readnoise_config.extnum,&jst,&jfn);
434  if(omega_readnoise_config.extnum == 0){
435  cpl_msg_error(cpl_func,"Unsupported extension request, %d",omega_readnoise_config.extnum);
436  omega_readnoise_tidy();
437  return -1;
438  }
439 
440  /* Check which instrument */
441  if(omega_pfits_check_instrume(cpl_frameset_get_position_const(set, 0)) == 1 &&
442  omega_readnoise_config.extnum == 0 && jfn == 32)
443  jfn = 8;
444 
445  for (j = jst; j <= jfn; j++) {
446  cpl_msg_info(_id,"Beginning work on extension %d",j);
447  isfirst = (j == jst);
448  omega_readnoise_config.rnoise = 0.0;
449  omega_readnoise_config.mean_diff = 0.0;
450  omega_readnoise_config.median_diff = 0.0;
451  omega_readnoise_config.RawBias1Min=0.;
452  omega_readnoise_config.RawBias1Max=0.;
453  omega_readnoise_config.RawBias1Mean=0.;
454  omega_readnoise_config.RawBias1Median=0.;
455  omega_readnoise_config.RawBias1Stdev=0.;
456  omega_readnoise_config.RawBias2Min=0.;
457  omega_readnoise_config.RawBias2Max=0.;
458  omega_readnoise_config.RawBias2Mean=0.;
459  omega_readnoise_config.RawBias2Median=0.;
460  omega_readnoise_config.RawBias2Stdev=0.;
461 
462  ps.biasfits1 = omega_fits_load(bias1,CPL_TYPE_FLOAT,j);
463  ps.biasfits2 = omega_fits_load(bias2,CPL_TYPE_FLOAT,j);
464 
465  if (ps.biasfits1 == NULL || ps.biasfits2 == NULL) {
466  cpl_msg_error(_id,"NULL image input for extension %d",j);
467  /*save dummy extension*/
468  freefits(ps.biasfits1);
469  freefits(ps.biasfits2);
470  continue;
471  }
472 
473 
474  /* Check that this detector is live*/
475  plist = cpl_propertylist_load(cpl_frame_get_filename(bias1),j);
476  omega_pfits_get_detlive(plist,&live);
477  if (! live) {
478  cpl_msg_warning(_id,"First bias image detector not live");
479  /*save dummy extension*/
480  freefits(ps.biasfits1);
481  freefits(ps.biasfits2);
482  freeplist(plist);
483  continue;
484  }
485  freeplist(plist);
486 
487  plist = cpl_propertylist_load(cpl_frame_get_filename(bias2),j);
488  omega_pfits_get_detlive(plist,&live);
489  if (! live) {
490  cpl_msg_warning(_id,"Second bias image detector not live");
491  /*save dummy extension*/
492  freefits(ps.biasfits1);
493  freefits(ps.biasfits2);
494  freeplist(plist);
495  continue;
496  }
497  freeplist(plist);
498 
499  /* Get the raw images and derive some QC parameter */
500 
501  rawbiasfits1=omega_fits_get_image(ps.biasfits1);
502  rawbiasfits2=omega_fits_get_image(ps.biasfits2);
503  omega_readnoise_config.RawBias1Min =cpl_image_get_min(rawbiasfits1);
504  omega_readnoise_config.RawBias1Max =cpl_image_get_max(rawbiasfits1);
505  omega_readnoise_config.RawBias1Mean =cpl_image_get_mean(rawbiasfits1);
506  omega_readnoise_config.RawBias1Median=cpl_image_get_median(rawbiasfits1);
507  omega_readnoise_config.RawBias1Stdev =cpl_image_get_stdev(rawbiasfits1);
508  omega_readnoise_config.RawBias2Min =cpl_image_get_min(rawbiasfits2);
509  omega_readnoise_config.RawBias2Max =cpl_image_get_max(rawbiasfits2);
510  omega_readnoise_config.RawBias2Mean =cpl_image_get_mean(rawbiasfits2);
511  omega_readnoise_config.RawBias2Median=cpl_image_get_median(rawbiasfits2);
512  omega_readnoise_config.RawBias2Stdev =cpl_image_get_stdev(rawbiasfits2);
513 
514 
515  /* Get the difference image */
516  biasim = cpl_image_subtract_create(omega_fits_get_image(ps.biasfits1),
517  omega_fits_get_image(ps.biasfits2));
518 
519  freefits(ps.biasfits2);
520 
521  /*Calculate statistics iteratively*/
522  ps.stats = omega_iter_stat(biasim,omega_readnoise_config.rej_sig,omega_readnoise_config.niter);
523 
524  /* Now the read noise */
525  if(ps.stats != NULL){
526  stdev = cpl_stats_get_stdev(ps.stats);
527  omega_readnoise_config.rnoise = stdev / sqrt(2);
528  omega_readnoise_config.mean_diff = cpl_stats_get_mean(ps.stats);
529  omega_readnoise_config.median_diff = cpl_stats_get_median(ps.stats);
530  }
531  else{
532  cpl_msg_warning(_id,"Cannot calculate statistics iteratively");
533  }
534 
535  plist = cpl_propertylist_load(cpl_frame_get_filename(bias1),j);
536  chipid = omega_pfits_get_chipid(plist);
537 
538  cpl_msg_info(_id,"The read noise of %s is: %5.3g", chipid, omega_readnoise_config.rnoise);
539  cpl_msg_info(_id,"Difference between bias frames is: %5.3g (mean), %5.3g (median)",
540  omega_readnoise_config.mean_diff, omega_readnoise_config.median_diff);
541 
542  freeimage(biasim);
543  freestats(ps.stats);
544  freeplist(plist);
545 
546  /* Create the product */
547  ps.table = cpl_table_new(1);
548  cpl_table_new_column(ps.table, "READNOISE", CPL_TYPE_DOUBLE);
549  cpl_table_new_column(ps.table, "MEAN_DIFF", CPL_TYPE_DOUBLE);
550  cpl_table_new_column(ps.table, "MEDIAN_DIFF", CPL_TYPE_DOUBLE);
551  cpl_table_set_double(ps.table, "READNOISE", 0, omega_readnoise_config.rnoise);
552  cpl_table_set_double(ps.table, "MEAN_DIFF", 0, omega_readnoise_config.mean_diff);
553  cpl_table_set_double(ps.table, "MEDIAN_DIFF", 0, omega_readnoise_config.median_diff);
554 
555  /* Save the product */
556  if(omega_readnoise_save(set, pars) == -1){
557  cpl_msg_error(_id,"Cannot save this extension product");
558  omega_readnoise_tidy();
559  return -1;
560  }
561 
562  freefits(ps.biasfits1);
563  freetable(ps.table);
564  } /* Work on next extension */
565 
566  omega_readnoise_tidy();
567 
568  return 0;
569 
570 }
571 
572 /*----------------------------------------------------------------------------*/
581 /*----------------------------------------------------------------------------*/
582 int omega_readnoise_save(cpl_frameset *set,
583  cpl_parameterlist *parlist)
584 {
585 
586  const char *fctid = "omega_readnoise_save";
587  cpl_propertylist *plist;
588  cpl_propertylist *qclist;
589 
590 
591  /* If it is the first time, setup initial frame */
592  if (isfirst) {
593 
594  /* Get the name of the instrument */
595  if(omega_pfits_check_instrume(cpl_frameset_get_position_const(set, 0)) == 1)
596  sprintf(INSTRUME,"wfi");
597 
598  /* Set the file name*/
599  sprintf(outfile, "%s_%s.fits",INSTRUME,PROCATG) ;
600 
601  /* Create a new product frame object and define some tags */
602  product_frame = cpl_frame_new();
603  cpl_frame_set_filename(product_frame,outfile);
604  cpl_frame_set_tag(product_frame,PROCATG);
605  cpl_frame_set_type(product_frame,CPL_FRAME_TYPE_TABLE);
606  cpl_frame_set_group(product_frame,CPL_FRAME_GROUP_PRODUCT);
607  cpl_frame_set_level(product_frame,CPL_FRAME_LEVEL_FINAL);
608 
609  plist = cpl_propertylist_new();
610 
611  /* Add DataFlow keywords in primary header */
612  if (cpl_dfs_setup_product_header(plist, product_frame, set, parlist,
613  RECIPE,PIPEID,DICID,NULL) != CPL_ERROR_NONE) {
614 
615  cpl_msg_warning(fctid, "Problem in the main header of product DFS-compliance") ;
616  }
617 
618  /* Once CPL recalculates these values, the following
619  * line should be removed
620  */
621  cpl_propertylist_erase_regexp(plist,REM_PRIM_KEYS,0);
622 
623  /* Save the empty primary unit */
624  if (cpl_propertylist_save(plist,outfile,CPL_IO_DEFAULT) != CPL_ERROR_NONE){
625  cpl_msg_error(fctid,"Cannot save product PHU");
626  cpl_frame_delete(product_frame);
627  freeplist(plist);
628  return -1;
629  }
630 
631  freeplist(plist);
632  cpl_frameset_insert(set,product_frame);
633  }
634 
635  /* Setup the extension */
636  plist = cpl_propertylist_duplicate(omega_fits_get_ehu(ps.biasfits1));
637  qclist = cpl_propertylist_new();
638 
639  /* Add DataFlow keywords in extension header */
640  if (cpl_dfs_setup_product_header(plist, product_frame, set, parlist,
641  RECIPE,PIPEID,DICID,NULL) != CPL_ERROR_NONE) {
642 
643  cpl_msg_warning(fctid, "Problem in the extension header of product DFS-compliance") ;
644  }
645 
646  /*Remove undesired keywords from extension header*/
647  cpl_propertylist_erase_regexp(plist, REM_EXT_KEYS, 0);
648 
649 
650  /* Now add the QC data... */
651 
652  cpl_propertylist_update_float(qclist,"ESO QC READNOISE",
653  omega_readnoise_config.rnoise);
654  cpl_propertylist_update_float(qclist,"ESO QC READNOISE MEAN DIFF",
655  omega_readnoise_config.mean_diff);
656  cpl_propertylist_update_float(qclist,"ESO QC READNOISE MEDIAN DIFF",
657  omega_readnoise_config.median_diff);
658 
659  cpl_propertylist_update_float(qclist,"ESO QC RAW BIAS1 MIN" , omega_readnoise_config.RawBias1Min );
660  cpl_propertylist_update_float(qclist,"ESO QC RAW BIAS1 MAX" , omega_readnoise_config.RawBias1Max );
661  cpl_propertylist_update_float(qclist,"ESO QC RAW BIAS1 MEAN" , omega_readnoise_config.RawBias1Mean );
662  cpl_propertylist_update_float(qclist,"ESO QC RAW BIAS1 MEDIAN", omega_readnoise_config.RawBias1Median);
663  cpl_propertylist_update_float(qclist,"ESO QC RAW BIAS1 STDEV" , omega_readnoise_config.RawBias1Stdev );
664  cpl_propertylist_update_float(qclist,"ESO QC RAW BIAS2 MIN" , omega_readnoise_config.RawBias2Min );
665  cpl_propertylist_update_float(qclist,"ESO QC RAW BIAS2 MAX" , omega_readnoise_config.RawBias2Max );
666  cpl_propertylist_update_float(qclist,"ESO QC RAW BIAS2 MEAN" , omega_readnoise_config.RawBias2Mean );
667  cpl_propertylist_update_float(qclist,"ESO QC RAW BIAS2 MEDIAN", omega_readnoise_config.RawBias2Median);
668  cpl_propertylist_update_float(qclist,"ESO QC RAW BIAS2 STDEV ", omega_readnoise_config.RawBias2Stdev );
669 
670  cpl_propertylist_set_comment(qclist,"ESO QC RAW BIAS1 MIN" , "minimum value of first frame");
671  cpl_propertylist_set_comment(qclist,"ESO QC RAW BIAS1 MAX" , "maximum value of first frame");
672  cpl_propertylist_set_comment(qclist,"ESO QC RAW BIAS1 MEAN" , "mean value of first frame");
673  cpl_propertylist_set_comment(qclist,"ESO QC RAW BIAS1 MEDIAN", "median value of first frame");
674  cpl_propertylist_set_comment(qclist,"ESO QC RAW BIAS1 STDEV" , "standard deviation of first frame");
675  cpl_propertylist_set_comment(qclist,"ESO QC RAW BIAS2 MIN" , "minimum value of second frame");
676  cpl_propertylist_set_comment(qclist,"ESO QC RAW BIAS2 MAX" , "maximum value of second frame");
677  cpl_propertylist_set_comment(qclist,"ESO QC RAW BIAS2 MEAN" , "mean value of second frame");
678  cpl_propertylist_set_comment(qclist,"ESO QC RAW BIAS2 MEDIAN", "median value of second frame");
679  cpl_propertylist_set_comment(qclist,"ESO QC RAW BIAS2 STDEV ", "standard deviation of second frame");
680 
681  /* Append it to the extension header */
682  cpl_propertylist_append(plist, qclist);
683 
684  /* Add comments to QC parameters in extension header*/
685  cpl_propertylist_set_comment(plist,"ESO QC READNOISE",
686  "Calculated detector readnoise");
687  cpl_propertylist_set_comment(plist,"ESO QC READNOISE MEAN DIFF",
688  "Calculated mean of difference");
689  cpl_propertylist_set_comment(plist,"ESO QC READNOISE MEDIAN DIFF",
690  "Calculated median of difference");
691 
692  /* 'Save' the product */
693  if (cpl_table_save(ps.table,NULL,plist,outfile,CPL_IO_EXTEND) != CPL_ERROR_NONE) {
694  cpl_msg_error(fctid,"Cannot save product. %s", cpl_error_get_message());
695  freeplist(plist);
696  freeplist(qclist);
697  return -1;
698  }
699  /* Save the paf file */
700  if(omega_readnoise_config.paf){
701  int xtnum = omega_fits_get_extnum(ps.biasfits1);
702  const char pafcopy[] = "^(DATE-OBS|ARCFILE|ESO TPL ID|ESO DET WIN1 DIT1|MJD-OBS|EXTNAME|ESO PRO CATG)$";
703  sprintf(outpaf, "%s_%s_%d.paf",INSTRUME,PROCATG,xtnum) ;
704  cpl_frame *fframe = cpl_frameset_get_position(set, 0);
705  cpl_propertylist *mlist = cpl_propertylist_load_regexp(cpl_frame_get_filename(fframe),0,pafcopy, 0);
706  cpl_propertylist_copy_property_regexp(qclist, mlist, pafcopy, 0);
707  if(cpl_propertylist_copy_property_regexp(qclist, plist,
708  pafcopy, 0) != CPL_ERROR_NONE){
709  cpl_msg_warning(fctid,"Some mandatory keywords are missing in PAF file");
710  }
711 
712  cpl_dfs_save_paf(INSTRUME, RECIPE, qclist, outpaf);
713  freeplist(mlist);
714  }
715 
716  freeplist(plist);
717  freeplist(qclist);
718 
719  return 0;
720 }
721 
722 
723 /*---------------------------------------------------------------------------*/
727 /*---------------------------------------------------------------------------*/
728 
729 static void omega_readnoise_init(void) {
730  ps.labels = NULL;
731  ps.biaslist = NULL;
732  ps.biasfits1 = NULL;
733  ps.biasfits2 = NULL;
734  ps.stats = NULL;
735  ps.table = NULL;
736  return;
737 }
738 
739 /*---------------------------------------------------------------------------*/
743 /*---------------------------------------------------------------------------*/
744 
745 static void omega_readnoise_tidy(void) {
746  freespace(ps.labels);
747  freeframeset(ps.biaslist);
748  freefits(ps.biasfits1);
749  freefits(ps.biasfits2);
750  freetable(ps.table);
751  freestats(ps.stats);
752  return;
753 }
cpl_stats * omega_iter_stat(cpl_image *img, double threshold, int iter)
Compute statistics of an image iteratively.
Definition: omega_stats.c:83
int omega_pfits_get_detlive(const cpl_propertylist *plist, int *detlive)
Get the value of DET_LIVE.
Definition: omega_pfits.c:214
cpl_image * omega_fits_get_image(omega_fits *p)
Definition: omega_fits.c:381
int omega_readnoise_save(cpl_frameset *set, cpl_parameterlist *parlist)
Save the omega_readnoise recipe products on disk.
int omega_compare_tags(const cpl_frame *frame1, const cpl_frame *frame2)
Definition: omega_utils.c:206
int omega_pfits_check_instrume(const cpl_frame *fr)
Check if INSTRUME is WFI or OMEGA.
Definition: omega_pfits.c:785
omega_fits * omega_fits_load(const cpl_frame *inframe, cpl_type type, int extnum)
Definition: omega_fits.c:84
int omega_fits_get_extnum(omega_fits *p)
Definition: omega_fits.c:414
const char * omega_get_license(void)
Get the pipeline copyright and license.
Definition: omega_utils.c:67
void omega_exten_range(int inexten, int *out1, int *out2)
Definition: omega_utils.c:305
cpl_propertylist * omega_fits_get_ehu(omega_fits *p)
Definition: omega_fits.c:489
const char * omega_pfits_get_chipid(const cpl_propertylist *plist)
Get CHIP ID from header.
Definition: omega_pfits.c:1044
cpl_frameset * omega_frameset_subgroup(cpl_frameset *frameset, cpl_size *labels, cpl_size nlab, const char *tag)
Definition: omega_utils.c:257
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.