OMEGA Pipeline Reference Manual  1.0.5
omega_mbias.c
1 /* $Id: omega_mbias.c,v 1.3 2012-08-30 07:46:52 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-08-30 07:46:52 $
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 
59 /*-----------------------------------------------------------------------------
60  Functions prototypes
61  -----------------------------------------------------------------------------*/
62 
63 static int omega_mbias_create(cpl_plugin *) ;
64 static int omega_mbias_exec(cpl_plugin *) ;
65 static int omega_mbias_destroy(cpl_plugin *) ;
66 static int omega_mbias(cpl_frameset *,cpl_parameterlist *) ;
67 
68 /*-----------------------------------------------------------------------------
69  Private Functions
70  -----------------------------------------------------------------------------*/
71 int omega_mbias_combine(int xn);
72 static void omega_mbias_init(void);
73 static void omega_mbias_tidy(void);
74 
75 /*-----------------------------------------------------------------------------
76  Static structures
77  -----------------------------------------------------------------------------*/
78 
79 static struct {
80  /* Inputs. Parameters */
81  float rejsig;
82  double sigma;
83  int extnum;
84  int oc;
85  int paf;
86 
87  /* Outputs. QC parameters */
88  int CountHotPixels;
89  double Mean;
90  double Median;
91  double Stdev;
92 
93 }omega_mbias_config;
94 
95 
96 /* Input and Output */
97 static struct {
98  cpl_size *labels;
99  const cpl_frame *rnframe;
100  cpl_frameset *biaslist;
101  cpl_stats *stats;
102  omega_fits *firstbias;
103  cpl_propertylist *ph;
104  cpl_propertylist *eh;
105 
106  /* Products */
107  cpl_image *mbias;
108  cpl_image *hpixels;
109 
110 } ps;
111 
112 /*-----------------------------------------------------------------------------
113  Static variables
114  -----------------------------------------------------------------------------*/
115 
116 /* Static variables */
117 #define RECIPE "omega_mbias"
118 
119 static int isfirst;
120 static int dummy;
121 
122 
123 
134 int cpl_plugin_get_info(cpl_pluginlist * list)
135 {
136  cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe)) ;
137  cpl_plugin * plugin = &recipe->interface ;
138 
139  cpl_plugin_init(plugin,
140  CPL_PLUGIN_API,
141  OMEGA_BINARY_VERSION,
142  CPL_PLUGIN_TYPE_RECIPE,
143  "omega_mbias",
144  "OMEGA - Create Master Bias for each chip.",
145  "Trims and applies overscan correction to the raw input bias \n"
146  "frames. Averages these frames to derive the master bias frame. \n"
147  "Calculates the image statistics on the resulting frame. Creates \n"
148  "the FITS header and saves it together with the FITS image.",
149  "Sandra Castro",
150  "scastro@eso.org",
152  omega_mbias_create,
153  omega_mbias_exec,
154  omega_mbias_destroy) ;
155 
156  cpl_pluginlist_append(list, plugin) ;
157 
158  return 0;
159 }
160 
161 /*----------------------------------------------------------------------------*/
170 /*----------------------------------------------------------------------------*/
171 static int omega_mbias_create(cpl_plugin * plugin)
172 {
173  cpl_recipe * recipe;
174  cpl_parameter * p ;
175 
176  /* Do not create the recipe if an error code is already set */
177  if (cpl_error_get_code() != CPL_ERROR_NONE) {
178  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
179  cpl_func, __LINE__, cpl_error_get_where());
180  return (int)cpl_error_get_code();
181  }
182 
183  if (plugin == NULL) {
184  cpl_msg_error(cpl_func, "Null plugin");
185  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
186  }
187 
188  /* Verify plugin type */
189  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
190  cpl_msg_error(cpl_func, "Plugin is not a recipe");
191  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
192  }
193 
194  /* Get the recipe */
195  recipe = (cpl_recipe *)plugin;
196 
197  /* Create the parameters list in the cpl_recipe object */
198  recipe->parameters = cpl_parameterlist_new() ;
199  if (recipe->parameters == NULL) {
200  cpl_msg_error(cpl_func, "Parameter list allocation failed");
201  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
202  }
203 
204  /* Fill the parameters list */
205  p = cpl_parameter_new_value("omega.omega_mbias.ExtensionNumber",
206  CPL_TYPE_INT,
207  "FITS extension number to load (1 to 32). (-1 = all)",
208  "omega_mbias",
209  -1) ;
210 
211  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"ext") ;
212  cpl_parameterlist_append(recipe->parameters, p) ;
213 
214 
215  p = cpl_parameter_new_range("omega.omega_mbias.OverscanMethod",
216  CPL_TYPE_INT,
217  "Overscan Correction Method",
218  "omega_mbias",
219  0, 0, 6);
220  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"oc-meth") ;
221  cpl_parameterlist_append(recipe->parameters, p) ;
222 
223  p = cpl_parameter_new_value("omega.omega_mbias.PAF",
224  CPL_TYPE_BOOL,
225  "Boolean value to create PAF files. 1(Yes), 0(No)",
226  "omega_mbias",
227  1) ;
228 
229  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "paf") ;
230  cpl_parameterlist_append(recipe->parameters, p) ;
231 
232  p = cpl_parameter_new_value("omega.omega_mbias.SigmaClip",
233  CPL_TYPE_DOUBLE,
234  "Sigma Clipping Threshold for image",
235  "omega_mbias",
236  3.0) ;
237 
238  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"sig-clip") ;
239  cpl_parameterlist_append(recipe->parameters, p) ;
240 
241  p = cpl_parameter_new_range("omega.omega_mbias.RejSigma",
242  CPL_TYPE_DOUBLE,
243  "Rejection threshold for outlying pixels in Hot Pixels Map",
244  "omega_mbias",
245  5.0, 1.0, 10.0) ;
246 
247  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "rej-sigma") ;
248  cpl_parameterlist_append(recipe->parameters, p) ;
249 
250 
251  /* Return */
252  return 0;
253 }
254 
255 /*----------------------------------------------------------------------------*/
261 /*----------------------------------------------------------------------------*/
262 static int omega_mbias_exec(cpl_plugin * plugin)
263 {
264  cpl_recipe * recipe;
265  int recipe_status;
266 /* cpl_errorstate initial_errorstate = cpl_errorstate_get();*/
267 
268  /* Return immediately if an error code is already set */
269  if (cpl_error_get_code() != CPL_ERROR_NONE) {
270  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
271  cpl_func, __LINE__, cpl_error_get_where());
272  return (int)cpl_error_get_code();
273  }
274 
275  if (plugin == NULL) {
276  cpl_msg_error(cpl_func, "Null plugin");
277  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
278  }
279 
280  /* Verify plugin type */
281  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
282  cpl_msg_error(cpl_func, "Plugin is not a recipe");
283  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
284  }
285 
286  /* Get the recipe */
287  recipe = (cpl_recipe *)plugin;
288 
289  /* Verify parameter and frame lists */
290  if (recipe->parameters == NULL) {
291  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
292  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
293  }
294  if (recipe->frames == NULL) {
295  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
296  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
297  }
298 
299  /* Invoke the recipe */
300  recipe_status = omega_mbias(recipe->frames, recipe->parameters);
301 
302  /* Ensure DFS-compliance of the products */
303  if (cpl_dfs_update_product_header(recipe->frames)) {
304  if (!recipe_status) recipe_status = (int)cpl_error_get_code();
305  }
306 
307 
308  return recipe_status;
309 }
310 
311 /*----------------------------------------------------------------------------*/
317 /*----------------------------------------------------------------------------*/
318 static int omega_mbias_destroy(cpl_plugin * plugin)
319 {
320  cpl_recipe * recipe;
321 
322  if (plugin == NULL) {
323  cpl_msg_error(cpl_func, "Null plugin");
324  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
325  }
326 
327  /* Verify plugin type */
328  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
329  cpl_msg_error(cpl_func, "Plugin is not a recipe");
330  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
331  }
332 
333  /* Get the recipe */
334  recipe = (cpl_recipe *)plugin;
335 
336  cpl_parameterlist_delete(recipe->parameters);
337 
338  return 0 ;
339 }
340 
341 /*----------------------------------------------------------------------------*/
348 /*----------------------------------------------------------------------------*/
349 static int omega_mbias(cpl_frameset *set, cpl_parameterlist *pars)
350 {
351 
352  int j,jst,jfn,status;
353  cpl_size nlab;
354  int nbias = 0;
355  char *outhpm = NULL;
356  char *outmbias = NULL;
357 
358  const char *_id = "omega_mbias";
359 
360  cpl_parameter *par;
361  cpl_frame *firstframe;
362  cpl_frame *prframe_mbias = NULL;
363  cpl_frame *prframe_hpm = NULL;
364  const cpl_frame *refframe = NULL;
365  cpl_propertylist *qclist;
366  cpl_propertylist *alist;
367  cpl_stats *diffstats = NULL;
368 
369 
370  /*Start the recipe */
371 
372  if (!pars) {
373  cpl_msg_error (_id, "Parameters list not found");
374  return -1;
375  }
376 
377  if (cpl_frameset_is_empty(set) == 1) {
378  cpl_msg_error (_id, "Frameset not found");
379  return -1;
380  }
381 
382 
383 /* Retrieve input parameters */
384  par = cpl_parameterlist_find(pars, "omega.omega_mbias.ExtensionNumber") ;
385  omega_mbias_config.extnum = cpl_parameter_get_int(par) ;
386 
387  par = cpl_parameterlist_find(pars, "omega.omega_mbias.OverscanMethod") ;
388  omega_mbias_config.oc = cpl_parameter_get_int(par) ;
389 
390  par = cpl_parameterlist_find(pars, "omega.omega_mbias.SigmaClip") ;
391  omega_mbias_config.sigma = cpl_parameter_get_double(par) ;
392 
393  par = cpl_parameterlist_find(pars, "omega.omega_mbias.RejSigma") ;
394  omega_mbias_config.rejsig = cpl_parameter_get_double(par) ;
395 
396  par = cpl_parameterlist_find(pars, "omega.omega_mbias.PAF");
397  omega_mbias_config.paf = cpl_parameter_get_bool(par);
398 
399 
400 
401 /* Identify the RAW and CALIB frames in the input frameset */
402  if (oc_dfs_set_groups(set)) {
403  cpl_msg_error(_id, "Cannot identify RAW and CALIB frames") ;
404  return -1 ;
405  }
406 
407 
408  /*Initialized things*/
409  omega_mbias_init();
410 
411 
412  /* Verify the frameset contents. */
413  if ((ps.labels = cpl_frameset_labelise(set,omega_compare_tags,
414  &nlab)) == NULL) {
415  cpl_msg_error(_id,"Cannot labelise the input frameset");
416  omega_mbias_tidy();
417  return -1;
418  }
419  if ((ps.biaslist = omega_frameset_subgroup(set,ps.labels,nlab,
420  MBIAS_RAW)) == NULL) {
421  cpl_msg_error(_id,"Cannot find bias frames in input frameset");
422  omega_mbias_tidy();
423  return -1;
424  }
425 
426  nbias = cpl_frameset_get_size(ps.biaslist);
427  if (nbias < 2) {
428  cpl_msg_error(_id,"Need at least 2 (%s) frames to run this recipe",MBIAS_RAW);
429  omega_mbias_tidy();
430  return -1;
431  }
432 
433  cpl_msg_info (_id,"There are %d %s in frame set",nbias, MBIAS_RAW);
434 
435  /* Check for calibration frame */
436  /* Readnoise table */
437  ps.rnframe = cpl_frameset_find_const(set, OMEGA_CALIB_RDNOISE);
438  if (ps.rnframe == NULL) {
439  cpl_msg_info(_id,"A Readnoise table is not present in frame set. Using header values");
440  }
441  else{
442  cpl_msg_info(_id,"Using %s %s",OMEGA_CALIB_RDNOISE, cpl_frame_get_filename(ps.rnframe));
443  }
444 
445  /* Get first frame from frame set */
446  firstframe = cpl_frameset_get_first(ps.biaslist);
447 
448  /* Optional reference master bias frame */
449  refframe = cpl_frameset_find_const(set, REFBIAS);
450  if (refframe != NULL)
451  cpl_msg_info(cpl_func,"Using %s for comparison",cpl_frame_get_filename(refframe));
452 
453  /* Loop for each of the image extensions */
454  omega_extensions(firstframe,omega_mbias_config.extnum,&jst,&jfn);
455 
456  if(omega_mbias_config.extnum == 0){
457  cpl_msg_error(cpl_func,"Unsupported extension request, %d",omega_mbias_config.extnum);
458  omega_mbias_tidy();
459  return -1;
460  }
461 
462 
463  /* Check which instrument */
464  if (omega_pfits_check_instrume(firstframe) == 1)
465  sprintf(INSTRUME,"wfi");
466 
467  if(omega_pfits_check_instrume(firstframe) == 1 &&
468  omega_mbias_config.extnum == 0 && jfn == 32){
469  jfn = 8;
470  }
471 
472  for (j = jst; j <= jfn; j++) {
473 
474  isfirst = (j == jst);
475  cpl_msg_info(_id,"Beginning work on extension %d",j);
476  omega_mbias_config.CountHotPixels = 0;
477  omega_mbias_config.Mean = 0.0;
478  omega_mbias_config.Median = 0.0;
479  omega_mbias_config.Stdev = 0.0;
480 
481  ps.firstbias = omega_fits_load(firstframe,CPL_TYPE_FLOAT,j);
482  ps.eh = omega_fits_get_ehu(ps.firstbias);
483 
484  /* Call the combining routine */
485  status = omega_mbias_combine(j);
486  if(status == 1){
487  cpl_msg_warning(_id, "Image detector is not live");
488  /* Save dummy product */
489  freefits(ps.firstbias);
490  ps.eh = NULL;
491  continue;
492  }
493  else if(status == -1){
494  cpl_msg_error(_id,"Cannot combine images");
495  freespace(outhpm);
496  freespace(outmbias);
497  omega_mbias_tidy();
498  return -1;
499  }
500 
501  status = 0;
502 
503  qclist = cpl_propertylist_new();
504 
505  /* Compare with reference frame */
506  if(refframe != NULL){
507  if(omega_compare_reference(ps.mbias,refframe,j,&diffstats) == -1){
508  cpl_msg_warning(cpl_func,"Cannot compare with reference frame");
509  }
510  else{
511  cpl_propertylist_append_double(qclist,"ESO QC DIFF REFBIAS MEAN",
512  cpl_stats_get_mean(diffstats));
513  cpl_propertylist_set_comment(qclist,"ESO QC DIFF REFBIAS MEAN",
514  "Mean of difference with reference");
515  cpl_propertylist_append_double(qclist,"ESO QC DIFF REFBIAS MEDIAN",
516  cpl_stats_get_median(diffstats));
517  cpl_propertylist_set_comment(qclist,"ESO QC DIFF REFBIAS MEDIAN",
518  "Median of difference with reference");
519  cpl_propertylist_append_double(qclist,"ESO QC DIFF REFBIAS STDEV",
520  cpl_stats_get_stdev(diffstats));
521  cpl_propertylist_set_comment(qclist,"ESO QC DIFF REFBIAS STDEV",
522  "Stdev of difference with reference");
523 
524  freestats(diffstats);
525  }
526  }
527 
528  /* Save the products */
529  /* Save the MASTER BIAS product */
530  cpl_propertylist_append_double(qclist, "ESO QC MASTER BIAS MEAN",
531  omega_mbias_config.Mean) ;
532  cpl_propertylist_set_comment (qclist, "ESO QC MASTER BIAS MEAN",
533  "Mean value of master bias");
534 
535  cpl_propertylist_append_double(qclist, "ESO QC MASTER BIAS MEDIAN",
536  omega_mbias_config.Median) ;
537  cpl_propertylist_set_comment (qclist, "ESO QC MASTER BIAS MEDIAN",
538  "Median value of master bias");
539 
540  cpl_propertylist_append_double(qclist, "ESO QC MASTER BIAS STDEV",
541  omega_mbias_config.Stdev) ;
542  cpl_propertylist_set_comment (qclist, "ESO QC MASTER BIAS STDEV",
543  "Standard Deviation of master bias");
544 
545  if(isfirst){
546  outmbias = cpl_sprintf("%s_%s.fits", INSTRUME,MBIAS_PROCATG);
547  prframe_mbias = omega_product_frame(outmbias, MBIAS_PROCATG, CPL_FRAME_TYPE_IMAGE);
548  }
549 
550  alist = cpl_propertylist_new();
551  cpl_propertylist_append_string(alist, "EXTNAME",
552  cpl_propertylist_get_string(ps.eh, "EXTNAME"));
553  cpl_propertylist_set_comment(alist,"EXTNAME", "Extension name");
554 
555  /* Add DRS keywords */
556  cpl_propertylist_update_int(alist, "ESO DRS OVERSCAN METHOD", omega_mbias_config.oc);
557  cpl_propertylist_set_comment(alist, "ESO DRS OVERSCAN METHOD", "overscan correction method");
558 
559  cpl_propertylist_copy_property_regexp(alist, ps.eh, WCS_KEYS, 0);
560 
561 
562  if(omega_save_image(ps.mbias,set,pars,alist,qclist,CPL_BPP_IEEE_FLOAT,outmbias,
563  RECIPE,prframe_mbias,NULL,isfirst) == -1){
564  cpl_msg_error(_id,"Cannot save product %s", MBIAS_PROCATG);
565  freeplist(qclist);
566  freeplist(alist);
567  freespace(outhpm);
568  freespace(outmbias);
569  omega_mbias_tidy();
570  return -1;;
571  }
572 
573  freeplist(qclist);
574  freeimage(ps.mbias);
575 
576  /* Save the HOT PIXELS MAP product */
577  qclist = cpl_propertylist_new();
578  cpl_propertylist_append_int(qclist,"ESO QC NUMBER HOT PIXELS",
579  omega_mbias_config.CountHotPixels);
580  cpl_propertylist_set_comment(qclist,"ESO QC NUMBER HOT PIXELS",
581  "Number of hot pixels");
582  if(isfirst){
583  outhpm = cpl_sprintf("%s_%s.fits", INSTRUME,HPM_PROCATG);
584  prframe_hpm = omega_product_frame(outhpm, HPM_PROCATG, CPL_FRAME_TYPE_IMAGE);
585  }
586 
587  if(omega_save_image(ps.hpixels,set,pars,alist,qclist,CPL_BPP_16_SIGNED,outhpm,
588  RECIPE,prframe_hpm,NULL,isfirst) == -1){
589  cpl_msg_error(_id,"Cannot save product %s", HPM_PROCATG);
590  freeplist(qclist);
591  freeplist(alist);
592  freespace(outhpm);
593  freespace(outmbias);
594  omega_mbias_tidy();
595  return -1;;
596  }
597 
598  freeplist(qclist);
599  freeplist(alist);
600  freeimage(ps.hpixels);
601  status = 0;
602 
603  freefits(ps.firstbias);
604  ps.firstbias = NULL;
605  ps.eh = NULL;
606 
607 
608  } /* work on next extension */
609 
610  freespace(outhpm);
611  freespace(outmbias);
612  omega_mbias_tidy();
613 
614  return 0;
615 }
616 
626 {
627 
628  int i, nbias, live, naxis1, naxis2;
629  double read_noise, threshold;
630  double cutoff = 200.0; /*FIXME: arbitrary initial value*/
631  const char *_id = "omega_mbias_combine";
632 
633  const cpl_frame *biasfr;
634  cpl_image *trim_raw,*median_all,*dev,*good_int,*good_float;
635  cpl_image *sum_data,*sum_good,*image;
636  cpl_imagelist *ilist;
637  cpl_mask *good,*pixelmap;
638  cpl_table *rntable;
639 
640 
641  nbias = cpl_frameset_get_size(ps.biaslist);
642  biasfr = cpl_frameset_get_first_const(ps.biaslist);
643 
644 
645  /* Check that this detector is live*/
646  omega_pfits_get_detlive(ps.eh,&live);
647  if (! live) {
648  return 1;
649  }
650 
651  cpl_msg_info (_id,"Doing trim and overscan correction on images");
652 
653  for (i=0; i< nbias; i++){
654 
655  trim_raw = TrimOscanCorrect(biasfr, omega_mbias_config.oc, xn);
656  if(trim_raw == NULL){
657  return -1;
658  }
659 
660  if (i == 0) {
661  naxis1 = cpl_image_get_size_x (trim_raw);
662  naxis2 = cpl_image_get_size_y (trim_raw);
663  ilist = cpl_imagelist_new ();
664  }
665 
666  cpl_imagelist_set (ilist, trim_raw, i);
667 
668  biasfr = cpl_frameset_get_next_const(ps.biaslist);
669  if (biasfr == NULL)
670  break;
671 
672  }
673 
674  if (ilist == NULL) {
675  cpl_msg_error(_id,"Error in imagelist <%s>",cpl_error_get_message());
676  freeimage(trim_raw);
677  return -1;
678 
679  }
680 
681  /*
682  * If READNOISE_ADU table doesn't exist, try to
683  * get readnoise value from header of first image
684  */
685  if(ps.rnframe != NULL){
686  rntable = cpl_table_load(cpl_frame_get_filename(ps.rnframe), xn, 0);
687  if(rntable != NULL){
688  read_noise = cpl_table_get_double(rntable, "READNOISE",0, NULL);
689  freetable(rntable);
690  }
691  else{
692  omega_pfits_get_readnoise(ps.eh, &read_noise);
693  cpl_msg_warning(cpl_func,"Cannot load READNOISE_ADU table. %s",cpl_error_get_message());
694  }
695  }
696  else {
697  omega_pfits_get_readnoise(ps.eh, &read_noise);
698  }
699 
700  if (read_noise == 0.0){
701  cpl_msg_info(_id,"Using default value for read noise");
702  read_noise = 2.5;
703  }
704  else {
705  cpl_msg_info(_id,"Using read noise = %g", read_noise);
706  }
707 
708 
709  threshold = read_noise * omega_mbias_config.sigma;
710  cpl_msg_info (_id,"Discarding outliers using threshold %g", threshold);
711 
712 /* Calculate the median of all raw bias */
713 
714  cpl_msg_info (_id,"Computing the median of all images...");
715  median_all = cpl_imagelist_collapse_median_create (ilist);
716 
717  if (median_all == NULL) {
718  cpl_msg_error (_id,"Cannot take median of imagelist <%s>",cpl_error_get_message());
719  freeilist(ilist);
720  return -1;
721  }
722 
723 /* Clip the outliers from the first image*/
724  trim_raw = cpl_imagelist_get (ilist, 0);
725  dev = cpl_image_subtract_create(median_all, trim_raw);
726 
727  good = cpl_mask_threshold_image_create(dev, -threshold, threshold);
728  freeimage(dev);
729 
730  good_int = cpl_image_new_from_mask(good) ;
731  freemask(good) ;
732  good_float = cpl_image_cast(good_int, CPL_TYPE_FLOAT);
733  freeimage(good_int);
734 
735  sum_data = cpl_image_multiply_create(trim_raw, good_float);
736  sum_good = cpl_image_duplicate(good_float);
737 
738  freeimage(good_float);
739 
740 /* Clip the outliers from the remaining images*/
741  for (i=1; i< nbias; i++){
742 
743  trim_raw = cpl_imagelist_get(ilist, i);
744 /* if (trim_raw == NULL)
745  cpl_msg_error("","Image is NULL <%s>",cpl_error_get_message());
746 */
747  dev = cpl_image_subtract_create(median_all, trim_raw);
748 
749  if (dev == NULL) {
750  cpl_msg_error(_id,"Error in subtraction <%s>",cpl_error_get_function());
751  freeilist(ilist);
752  freeimage(median_all);
753  freeimage(sum_data);
754  freeimage(sum_good);
755  return -1;
756  }
757 
758  good = cpl_mask_threshold_image_create (dev, -threshold, threshold);
759 
760  freeimage(dev);
761 
762  good_int = cpl_image_new_from_mask(good) ;
763  freemask(good) ;
764  good_float = cpl_image_cast(good_int, CPL_TYPE_FLOAT);
765  freeimage(good_int);
766 
767  image = cpl_image_multiply_create(trim_raw, good_float);
768  cpl_image_add(sum_data, image);
769 
770  cpl_image_add(sum_good, good_float);
771 
772  freeimage(image);
773  freeimage(good_float);
774  }
775 
776  freeimage(median_all);
777  freeilist(ilist);
778 
779  ps.mbias = cpl_image_divide_create(sum_data, sum_good);
780 
781  if (ps.mbias == NULL) {
782  cpl_msg_error(_id,"Cannot create product. Error in division");
783  freeimage(sum_data);
784  freeimage(sum_good);
785  return -1;
786  }
787 
788  freeimage(sum_data);
789  freeimage(sum_good);
790 
791  /* Compute statistics on the master bias image */
792  ps.stats = cpl_stats_new_from_image(ps.mbias, CPL_STATS_ALL);
793  if(ps.stats != NULL) {
794  omega_mbias_config.Mean = cpl_stats_get_mean(ps.stats);
795  omega_mbias_config.Median = cpl_stats_get_median(ps.stats);
796  omega_mbias_config.Stdev = cpl_stats_get_stdev(ps.stats);
797  cutoff = omega_mbias_config.Mean + omega_mbias_config.rejsig * omega_mbias_config.Stdev;
798  cpl_msg_info(_id,"Using cutoff %g for Hot Pixels Map creation", cutoff);
799  }
800 
801  freestats(ps.stats);
802 
803  /* Create a hot pixels map */
804  pixelmap = cpl_mask_threshold_image_create(ps.mbias, -1e20, cutoff);
805 
806  /*Do an inverse to count the number of CPL_BINARY_1*/
807  cpl_mask_not(pixelmap);
808  omega_mbias_config.CountHotPixels = cpl_mask_count(pixelmap);
809 
810  /*Invert back*/
811  /* cpl_mask_not(pixelmap);*/
812 
813  /* Convert image to INT to save it */
814 
815  ps.hpixels = cpl_image_new_from_mask(pixelmap);
816  freemask(pixelmap);
817 
818  return 0;
819 }
820 
821 /* Initialize the pointers */
822 static void omega_mbias_init(void) {
823  ps.labels = NULL;
824  ps.rnframe = NULL;
825  ps.biaslist = NULL;
826  ps.mbias = NULL;
827  ps.hpixels = NULL;
828  ps.ph = NULL;
829  ps.eh = NULL;
830  ps.stats = NULL;
831  ps.firstbias = NULL;
832 }
833 
834 /* Free any allocated memory */
835 static void omega_mbias_tidy(void) {
836  freespace(ps.labels);
837  freeframeset(ps.biaslist);
838  freeimage(ps.mbias);
839  freeimage(ps.hpixels);
840  freestats(ps.stats);
841  freefits(ps.firstbias);
842 }
843