GIRAFFE Pipeline Reference Manual

gimasterbias.c
1 /* $Id$
2  *
3  * This file is part of the GIRAFFE Pipeline
4  * Copyright (C) 2002-2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /*
22  * $Author$
23  * $Date$
24  * $Revision$
25  * $Name$
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
31 
32 #include <math.h>
33 
34 #include <cxmessages.h>
35 #include <cxmemory.h>
36 
37 #include <cpl_recipe.h>
38 #include <cpl_plugininfo.h>
39 #include <cpl_parameterlist.h>
40 #include <cpl_frameset.h>
41 #include <cpl_propertylist.h>
42 #include <cpl_vector.h>
43 #include <cpl_msg.h>
44 
45 #include "gialias.h"
46 #include "gierror.h"
47 #include "giarray.h"
48 #include "giframe.h"
49 #include "giimage.h"
50 #include "giwindow.h"
51 #include "gifibers.h"
52 #include "gibias.h"
53 #include "gimath.h"
54 #include "gistacking.h"
55 #include "giqclog.h"
56 #include "giutils.h"
57 
58 
59 #define GIMASTERBIAS_BIAS_EXTENSION_IMG 0
60 #define GIMASTERBIAS_BIAS_EXTENSION_PL 0
61 #define GIMASTERBIAS_BAD_PIXEL_EXTENSION 0
62 
63 
64 struct GiMasterbiasConfig {
65 
66  cxbool removeoverscan;
67  cxbool correctbadpixels;
68 
69  struct {
70  cxbool create;
71  cxdouble factor;
72  cxdouble fraction;
73  } bpm;
74  cxbool crebadpixmap;
75 };
76 
77 typedef struct GiMasterbiasConfig GiMasterbiasConfig;
78 
79 static cxint gimasterbias(cpl_parameterlist*, cpl_frameset*);
80 static cxint giqcmasterbias(cpl_frameset*);
81 
82 
83 /*
84  * Maximum fraction of pixels which may be bad.
85  */
86 
87 static cxdouble max_bpx_fraction = 0.15;
88 
89 
90 /*
91  * Create the recipe instance, i.e. setup the parameter list for this
92  * recipe and make it availble to the application using the interface.
93  */
94 
95 static cxint
96 gimasterbias_create(cpl_plugin* plugin)
97 {
98 
99  cpl_recipe* recipe = (cpl_recipe*)plugin;
100 
101  cpl_parameter* p;
102 
103 
104  giraffe_error_init();
105 
106 
107  /*
108  * We have to provide the option we accept to the application. We
109  * need to setup our parameter list and hook it into the recipe
110  * interface.
111  */
112 
113  recipe->parameters = cpl_parameterlist_new();
114  cx_assert(recipe->parameters != NULL);
115 
116  /*
117  * Fill the parameter list.
118  */
119 
120  /* Stacking */
121 
122  giraffe_stacking_config_add(recipe->parameters);
123 
124  /* Masterbias */
125 
126  p = cpl_parameter_new_value("giraffe.masterbias.overscan.remove",
127  CPL_TYPE_BOOL,
128  "Remove pre- and over-scan regions from "
129  "the created master bias image.",
130  "giraffe.masterbias.overscan",
131  FALSE);
132  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "mbias-oscremove");
133  cpl_parameterlist_append(recipe->parameters, p);
134 
135  p = cpl_parameter_new_value("giraffe.masterbias.badpixel.clean",
136  CPL_TYPE_BOOL,
137  "Correct master bias image for bad pixels",
138  "giraffe.masterbias.badpixel",
139  FALSE);
140  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "mbias-bpxclean");
141  cpl_parameterlist_append(recipe->parameters, p);
142 
143  p = cpl_parameter_new_value("giraffe.masterbias.bpm.create",
144  CPL_TYPE_BOOL,
145  "Create bad pixel map using a simple "
146  "thresholding algorithm. (temporary!)",
147  "giraffe.masterbias.bpm",
148  TRUE);
149  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "bpm-create");
150  cpl_parameterlist_append(recipe->parameters, p);
151 
152  p = cpl_parameter_new_value("giraffe.masterbias.bpm.factor",
153  CPL_TYPE_DOUBLE,
154  "Readout noise multiplier defining the "
155  "valid range of pixel values for searching "
156  "bad pixels.",
157  "giraffe.masterbias.bpm",
158  5.0);
159  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "bpm-factor");
160  cpl_parameterlist_append(recipe->parameters, p);
161 
162  p = cpl_parameter_new_value("giraffe.masterbias.bpm.fraction",
163  CPL_TYPE_DOUBLE,
164  "Maximum fraction of pixels which may be "
165  "flagged as 'bad. If more pixels are "
166  "found to be 'bad a warning is issued.",
167  "giraffe.masterbias.bpm",
168  max_bpx_fraction);
169  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "bpm-frac");
170  cpl_parameterlist_append(recipe->parameters, p);
171 
172  return 0;
173 
174 }
175 
176 /*
177  * Execute the plugin instance given by the interface.
178  */
179 
180 static cxint
181 gimasterbias_exec(cpl_plugin* plugin)
182 {
183 
184  cpl_recipe* recipe = (cpl_recipe*)plugin;
185 
186  cxint status = 0;
187 
188 
189  if (recipe->parameters == NULL || recipe->frames == NULL) {
190  return 1;
191  }
192 
193  status = gimasterbias(recipe->parameters, recipe->frames);
194 
195  if (status != 0) {
196  return 1;
197  }
198 
199  status = giqcmasterbias(recipe->frames);
200 
201  if (status != 0) {
202  return 1;
203  }
204 
205  return 0;
206 
207 }
208 
209 
210 static cxint
211 gimasterbias_destroy(cpl_plugin* plugin)
212 {
213 
214  cpl_recipe* recipe = (cpl_recipe*)plugin;
215 
216 
217  /*
218  * We just destroy what was created during the plugin initialization
219  * phase, i.e. the parameter list. The frame set is managed by the
220  * application which called us, so we must not touch it,
221  */
222 
223  cpl_parameterlist_delete(recipe->parameters);
224 
225  giraffe_error_clear();
226 
227  return 0;
228 
229 }
230 
231 /*
232  * Remove bad pixels from a Image using a bad pixel map
233  */
234 
235 static cxint
236 gimasterbias_remove_badpixels(GiImage* img, GiImage* img_badpixels)
237 {
238 
239  const cxchar* const fctid = "gimasterbias_remove_badpixels";
240 
241 
242  cxbool found_first;
243 
244  register cxint j;
245  register cxint k;
246  register cxint nr_pairs;
247  register cxint d;
248  register cxint sign;
249 
250  cxint ncol_bp;
251  cxint nrow_bp;
252  cxint badx;
253  cxint bady;
254  cxint cx;
255  cxint cy;
256  cxint search_horizon = 100;
257 
258  cxint* pi_bp = NULL;
259 
260  cxint sx[] = { 0, 1, 1, 1 };
261  cxint sy[] = { 1,-1, 0, 1 };
262 
263  cxlong npix_bp;
264  cxlong nr_bad_pixels = 0L;
265  cxlong n;
266 
267  cxdouble sumd;
268  cxdouble save = 0.;
269 
270  cxdouble* pd_img = NULL;
271 
272  cxdouble estimate[4];
273 
274 
275 
276  if (!img) {
277  cpl_msg_error(fctid, "NULL Image as input, aborting..." );
278  return -1;
279  }
280 
281  if (!img_badpixels) {
282  cpl_msg_error(fctid, "NULL Bad Pixel Image as input, aborting..." );
283  return -1;
284  }
285 
286  ncol_bp = cpl_image_get_size_x(giraffe_image_get(img_badpixels));
287  nrow_bp = cpl_image_get_size_y(giraffe_image_get(img_badpixels));
288  npix_bp = ncol_bp * nrow_bp;
289  pi_bp = cpl_image_get_data_int(giraffe_image_get(img_badpixels));
290 
291  pd_img = cpl_image_get_data_double(giraffe_image_get(img));
292 
293  for (n=0; n<npix_bp; n++) {
294  if (pi_bp[n]!=0)
295  nr_bad_pixels++;
296  }
297 
298  if (((cxdouble)nr_bad_pixels / (cxdouble)npix_bp) >= max_bpx_fraction) {
299  cpl_msg_error(fctid, "Too many bad pixels, aborting..." );
300  return -1;
301  }
302 
303  /************************************************************************
304  PROCESSING
305  ************************************************************************/
306 
307  for (badx=0; badx<ncol_bp; badx++) {
308  for (bady=0; bady<nrow_bp; bady++) {
309  if (pi_bp[badx + bady * ncol_bp]==1) {
310  nr_pairs = 0;
311  for (j=0; j<4; j++) {
312  estimate[nr_pairs] = 0.0;
313  sumd = 0.0;
314  found_first = FALSE;
315  for (k=0; k<2; k++) {
316  sign = 2 * k - 1;
317  d = 0;
318  cx = badx;
319  cy = bady;
320  do {
321  cx += sign * sx[j];
322  cy += sign * sy[j];
323  if (cx<0 || cx>=ncol_bp || cy<0 || cy>=nrow_bp)
324  break;
325  d++;
326  } while (pi_bp[cx+cy*ncol_bp] && (d<search_horizon));
327 
328  if (cx>=0 && cx<ncol_bp && cy>=0 && cy<nrow_bp &&
329  (d<search_horizon) )
330  {
331  save = pd_img[cx+cy*ncol_bp];
332  estimate[nr_pairs] += save / d;
333  sumd += 1.0 / (cxdouble) d;
334  if (k) {
335  estimate[nr_pairs] /= sumd;
336  nr_pairs++;
337  } else {
338  found_first = TRUE;
339  }
340  } else {
341  if (k) {
342  if (found_first) {
343  estimate[nr_pairs] = save;
344  nr_pairs++;
345  if (nr_pairs>2) {
346 
347  cpl_vector* _estimate =
348  cpl_vector_wrap(nr_pairs,
349  estimate);
350 
351  pd_img[badx+bady*ncol_bp] =
352  cpl_vector_get_median(_estimate);
353 
354  cpl_vector_unwrap(_estimate);
355  _estimate = NULL;
356 
357  } else if (nr_pairs==2) {
358  pd_img[badx+bady*ncol_bp] =
359  (estimate[0]+estimate[1]) * 0.5;
360  } else if (nr_pairs==1) {
361  pd_img[badx+bady*ncol_bp] =
362  estimate[0];
363  } else {
364  cpl_msg_warning(
365  fctid,
366  "Can't correct badpixel [%d,%d]",
367  badx,
368  bady
369  );
370  }
371  }
372  }
373  }
374  }
375 
376  }
377  }
378  }
379  }
380 
381  return 0;
382 
383 }
384 
385 
386 /*
387  * The actual recipe starts here.
388  */
389 
390 static cxint
391 gimasterbias(cpl_parameterlist* config, cpl_frameset* set)
392 {
393 
394  const cxchar* const fctid = "gimasterbias";
395 
396 
397  cxint raw_bias_count = 0;
398  cxint bad_pixel_count = 0;
399  cxint e_code = 0;
400 
401  cxlong i = 0;
402  cxlong j = 0;
403 
404  cpl_propertylist* properties = NULL;
405 
406  cpl_frame* curr_frame = NULL;
407  cpl_frame* bad_pixel_frame = NULL;
408  cpl_frame* product_frame = NULL;
409 
410  cpl_parameter* p = NULL;
411 
412  GiImage** raw_bias_list = NULL;
413  GiImage* bad_pixels = NULL;
414  GiImage* master_bias = NULL;
415 
416  GiMasterbiasConfig mbias_config;
417 
418  GiStackingConfig* stack_config = NULL;
419 
420  GiRecipeInfo info = {(cxchar*)fctid, 1, NULL};
421 
422  GiGroupInfo groups[] = {
423  {GIFRAME_BIAS, CPL_FRAME_GROUP_RAW},
424  {GIFRAME_BADPIXEL_MAP, CPL_FRAME_GROUP_CALIB},
425  {NULL, CPL_FRAME_GROUP_NONE}
426  };
427 
428 
429  /************************************************************************
430  PREPROCESSING
431  ************************************************************************/
432 
433  p = cpl_parameterlist_find(config, "giraffe.masterbias.overscan.remove");
434  mbias_config.removeoverscan = cpl_parameter_get_bool(p);
435 
436  p = cpl_parameterlist_find(config, "giraffe.masterbias.badpixel.clean");
437  mbias_config.correctbadpixels = cpl_parameter_get_bool(p);
438 
439  p = cpl_parameterlist_find(config, "giraffe.masterbias.bpm.create");
440  mbias_config.bpm.create = cpl_parameter_get_bool(p);
441 
442  p = cpl_parameterlist_find(config, "giraffe.masterbias.bpm.factor");
443  mbias_config.bpm.factor = cpl_parameter_get_double(p);
444 
445  p = cpl_parameterlist_find(config, "giraffe.masterbias.bpm.fraction");
446  mbias_config.bpm.fraction = cpl_parameter_get_double(p);
447 
448 
449  e_code = giraffe_frameset_set_groups(set, groups);
450 
451  if (e_code != 0) {
452  cpl_msg_error(fctid, "Setting frame group information failed!");
453  return 1;
454  }
455 
456 
457  /************************************************************************
458  PROCESSING
459  ************************************************************************/
460 
461  stack_config = giraffe_stacking_config_create(config);
462 
463  /* check number of images */
464  raw_bias_count = cpl_frameset_count_tags(set, GIFRAME_BIAS);
465 
466  if (raw_bias_count < stack_config->min_nr_frames) {
467  cpl_msg_error(fctid, "Not enough raw bias Images [%d, need %d], "
468  "aborting...", raw_bias_count,
469  stack_config->min_nr_frames);
470 
471  giraffe_stacking_config_destroy(stack_config);
472  stack_config = NULL;
473 
474  return -1;
475  }
476 
477  bad_pixel_count = cpl_frameset_count_tags(set, GIFRAME_BADPIXEL_MAP);
478 
479  if (mbias_config.correctbadpixels == TRUE) {
480  if (bad_pixel_count != 1) {
481  cpl_msg_error(fctid, "Invalid number of bad pixel Images "
482  "[%d instead of 1], aborting...", bad_pixel_count);
483 
484  giraffe_stacking_config_destroy(stack_config);
485  stack_config = NULL;
486 
487  return -1;
488  }
489  }
490 
491  cpl_msg_info(fctid, "Creating master bias from %d bias frames ...",
492  raw_bias_count);
493 
494 
495  /* load images */
496 
497  raw_bias_list = (GiImage**)cx_calloc(raw_bias_count + 1, sizeof(GiImage*));
498 
499  raw_bias_list[raw_bias_count] = NULL;
500 
501  curr_frame = cpl_frameset_find(set, GIFRAME_BIAS);
502 
503  for (i = 0; i < raw_bias_count; ++i) {
504 
505  raw_bias_list[i] = giraffe_image_new(CPL_TYPE_DOUBLE);
506 
507  e_code = giraffe_image_load(raw_bias_list[i],
508  cpl_frame_get_filename(curr_frame),
509  GIMASTERBIAS_BIAS_EXTENSION_IMG);
510 
511  if (e_code != 0) {
512 
513  cpl_msg_error(fctid, "Could not load raw Bias Image [%s], "
514  "aborting...", cpl_frame_get_filename(curr_frame));
515 
516  for (j = 0; j <= i; ++j) {
517  if (raw_bias_list[j] != NULL) {
518  giraffe_image_delete(raw_bias_list[j]);
519  raw_bias_list[j] = NULL;
520  }
521  }
522 
523  cx_free(raw_bias_list);
524 
525  giraffe_stacking_config_destroy(stack_config);
526  stack_config = NULL;
527 
528  return -1;
529 
530  }
531  else {
532  curr_frame = cpl_frameset_find(set, NULL);
533  }
534  }
535 
536  if (mbias_config.correctbadpixels == TRUE) {
537 
538  /* load bad pixel image */
539 
540  bad_pixel_frame = cpl_frameset_find(set, GIFRAME_BADPIXEL_MAP);
541 
542  cpl_msg_info(fctid, "Bad Pixel Frame is : %s.",
543  cpl_frame_get_filename(bad_pixel_frame));
544 
545  bad_pixels = giraffe_image_new(CPL_TYPE_INT);
546 
547  e_code = giraffe_image_load(bad_pixels,
548  cpl_frame_get_filename(bad_pixel_frame),
549  GIMASTERBIAS_BAD_PIXEL_EXTENSION);
550 
551  if (e_code !=0 ) {
552  cpl_msg_error(fctid, "Could not load Bad Pixel Image [%s], "
553  "aborting...",
554  cpl_frame_get_filename(bad_pixel_frame));
555 
556  for (j = 0; j < raw_bias_count; j++) {
557  if (raw_bias_list[j] != NULL) {
558  giraffe_image_delete(raw_bias_list[j]);
559  }
560  }
561 
562  cx_free(raw_bias_list);
563 
564  giraffe_stacking_config_destroy(stack_config);
565  stack_config = NULL;
566 
567  return -1;
568  }
569  }
570 
571 
572  /*
573  * Stack the bias frames...
574  */
575 
576  master_bias = giraffe_stacking_stack_images(raw_bias_list, stack_config);
577 
578  if (master_bias == NULL) {
579  cpl_msg_error(fctid,"Stacking of raw bias frames failed! "
580  "No master bias was created, aborting...");
581 
582  for (j = 0; j < raw_bias_count; j++) {
583  if (raw_bias_list[j] != NULL) {
584  giraffe_image_delete(raw_bias_list[j]);
585  }
586  }
587 
588  cx_free(raw_bias_list);
589 
590  if (bad_pixels != NULL) {
591  giraffe_image_delete(bad_pixels);
592  }
593 
594  giraffe_stacking_config_destroy(stack_config);
595  stack_config = NULL;
596 
597  return -1;
598 
599  }
600 
601  properties = giraffe_image_get_properties(raw_bias_list[0]);
602  e_code = giraffe_image_set_properties(master_bias, properties);
603 
604  giraffe_stacking_config_destroy(stack_config);
605  stack_config = NULL;
606 
607 
608  /*
609  * Bad pixel cleaning on result, if necessary...
610  */
611 
612  if (mbias_config.correctbadpixels == TRUE) {
613 
614  cpl_msg_info(fctid, "Cleaning bad pixels on created "
615  "master bias image.");
616 
617  if (gimasterbias_remove_badpixels(master_bias, bad_pixels) != 0) {
618 
619  cpl_msg_error(fctid, "Bad pixel cleaning failed, aborting...");
620 
621  for (j = 0; j < raw_bias_count; j++) {
622  if (raw_bias_list[j] != NULL) {
623  giraffe_image_delete(raw_bias_list[j]);
624  }
625  }
626 
627  cx_free(raw_bias_list);
628 
629  if (bad_pixels != NULL) {
630  giraffe_image_delete(bad_pixels);
631  }
632 
633  if (master_bias != NULL) {
634  giraffe_image_delete(master_bias);
635  }
636 
637  return -1;
638 
639  }
640  }
641 
642  /*
643  * Remove overscans, if necessary...
644  */
645 
646  if (mbias_config.removeoverscan == TRUE) {
647 
648  cpl_msg_info(fctid, "Removing overscan areas from "
649  "master bias image");
650 
651  if (giraffe_trim_raw_areas(master_bias) != 0) {
652 
653  cpl_msg_error(fctid, "Removing overscan areas from master "
654  "bias failed, aborting...");
655 
656  for (j = 0; j < raw_bias_count; j++) {
657  if (raw_bias_list[j] != NULL) {
658  giraffe_image_delete(raw_bias_list[j]);
659  }
660  }
661 
662  cx_free(raw_bias_list);
663 
664  if (bad_pixels != NULL) {
665  giraffe_image_delete(bad_pixels);
666  }
667 
668  if (master_bias != NULL) {
669  giraffe_image_delete(master_bias);
670  }
671 
672  return -1;
673  }
674 
675  }
676 
677 
678  /*
679  * Update master bias properties, save the master bias frame
680  * and register it as product.
681  */
682 
683  cpl_msg_info(fctid, "Writing master bias image ...");
684 
685  properties = giraffe_image_get_properties(master_bias);
686  cx_assert(properties != NULL);
687 
688  cpl_propertylist_update_double(properties, GIALIAS_CRPIX1, 1.);
689 
690  cpl_propertylist_update_double(properties, GIALIAS_EXPTTOT, 0.0);
691  cpl_propertylist_update_int(properties, GIALIAS_DATANCOM, raw_bias_count);
692  cpl_propertylist_update_double(properties, GIALIAS_BZERO, 0.0);
693 
694  cpl_propertylist_update_double(properties, GIALIAS_BIASVALUE,
695  cpl_image_get_mean(giraffe_image_get(master_bias)));
696  cpl_propertylist_update_double(properties, GIALIAS_BIASSIGMA,
697  cpl_image_get_stdev(giraffe_image_get(master_bias)));
698 
699  cpl_propertylist_erase(properties, GIALIAS_EXPTIME);
700  cpl_propertylist_erase(properties, GIALIAS_TPLEXPNO);
701 
702 
703  /*
704  * Clean up bias list and bad pixels...
705  */
706 
707  for (j = 0; j < raw_bias_count; j++) {
708  if (raw_bias_list[j] != NULL) {
709  giraffe_image_delete(raw_bias_list[j]);
710  }
711  }
712 
713  cx_free(raw_bias_list);
714  raw_bias_list = NULL;
715 
716  if (bad_pixels != NULL) {
717  giraffe_image_delete(bad_pixels);
718  bad_pixels = NULL;
719  }
720 
721 
722  giraffe_image_add_info(master_bias, &info, set);
723 
724  product_frame = giraffe_frame_create_image(master_bias,
725  GIFRAME_BIAS_MASTER,
726  CPL_FRAME_LEVEL_FINAL,
727  TRUE, TRUE);
728 
729  if (product_frame == NULL) {
730 
731  cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
732 
733  if (master_bias != NULL) {
734  giraffe_image_delete(master_bias);
735  }
736 
737  return -1;
738 
739  }
740 
741  cpl_frameset_insert(set, product_frame);
742 
743 
744  /*
745  * Create bad pixel map based on masterbias
746  * Very simple algorithm, should be refined later...
747  */
748 
749  if ((mbias_config.bpm.create == TRUE) && (master_bias != NULL)
750  && (bad_pixel_count == 0)) {
751 
752  const cpl_image* _master_bias = giraffe_image_get(master_bias);
753 
754  const cxdouble* pd_mbias =
755  cpl_image_get_data_double_const(_master_bias);
756 
757 
758  cxint e_code2 = 0;
759  cxint row_min = 0;
760  cxint row_max = 0;
761  cxint ncol = cpl_image_get_size_x(_master_bias);
762  cxint nrow = cpl_image_get_size_y(_master_bias);
763  cxint* pi_bpm = NULL;
764 
765  cxlong npix = ncol * nrow;
766  cxlong nbpx = 0L;
767  cxlong nbpx_max = (cxlong)(mbias_config.bpm.fraction * npix + 0.5);
768 
769  cxdouble median = 0.;
770  cxdouble median_max = CX_MINDOUBLE;
771  cxdouble median_min = CX_MAXDOUBLE;
772  cxdouble ron = 0.;
773  cxdouble tlow = 0.;
774  cxdouble thigh = 0.;
775 
776  GiImage* bpixel = giraffe_image_create(CPL_TYPE_INT, ncol, nrow);
777 
778 
779  cpl_msg_info(fctid, "Creating bad pixel map from master bias "
780  "frame ...");
781 
782 
783  /*
784  * Copy master bias properties to the bad pixel map and
785  * re-assign the properties' handle.
786  */
787 
788  e_code2 = giraffe_image_set_properties(bpixel, properties);
789  properties = giraffe_image_get_properties(bpixel);
790 
791 
792  /*
793  * Get bad pixel map pixel buffer
794  */
795 
796  pi_bpm = cpl_image_get_data_int(giraffe_image_get(bpixel));
797 
798 
799  /*
800  * Setup detection thresholds
801  */
802 
803  if ((cpl_propertylist_has(properties, GIALIAS_PRSCX) == TRUE) ||
804  (cpl_propertylist_has(properties, GIALIAS_OVSCX) == TRUE)) {
805 
806  cxint nvalues = 0;
807 
808  if (cpl_propertylist_has(properties, GIALIAS_PRSCX) == TRUE) {
809 
810  cxint xsz = cpl_propertylist_get_int(properties,
811  GIALIAS_PRSCX);
812 
813  cxdouble sdev = 0.;
814 
815 
816  for (i = 0; i < nrow; ++i) {
817 
818  register cxint stride = i * ncol;
819 
820  cxdouble scx_mean = giraffe_array_mean(pd_mbias + stride,
821  xsz);
822 
823  for (j = 0; j < xsz; ++j) {
824  sdev += (pd_mbias[stride + j] - scx_mean) *
825  (pd_mbias[stride + j] - scx_mean);
826  }
827 
828  }
829 
830  ron = sqrt(sdev / (cxdouble)(nrow * xsz - 1));
831  ++nvalues;
832 
833  }
834 
835  if (cpl_propertylist_has(properties, GIALIAS_OVSCX) == TRUE) {
836 
837  cxint xsz = cpl_propertylist_get_int(properties,
838  GIALIAS_OVSCX);
839 
840  cxdouble sdev = 0.;
841 
842 
843  for (i = 0; i < nrow; ++i) {
844 
845  register cxint stride = (i + 1) * ncol - xsz;
846 
847  cxdouble scx_mean = giraffe_array_mean(pd_mbias + stride,
848  xsz);
849 
850  for (j = 0; j < xsz; ++j) {
851  sdev += (pd_mbias[stride + j] - scx_mean) *
852  (pd_mbias[stride + j] - scx_mean);
853  }
854 
855  }
856 
857  ron += sqrt(sdev / (cxdouble)(nrow * xsz - 1));
858  ++nvalues;
859 
860  }
861 
862  ron /= (cxdouble)nvalues;
863 
864  }
865  else {
866 
867  if (cpl_propertylist_has(properties, GIALIAS_RON)) {
868 
869  ron = cpl_propertylist_get_double(properties, GIALIAS_RON);
870 
871  if (cpl_propertylist_has(properties, GIALIAS_CONAD)) {
872 
873  cxdouble conad = cpl_propertylist_get_double(properties,
874  GIALIAS_CONAD);
875 
876  if (conad <= 0.) {
877 
878  cpl_msg_error(fctid, "Invalid conversion factor "
879  "property (%s): %.2g!", GIALIAS_CONAD,
880  conad);
881 
882  giraffe_image_delete(bpixel);
883  bpixel = NULL;
884 
885  giraffe_image_delete(master_bias);
886  master_bias = NULL;
887 
888  return -1;
889  }
890  else {
891  ron /= conad;
892  }
893  }
894  else {
895  cpl_msg_error(fctid, "Missing conversion factor property "
896  "(%s)!", GIALIAS_CONAD);
897 
898  giraffe_image_delete(bpixel);
899  bpixel = NULL;
900 
901  giraffe_image_delete(master_bias);
902  master_bias = NULL;
903 
904  return -1;
905  }
906  }
907  else {
908  ron = cpl_image_get_stdev(giraffe_image_get(master_bias));
909  }
910 
911  }
912 
913  cpl_msg_info(fctid, "Using local median +/- %.4f [ADU] as "
914  "valid pixel value range", ron);
915 
916 
917  for (i = 0; i < nrow; ++i) {
918 
919  register cxint stride = i * ncol;
920  register cxint* bpx_row = pi_bpm + stride;
921 
922  register const cxdouble* bias_row = pd_mbias + stride;
923 
924  register cxdouble sdev = 0.;
925 
926  median = giraffe_array_median(bias_row, ncol);
927 
928  for (j = 0; j < ncol; ++j) {
929  sdev += (bias_row[j] - median) * (bias_row[j] - median);
930  }
931  sdev = sqrt(sdev / (cxdouble)(ncol - 1));
932 
933  if (median < median_min) {
934  median_min = median;
935  row_min = i;
936  }
937 
938  if (median > median_max) {
939  median_max = median;
940  row_max = i;
941  }
942 
943  tlow = median - mbias_config.bpm.factor * ron;
944  thigh = median + mbias_config.bpm.factor * ron;
945 
946  for (j = 0; j < ncol; ++j) {
947 
948  if ((bias_row[j] < tlow) || (bias_row[j] > thigh)) {
949  bpx_row[j] = 1;
950  ++nbpx;
951  }
952  else {
953  bpx_row[j] = 0;
954  }
955 
956  }
957 
958  }
959 
960 
961  if (nbpx > nbpx_max) {
962  cpl_msg_warning(fctid, "Number of bad pixels found (%ld) exceeds "
963  "maximum number of bad pixels expected (%ld)!", nbpx,
964  nbpx_max);
965  }
966 
967  properties = giraffe_image_get_properties(bpixel);
968 
969  cpl_propertylist_update_double(properties, GIALIAS_BZERO, 0.);
970 
971  cpl_propertylist_update_double(properties,
972  GIALIAS_BPM_FRACTION, mbias_config.bpm.fraction);
973  cpl_propertylist_set_comment(properties, GIALIAS_BPM_FRACTION,
974  "Maximum fraction of bad pixels allowed.");
975 
976  cpl_propertylist_update_int(properties,
977  GIALIAS_BPM_NPIX, nbpx);
978  cpl_propertylist_set_comment(properties, GIALIAS_BPM_NPIX,
979  "Number of pixels flagged as bad.");
980 
981  cpl_propertylist_update_double(properties,
982  GIALIAS_BPM_MEDIAN_MIN, median_min);
983  cpl_propertylist_set_comment(properties, GIALIAS_BPM_MEDIAN_MIN,
984  "Minimum median pixel value used for bad pixel detection.");
985 
986  cpl_propertylist_update_double(properties,
987  GIALIAS_BPM_MEDIAN_MAX, median_max);
988  cpl_propertylist_set_comment(properties, GIALIAS_BPM_MEDIAN_MAX,
989  "Maximum median pixel value used for bad pixel detection.");
990 
991  cpl_propertylist_update_double(properties,
992  GIALIAS_BPM_FACTOR, mbias_config.bpm.factor);
993  cpl_propertylist_set_comment(properties, GIALIAS_BPM_FACTOR,
994  "Noise multiplier defining thresholds for bad pixel "
995  "detection.");
996 
997  cpl_propertylist_update_double(properties,
998  GIALIAS_BPM_NOISE, ron);
999  cpl_propertylist_set_comment(properties, GIALIAS_BPM_NOISE,
1000  "Bias noise value [ADU] used for bad pixel detection.");
1001 
1002  giraffe_image_add_info(bpixel, &info, set);
1003 
1004  product_frame = giraffe_frame_create_image(bpixel,
1005  GIFRAME_BADPIXEL_MAP,
1006  CPL_FRAME_LEVEL_FINAL,
1007  TRUE, TRUE);
1008 
1009  if (product_frame == NULL) {
1010 
1011  cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
1012 
1013  if (master_bias != NULL) {
1014  giraffe_image_delete(master_bias);
1015  }
1016 
1017  if (bpixel != NULL) {
1018  giraffe_image_delete(bpixel);
1019  }
1020 
1021  return -1;
1022 
1023  }
1024 
1025  cpl_frameset_insert(set, product_frame);
1026 
1027 
1028  /*
1029  * Clean up
1030  */
1031 
1032  if (bpixel != NULL) {
1033  giraffe_image_delete(bpixel);
1034  }
1035 
1036  }
1037 
1038  if (master_bias != NULL) {
1039  giraffe_image_delete(master_bias);
1040  }
1041 
1042  return 0;
1043 
1044 }
1045 
1046 
1047 /*
1048  * The quality control task starts here.
1049  */
1050 
1051 static cxint
1052 giqcmasterbias(cpl_frameset* set)
1053 {
1054 
1055  const cxchar* const fctid = "giqcmasterbias";
1056 
1057 
1058  const cxint wstart = 50;
1059  const cxint wsize = 100;
1060 
1061  cxint i;
1062  cxint j;
1063  cxint k;
1064  cxint nx = 0;
1065  cxint ny = 0;
1066  cxint nvalid = 0;
1067  cxint status = 0;
1068  cxint nsigma = 5;
1069 
1070  const cxdouble low = 100.;
1071  const cxdouble high = 300.;
1072  const cxdouble sthreshold = 2.;
1073 
1074  cxdouble mean = 0.;
1075  cxdouble median = 0.;
1076  cxdouble smean = 0.;
1077  cxdouble sum = 0.;
1078  cxdouble* _mbdata = NULL;
1079  cxdouble* _tdata = NULL;
1080  cxdouble sigma[nsigma];
1081 
1082  cpl_propertylist* properties = NULL;
1083  cpl_propertylist* qclog = NULL;
1084 
1085  cpl_vector* _sigma = NULL;
1086 
1087  cpl_image* _mbias = NULL;
1088  cpl_image* _smbias = NULL;
1089  cpl_image* _test = NULL;
1090 
1091  cpl_frame* rframe = NULL;
1092  cpl_frame* pframe = NULL;
1093 
1094  GiPaf* qc = NULL;
1095 
1096  GiImage* mbias = NULL;
1097  GiImage* bias = NULL;
1098 
1099  GiWindow w;
1100 
1101 
1102  cpl_msg_info(fctid, "Computing QC1 parameters ...");
1103 
1104  qc = giraffe_qclog_open(0);
1105 
1106  if (qc == NULL) {
1107  cpl_msg_error(fctid, "Cannot create QC1 log!");
1108  return 1;
1109  }
1110 
1111  qclog = giraffe_paf_get_properties(qc);
1112  cx_assert(qclog != NULL);
1113 
1114 
1115  /*
1116  * Process master bias
1117  */
1118 
1119  pframe = giraffe_get_frame(set, GIFRAME_BIAS_MASTER,
1120  CPL_FRAME_GROUP_PRODUCT);
1121 
1122  if (pframe == NULL) {
1123  cpl_msg_error(fctid, "Missing product frame (%s)",
1124  GIFRAME_BIAS_MASTER);
1125 
1126  giraffe_paf_delete(qc);
1127  qc = NULL;
1128 
1129  return 1;
1130  }
1131 
1132  cpl_msg_info(fctid, "Processing product frame '%s' (%s)",
1133  cpl_frame_get_filename(pframe), cpl_frame_get_tag(pframe));
1134 
1135  mbias = giraffe_image_new(CPL_TYPE_DOUBLE);
1136  status = giraffe_image_load(mbias, cpl_frame_get_filename(pframe), 0);
1137 
1138  if (status != 0) {
1139  cpl_msg_error(fctid, "Could not load master bias '%s'! Aborting ...",
1140  cpl_frame_get_filename(pframe));
1141 
1142  giraffe_image_delete(mbias);
1143  mbias = NULL;
1144 
1145  giraffe_paf_delete(qc);
1146  qc = NULL;
1147 
1148  return 1;
1149  }
1150 
1151 
1152  /*
1153  * Load first raw image as reference
1154  */
1155 
1156  rframe = cpl_frameset_find(set, GIFRAME_BIAS);
1157 
1158  if (rframe == NULL) {
1159  cpl_msg_error(fctid, "Missing raw frame (%s)", GIFRAME_BIAS);
1160 
1161  giraffe_image_delete(mbias);
1162  mbias = NULL;
1163 
1164  giraffe_paf_delete(qc);
1165  qc = NULL;
1166 
1167  return 1;
1168  }
1169 
1170  bias = giraffe_image_new(CPL_TYPE_DOUBLE);
1171  status = giraffe_image_load(bias, cpl_frame_get_filename(rframe), 0);
1172 
1173  if (status != 0) {
1174  cpl_msg_error(fctid, "Could not load bias '%s'!",
1175  cpl_frame_get_filename(rframe));
1176 
1177  giraffe_image_delete(bias);
1178  bias = NULL;
1179 
1180  giraffe_image_delete(mbias);
1181  mbias = NULL;
1182 
1183  giraffe_paf_delete(qc);
1184  qc = NULL;
1185 
1186  return 1;
1187 
1188  }
1189 
1190  properties = giraffe_image_get_properties(bias);
1191  cx_assert(properties != NULL);
1192 
1193  giraffe_propertylist_copy(qclog, "ARCFILE", properties, GIALIAS_ARCFILE);
1194  giraffe_propertylist_copy(qclog, "TPL.ID", properties, GIALIAS_TPLID);
1195 
1196  cpl_propertylist_update_string(qclog, "PRO.CATG",
1197  cpl_frame_get_tag(pframe));
1198  cpl_propertylist_set_comment(qclog, "PRO.CATG",
1199  "Pipeline product category");
1200 
1201  properties = giraffe_image_get_properties(mbias);
1202  cx_assert(properties != NULL);
1203 
1204  giraffe_propertylist_copy(qclog, "PRO.DATAAVG",
1205  properties, GIALIAS_DATAMEAN);
1206  giraffe_propertylist_copy(qclog, "PRO.DATARMS",
1207  properties, GIALIAS_DATASIG);
1208  giraffe_propertylist_copy(qclog, "PRO.DATAMED",
1209  properties, GIALIAS_DATAMEDI);
1210  giraffe_propertylist_copy(qclog, "PRO.DATANCOM",
1211  properties, GIALIAS_DATANCOM);
1212 
1213 
1214  /*
1215  * Create screened test image for statistics computation
1216  */
1217 
1218  _mbias = giraffe_image_get(mbias);
1219  _mbdata = cpl_image_get_data(_mbias);
1220 
1221  nx = cpl_image_get_size_x(_mbias);
1222  ny = cpl_image_get_size_y(_mbias);
1223 
1224  nvalid = 0;
1225 
1226  for (i = 0; i < nx * ny; i++) {
1227 
1228  if (_mbdata[i] >= low && _mbdata[i] < high) {
1229  ++nvalid;
1230  }
1231 
1232  }
1233 
1234  _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1235  _tdata = cpl_image_get_data(_test);
1236 
1237  j = 0;
1238 
1239  for (i = 0; i < nx * ny; i++) {
1240 
1241  if (_mbdata[i] >= low && _mbdata[i] < high) {
1242  _tdata[j++] = _mbdata[i];
1243  }
1244 
1245  }
1246 
1247  cpl_propertylist_update_double(properties, GIALIAS_QCMBIASMED,
1248  cpl_image_get_median(_test));
1249  cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASMED,
1250  "Median master bias level (ADU)");
1251 
1252  cpl_propertylist_update_double(properties, GIALIAS_QCMBIASAVG,
1253  cpl_image_get_mean(_test));
1254  cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASAVG,
1255  "Mean master bias level (ADU)");
1256 
1257  cpl_propertylist_update_double(properties, GIALIAS_QCMBIASRMS,
1258  cpl_image_get_stdev(_test));
1259  cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASRMS,
1260  "RMS of master bias level (ADU)");
1261 
1262  cpl_image_delete(_test);
1263  _test = NULL;
1264 
1265  giraffe_propertylist_copy(qclog, "QC.BIAS.MASTER.MEDIAN",
1266  properties, GIALIAS_QCMBIASMED);
1267  giraffe_propertylist_copy(qclog, "QC.BIAS.MASTER.MEAN",
1268  properties, GIALIAS_QCMBIASAVG);
1269  giraffe_propertylist_copy(qclog, "QC.BIAS.MASTER.RMS",
1270  properties, GIALIAS_QCMBIASRMS);
1271 
1272 
1273  /*
1274  * Compute read out noise on raw frames if at least 2 raw
1275  * biases are available.
1276  */
1277 
1278  if (cpl_frameset_count_tags(set, GIFRAME_BIAS) > 1) {
1279 
1280  cpl_frame* _frame = NULL;
1281 
1282  cpl_image* diff = NULL;
1283 
1284  GiImage* _bias;
1285 
1286 
1287  nsigma = 5;
1288  memset(sigma, 0, nsigma * sizeof(cxdouble));
1289 
1290  _frame = cpl_frameset_find(set, GIFRAME_BIAS);
1291  _frame = cpl_frameset_find(set, NULL);
1292 
1293  _bias = giraffe_image_new(CPL_TYPE_DOUBLE);
1294  status = giraffe_image_load(_bias, cpl_frame_get_filename(_frame), 0);
1295 
1296  if (status != 0) {
1297  cpl_msg_error(fctid, "Could not load bias '%s'! Aborting ...",
1298  cpl_frame_get_filename(_frame));
1299 
1300  giraffe_image_delete(_bias);
1301  _bias = NULL;
1302 
1303  giraffe_image_delete(mbias);
1304  mbias = NULL;
1305 
1306  giraffe_image_delete(bias);
1307  bias = NULL;
1308 
1309  giraffe_paf_delete(qc);
1310  qc = NULL;
1311 
1312  return 1;
1313  }
1314 
1315  diff = cpl_image_duplicate(giraffe_image_get(bias));
1316 
1317  if (diff == NULL) {
1318  cpl_msg_error(fctid, "Cannot compute bias difference image! "
1319  "Aborting ...");
1320 
1321  giraffe_image_delete(_bias);
1322  _bias = NULL;
1323 
1324  giraffe_image_delete(mbias);
1325  mbias = NULL;
1326 
1327  giraffe_image_delete(bias);
1328  bias = NULL;
1329 
1330  giraffe_paf_delete(qc);
1331  qc = NULL;
1332 
1333  return 1;
1334  }
1335 
1336  cpl_image_subtract(diff, giraffe_image_get(_bias));
1337 
1338  giraffe_image_delete(_bias);
1339 
1340 
1341  i = 0;
1342 
1343  /* Lower left window */
1344 
1345  w.x0 = wstart;
1346  w.y0 = wstart;
1347  w.x1 = w.x0 + wsize;
1348  w.y1 = w.y0 + wsize;
1349 
1350  giraffe_error_push();
1351 
1352  sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1353 
1354  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1355  --nsigma;
1356  }
1357 
1358  giraffe_error_pop();
1359 
1360 
1361  /* Lower right window */
1362 
1363  w.x0 = cpl_image_get_size_x(diff) - wstart - wsize;
1364  w.x1 = w.x0 + wsize;
1365 
1366  giraffe_error_push();
1367 
1368  sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1369 
1370  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1371  --nsigma;
1372  }
1373 
1374  giraffe_error_pop();
1375 
1376 
1377  /* Upper right window */
1378 
1379  w.y0 = cpl_image_get_size_y(diff) - wstart - wsize;
1380  w.y1 = w.y0 + wsize;
1381 
1382  giraffe_error_push();
1383 
1384  sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1385 
1386  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1387  --nsigma;
1388  }
1389 
1390  giraffe_error_pop();
1391 
1392 
1393  /* Upper left window */
1394 
1395  w.x0 = wstart;
1396  w.x1 = w.x0 + wsize;
1397 
1398  giraffe_error_push();
1399 
1400  sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1401 
1402  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1403  --nsigma;
1404  }
1405 
1406  giraffe_error_pop();
1407 
1408 
1409  /* Central window */
1410 
1411  w.x0 = 1024;
1412  w.y0 = 1998;
1413  w.x1 = 1124;
1414  w.y1 = 2098;
1415 
1416  giraffe_error_push();
1417 
1418  sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1419 
1420  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1421  --nsigma;
1422  }
1423 
1424  giraffe_error_pop();
1425 
1426 
1427  for (i = 0; i < nsigma; i++) {
1428  sigma[i] /= sqrt(2.);
1429  }
1430 
1431  if (nsigma < 1) {
1432  cpl_msg_error(fctid, "Could not compute image statistics in any "
1433  "window! Aborting ...");
1434 
1435  cpl_image_delete(diff);
1436  diff = NULL;
1437 
1438  giraffe_image_delete(mbias);
1439  mbias = NULL;
1440 
1441  giraffe_image_delete(bias);
1442  bias = NULL;
1443 
1444  giraffe_paf_delete(qc);
1445  qc = NULL;
1446 
1447  return 1;
1448  }
1449 
1450 
1451  _sigma = cpl_vector_wrap(nsigma, sigma);
1452 
1453  median = cpl_vector_get_median(_sigma);
1454 
1455  cpl_vector_unwrap(_sigma);
1456  _sigma = NULL;
1457 
1458  cpl_image_delete(diff);
1459  diff = NULL;
1460 
1461 
1462  cpl_propertylist_update_double(properties, GIALIAS_QCRON, median);
1463  cpl_propertylist_set_comment(properties, GIALIAS_QCRON,
1464  "Readout noise (raw)");
1465 
1466  giraffe_propertylist_copy(qclog, "QC.OUT1.RON.RAW", properties,
1467  GIALIAS_QCRON);
1468  }
1469 
1470  giraffe_image_delete(bias);
1471  bias = NULL;
1472 
1473 
1474  /*
1475  * Compute read out noise on master bias frame
1476  */
1477 
1478  k = 0;
1479  nsigma = 5;
1480  memset(sigma, 0, nsigma * sizeof(cxdouble));
1481 
1482 
1483  /* Lower left window */
1484 
1485  w.x0 = wstart;
1486  w.y0 = wstart;
1487  w.x1 = w.x0 + wsize;
1488  w.y1 = w.y0 + wsize;
1489 
1490  _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1491  _mbdata = cpl_image_get_data(_smbias);
1492 
1493  nvalid = 0;
1494 
1495  for (i = 0; i < wsize * wsize; i++) {
1496 
1497  if (_mbdata[i] >= low && _mbdata[i] < high) {
1498  ++nvalid;
1499  }
1500 
1501  }
1502 
1503  _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1504  _tdata = cpl_image_get_data(_test);
1505 
1506  j = 0;
1507 
1508  for (i = 0; i < wsize * wsize; i++) {
1509 
1510  if (_mbdata[i] >= low && _mbdata[i] < high) {
1511  _tdata[j++] = _mbdata[i];
1512  }
1513 
1514  }
1515 
1516  giraffe_error_push();
1517 
1518  sigma[k++] = cpl_image_get_stdev(_test);
1519 
1520  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1521  --nsigma;
1522  }
1523 
1524  giraffe_error_pop();
1525 
1526  cpl_image_delete(_smbias);
1527  _smbias = NULL;
1528 
1529  cpl_image_delete(_test);
1530  _test = NULL;
1531 
1532  /* Lower right window */
1533 
1534  w.x0 = cpl_image_get_size_x(_mbias) - wstart - wsize;
1535  w.x1 = w.x0 + wsize;
1536 
1537  _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1538  _mbdata = cpl_image_get_data(_smbias);
1539 
1540  nvalid = 0;
1541 
1542  for (i = 0; i < wsize * wsize; i++) {
1543 
1544  if (_mbdata[i] >= low && _mbdata[i] < high) {
1545  ++nvalid;
1546  }
1547 
1548  }
1549 
1550  _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1551  _tdata = cpl_image_get_data(_test);
1552 
1553  j = 0;
1554 
1555  for (i = 0; i < wsize * wsize; i++) {
1556 
1557  if (_mbdata[i] >= low && _mbdata[i] < high) {
1558  _tdata[j++] = _mbdata[i];
1559  }
1560 
1561  }
1562 
1563  giraffe_error_push();
1564 
1565  sigma[k++] = cpl_image_get_stdev(_test);
1566 
1567  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1568  --nsigma;
1569  }
1570 
1571  giraffe_error_pop();
1572 
1573  cpl_image_delete(_smbias);
1574  _smbias = NULL;
1575 
1576  cpl_image_delete(_test);
1577  _test = NULL;
1578 
1579  /* Upper right window */
1580 
1581  w.y0 = cpl_image_get_size_y(_mbias) - wstart - wsize;
1582  w.y1 = w.y0 + wsize;
1583 
1584  _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1585  _mbdata = cpl_image_get_data(_smbias);
1586 
1587  nvalid = 0;
1588 
1589  for (i = 0; i < wsize * wsize; i++) {
1590 
1591  if (_mbdata[i] >= low && _mbdata[i] < high) {
1592  ++nvalid;
1593  }
1594 
1595  }
1596 
1597  _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1598  _tdata = cpl_image_get_data(_test);
1599 
1600  j = 0;
1601 
1602  for (i = 0; i < wsize * wsize; i++) {
1603 
1604  if (_mbdata[i] >= low && _mbdata[i] < high) {
1605  _tdata[j++] = _mbdata[i];
1606  }
1607 
1608  }
1609 
1610  giraffe_error_push();
1611 
1612  sigma[k++] = cpl_image_get_stdev(_test);
1613 
1614  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1615  --nsigma;
1616  }
1617 
1618  giraffe_error_pop();
1619 
1620  cpl_image_delete(_smbias);
1621  _smbias = NULL;
1622 
1623  cpl_image_delete(_test);
1624  _test = NULL;
1625 
1626  /* Upper left window */
1627 
1628  w.x0 = wstart;
1629  w.x1 = w.x0 + wsize;
1630 
1631  _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1632  _mbdata = cpl_image_get_data(_smbias);
1633 
1634  nvalid = 0;
1635 
1636  for (i = 0; i < wsize * wsize; i++) {
1637 
1638  if (_mbdata[i] >= low && _mbdata[i] < high) {
1639  ++nvalid;
1640  }
1641 
1642  }
1643 
1644  _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1645  _tdata = cpl_image_get_data(_test);
1646 
1647  j = 0;
1648 
1649  for (i = 0; i < wsize * wsize; i++) {
1650 
1651  if (_mbdata[i] >= low && _mbdata[i] < high) {
1652  _tdata[j++] = _mbdata[i];
1653  }
1654 
1655  }
1656 
1657  giraffe_error_push();
1658 
1659  sigma[k++] = cpl_image_get_stdev(_test);
1660 
1661  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1662  --nsigma;
1663  }
1664 
1665  giraffe_error_pop();
1666 
1667  cpl_image_delete(_smbias);
1668  _smbias = NULL;
1669 
1670  cpl_image_delete(_test);
1671  _test = NULL;
1672 
1673  /* Central window */
1674 
1675  w.x0 = 1024;
1676  w.y0 = 1998;
1677  w.x1 = 1124;
1678  w.y1 = 2098;
1679 
1680  _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1681  _mbdata = cpl_image_get_data(_smbias);
1682 
1683  nvalid = 0;
1684 
1685  for (i = 0; i < wsize * wsize; i++) {
1686 
1687  if (_mbdata[i] >= low && _mbdata[i] < high) {
1688  ++nvalid;
1689  }
1690 
1691  }
1692 
1693  _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1694  _tdata = cpl_image_get_data(_test);
1695 
1696  j = 0;
1697 
1698  for (i = 0; i < wsize * wsize; i++) {
1699 
1700  if (_mbdata[i] >= low && _mbdata[i] < high) {
1701  _tdata[j++] = _mbdata[i];
1702  }
1703 
1704  }
1705 
1706  giraffe_error_push();
1707 
1708  sigma[k++] = cpl_image_get_stdev(_test);
1709 
1710  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1711  --nsigma;
1712  }
1713 
1714  giraffe_error_pop();
1715 
1716  cpl_image_delete(_smbias);
1717  _smbias = NULL;
1718 
1719  cpl_image_delete(_test);
1720  _test = NULL;
1721 
1722  if (nsigma < 1) {
1723  cpl_msg_error(fctid, "Could not compute image statistics in any "
1724  "window! Aborting ...");
1725 
1726  giraffe_image_delete(mbias);
1727  mbias = NULL;
1728 
1729  giraffe_paf_delete(qc);
1730  qc = NULL;
1731 
1732  return 1;
1733  }
1734 
1735  _sigma = cpl_vector_wrap(nsigma, sigma);
1736 
1737  median = cpl_vector_get_median(_sigma);
1738 
1739  cpl_vector_unwrap(_sigma);
1740  _sigma = NULL;
1741 
1742  cpl_propertylist_update_double(properties, GIALIAS_QCMRON, median);
1743  cpl_propertylist_set_comment(properties, GIALIAS_QCMRON, "Readout noise "
1744  "(master)");
1745 
1746  giraffe_propertylist_copy(qclog, "QC.OUT1.RON.MASTER", properties,
1747  GIALIAS_QCMRON);
1748 
1749 
1750  /*
1751  * Compute structure along the x and y axes of the master bias.
1752  */
1753 
1754  _test = cpl_image_collapse_create(_mbias, 0);
1755  cpl_image_divide_scalar(_test, cpl_image_get_size_y(_mbias));
1756 
1757  mean = cpl_image_get_mean(_test);
1758 
1759 
1760  /*
1761  * Compute screened mean value
1762  */
1763 
1764  nvalid = 0;
1765  sum = 0.;
1766 
1767  _tdata = cpl_image_get_data(_test);
1768 
1769  for (i = 0; i < cpl_image_get_size_x(_test); i++) {
1770 
1771  if ((_tdata[i] > mean - sthreshold) &&
1772  (_tdata[i] < mean + sthreshold)) {
1773  sum += _tdata[i];
1774  ++nvalid;
1775  }
1776 
1777  }
1778 
1779  smean = sum / nvalid;
1780 
1781 
1782  /*
1783  * Compute RMS with respect to the screened mean value
1784  */
1785 
1786  nvalid = 0;
1787  sum = 0.;
1788 
1789  for (i = 0; i < cpl_image_get_size_x(_test); i++) {
1790 
1791  if ((_tdata[i] > mean - sthreshold) &&
1792  (_tdata[i] < mean + sthreshold)) {
1793  sum += pow(_tdata[i] - smean, 2.);
1794  ++nvalid;
1795  }
1796 
1797  }
1798 
1799  sum = sqrt(sum / (nvalid - 1));
1800 
1801  cpl_propertylist_update_double(properties, GIALIAS_QCSTRUCTX, sum);
1802  cpl_propertylist_set_comment(properties, GIALIAS_QCSTRUCTX,
1803  "Structure along the x axis");
1804 
1805  giraffe_propertylist_copy(qclog, "QC.OUT1.STRUCT.X", properties,
1806  GIALIAS_QCSTRUCTX);
1807 
1808  cpl_image_delete(_test);
1809  _test = NULL;
1810 
1811 
1812  _test = cpl_image_collapse_create(_mbias, 1);
1813  cpl_image_divide_scalar(_test, cpl_image_get_size_x(_mbias));
1814 
1815  mean = cpl_image_get_mean(_test);
1816 
1817 
1818  /*
1819  * Compute screened mean value
1820  */
1821 
1822  nvalid = 0;
1823  sum = 0.;
1824 
1825  _tdata = cpl_image_get_data(_test);
1826 
1827  for (i = 0; i < cpl_image_get_size_y(_test); i++) {
1828 
1829  if ((_tdata[i] > mean - sthreshold) &&
1830  (_tdata[i] < mean + sthreshold)) {
1831  sum += _tdata[i];
1832  ++nvalid;
1833  }
1834 
1835  }
1836 
1837  smean = sum / nvalid;
1838 
1839 
1840  /*
1841  * Compute RMS with respect to the screened mean value
1842  */
1843 
1844  nvalid = 0;
1845  sum = 0.;
1846 
1847  _tdata = cpl_image_get_data(_test);
1848 
1849  for (i = 0; i < cpl_image_get_size_y(_test); i++) {
1850 
1851  if ((_tdata[i] > mean - sthreshold) &&
1852  (_tdata[i] < mean + sthreshold)) {
1853  sum += pow(_tdata[i] - smean, 2.);
1854  ++nvalid;
1855  }
1856 
1857  }
1858 
1859  sum = sqrt(sum / (nvalid - 1));
1860 
1861  cpl_propertylist_update_double(properties, GIALIAS_QCSTRUCTY, sum);
1862  cpl_propertylist_set_comment(properties, GIALIAS_QCSTRUCTY,
1863  "Structure along the y axis");
1864 
1865  giraffe_propertylist_copy(qclog, "QC.OUT1.STRUCT.Y", properties,
1866  GIALIAS_QCSTRUCTY);
1867 
1868  cpl_image_delete(_test);
1869  _test = NULL;
1870 
1871 
1872  /*
1873  * Write QC1 log and save updated master bias.
1874  */
1875 
1876  giraffe_image_save(mbias, cpl_frame_get_filename(pframe));
1877 
1878  giraffe_image_delete(mbias);
1879  mbias = NULL;
1880 
1881  giraffe_qclog_close(qc);
1882  qc = NULL;
1883 
1884  return 0;
1885 
1886 }
1887 
1888 
1889 /*
1890  * Build table of contents, i.e. the list of available plugins, for
1891  * this module. This function is exported.
1892  */
1893 
1894 int
1895 cpl_plugin_get_info(cpl_pluginlist* list)
1896 {
1897 
1898  cpl_recipe* recipe = cx_calloc(1, sizeof *recipe);
1899  cpl_plugin* plugin = &recipe->interface;
1900 
1901 
1902  cpl_plugin_init(plugin,
1903  CPL_PLUGIN_API,
1904  GIRAFFE_BINARY_VERSION,
1905  CPL_PLUGIN_TYPE_RECIPE,
1906  "gimasterbias",
1907  "Creates a master bias image from a set of raw biases.",
1908  "For detailed information please refer to the "
1909  "GIRAFFE pipeline user manual.\nIt is available at "
1910  "http://www.eso.org/pipelines.",
1911  "Giraffe Pipeline",
1912  PACKAGE_BUGREPORT,
1914  gimasterbias_create,
1915  gimasterbias_exec,
1916  gimasterbias_destroy);
1917 
1918  cpl_pluginlist_append(list, plugin);
1919 
1920  return 0;
1921 
1922 }

This file is part of the GIRAFFE Pipeline Reference Manual 2.12.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Mon Mar 24 2014 11:43:52 by doxygen 1.8.2 written by Dimitri van Heesch, © 1997-2004