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  cxdouble conad = 1;
870 
871 
872  ron = cpl_propertylist_get_double(properties, GIALIAS_RON);
873 
874  giraffe_error_push();
875 
876  conad = giraffe_propertylist_get_conad(properties);
877 
878  if (cpl_error_get_code() != CPL_ERROR_NONE) {
879 
880  giraffe_image_delete(bpixel);
881  bpixel = NULL;
882 
883  giraffe_image_delete(master_bias);
884  master_bias = NULL;
885 
886  return -1;
887 
888  }
889 
890  giraffe_error_pop();
891 
892  ron /= conad;
893 
894  }
895  else {
896 
897  ron = cpl_image_get_stdev(giraffe_image_get(master_bias));
898 
899  }
900 
901  }
902 
903  cpl_msg_info(fctid, "Using local median +/- %.4f [ADU] as "
904  "valid pixel value range", ron);
905 
906 
907  for (i = 0; i < nrow; ++i) {
908 
909  register cxint stride = i * ncol;
910  register cxint* bpx_row = pi_bpm + stride;
911 
912  register const cxdouble* bias_row = pd_mbias + stride;
913 
914  register cxdouble sdev = 0.;
915 
916  median = giraffe_array_median(bias_row, ncol);
917 
918  for (j = 0; j < ncol; ++j) {
919  sdev += (bias_row[j] - median) * (bias_row[j] - median);
920  }
921  sdev = sqrt(sdev / (cxdouble)(ncol - 1));
922 
923  if (median < median_min) {
924  median_min = median;
925  /*row_min = i;*/
926  }
927 
928  if (median > median_max) {
929  median_max = median;
930  /*row_max = i;*/
931  }
932 
933  tlow = median - mbias_config.bpm.factor * ron;
934  thigh = median + mbias_config.bpm.factor * ron;
935 
936  for (j = 0; j < ncol; ++j) {
937 
938  if ((bias_row[j] < tlow) || (bias_row[j] > thigh)) {
939  bpx_row[j] = 1;
940  ++nbpx;
941  }
942  else {
943  bpx_row[j] = 0;
944  }
945 
946  }
947 
948  }
949 
950 
951  if (nbpx > nbpx_max) {
952  cpl_msg_warning(fctid, "Number of bad pixels found (%ld) exceeds "
953  "maximum number of bad pixels expected (%ld)!", nbpx,
954  nbpx_max);
955  }
956 
957  properties = giraffe_image_get_properties(bpixel);
958 
959  cpl_propertylist_update_double(properties, GIALIAS_BZERO, 0.);
960 
961  cpl_propertylist_update_double(properties,
962  GIALIAS_BPM_FRACTION, mbias_config.bpm.fraction);
963  cpl_propertylist_set_comment(properties, GIALIAS_BPM_FRACTION,
964  "Maximum fraction of bad pixels allowed.");
965 
966  cpl_propertylist_update_int(properties,
967  GIALIAS_BPM_NPIX, nbpx);
968  cpl_propertylist_set_comment(properties, GIALIAS_BPM_NPIX,
969  "Number of pixels flagged as bad.");
970 
971  cpl_propertylist_update_double(properties,
972  GIALIAS_BPM_MEDIAN_MIN, median_min);
973  cpl_propertylist_set_comment(properties, GIALIAS_BPM_MEDIAN_MIN,
974  "Minimum median pixel value used for bad pixel detection.");
975 
976  cpl_propertylist_update_double(properties,
977  GIALIAS_BPM_MEDIAN_MAX, median_max);
978  cpl_propertylist_set_comment(properties, GIALIAS_BPM_MEDIAN_MAX,
979  "Maximum median pixel value used for bad pixel detection.");
980 
981  cpl_propertylist_update_double(properties,
982  GIALIAS_BPM_FACTOR, mbias_config.bpm.factor);
983  cpl_propertylist_set_comment(properties, GIALIAS_BPM_FACTOR,
984  "Noise multiplier defining thresholds for bad pixel "
985  "detection.");
986 
987  cpl_propertylist_update_double(properties,
988  GIALIAS_BPM_NOISE, ron);
989  cpl_propertylist_set_comment(properties, GIALIAS_BPM_NOISE,
990  "Bias noise value [ADU] used for bad pixel detection.");
991 
992  giraffe_image_add_info(bpixel, &info, set);
993 
994  product_frame = giraffe_frame_create_image(bpixel,
995  GIFRAME_BADPIXEL_MAP,
996  CPL_FRAME_LEVEL_FINAL,
997  TRUE, TRUE);
998 
999  if (product_frame == NULL) {
1000 
1001  cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
1002 
1003  if (master_bias != NULL) {
1004  giraffe_image_delete(master_bias);
1005  }
1006 
1007  if (bpixel != NULL) {
1008  giraffe_image_delete(bpixel);
1009  }
1010 
1011  return -1;
1012 
1013  }
1014 
1015  cpl_frameset_insert(set, product_frame);
1016 
1017 
1018  /*
1019  * Clean up
1020  */
1021 
1022  if (bpixel != NULL) {
1023  giraffe_image_delete(bpixel);
1024  }
1025 
1026  }
1027 
1028  if (master_bias != NULL) {
1029  giraffe_image_delete(master_bias);
1030  }
1031 
1032  return 0;
1033 
1034 }
1035 
1036 
1037 /*
1038  * The quality control task starts here.
1039  */
1040 
1041 static cxint
1042 giqcmasterbias(cpl_frameset* set)
1043 {
1044 
1045  const cxchar* const fctid = "giqcmasterbias";
1046 
1047 
1048  const cxint wstart = 50;
1049  const cxint wsize = 100;
1050 
1051  cxint i;
1052  cxint j;
1053  cxint k;
1054  cxint nx = 0;
1055  cxint ny = 0;
1056  cxint nvalid = 0;
1057  cxint status = 0;
1058  cxint nsigma = 5;
1059 
1060  const cxdouble low = 100.;
1061  const cxdouble high = 300.;
1062  const cxdouble sthreshold = 2.;
1063 
1064  cxdouble mean = 0.;
1065  cxdouble median = 0.;
1066  cxdouble smean = 0.;
1067  cxdouble sum = 0.;
1068  cxdouble* _mbdata = NULL;
1069  cxdouble* _tdata = NULL;
1070  cxdouble sigma[nsigma];
1071 
1072  cpl_propertylist* properties = NULL;
1073  cpl_propertylist* qclog = NULL;
1074 
1075  cpl_vector* _sigma = NULL;
1076 
1077  cpl_image* _mbias = NULL;
1078  cpl_image* _smbias = NULL;
1079  cpl_image* _test = NULL;
1080 
1081  cpl_frame* rframe = NULL;
1082  cpl_frame* pframe = NULL;
1083 
1084  GiPaf* qc = NULL;
1085 
1086  GiImage* mbias = NULL;
1087  GiImage* bias = NULL;
1088 
1089  GiWindow w;
1090 
1091 
1092  cpl_msg_info(fctid, "Computing QC1 parameters ...");
1093 
1094  qc = giraffe_qclog_open(0);
1095 
1096  if (qc == NULL) {
1097  cpl_msg_error(fctid, "Cannot create QC1 log!");
1098  return 1;
1099  }
1100 
1101  qclog = giraffe_paf_get_properties(qc);
1102  cx_assert(qclog != NULL);
1103 
1104 
1105  /*
1106  * Process master bias
1107  */
1108 
1109  pframe = giraffe_get_frame(set, GIFRAME_BIAS_MASTER,
1110  CPL_FRAME_GROUP_PRODUCT);
1111 
1112  if (pframe == NULL) {
1113  cpl_msg_error(fctid, "Missing product frame (%s)",
1114  GIFRAME_BIAS_MASTER);
1115 
1116  giraffe_paf_delete(qc);
1117  qc = NULL;
1118 
1119  return 1;
1120  }
1121 
1122  cpl_msg_info(fctid, "Processing product frame '%s' (%s)",
1123  cpl_frame_get_filename(pframe), cpl_frame_get_tag(pframe));
1124 
1125  mbias = giraffe_image_new(CPL_TYPE_DOUBLE);
1126  status = giraffe_image_load(mbias, cpl_frame_get_filename(pframe), 0);
1127 
1128  if (status != 0) {
1129  cpl_msg_error(fctid, "Could not load master bias '%s'! Aborting ...",
1130  cpl_frame_get_filename(pframe));
1131 
1132  giraffe_image_delete(mbias);
1133  mbias = NULL;
1134 
1135  giraffe_paf_delete(qc);
1136  qc = NULL;
1137 
1138  return 1;
1139  }
1140 
1141 
1142  /*
1143  * Load first raw image as reference
1144  */
1145 
1146  rframe = cpl_frameset_find(set, GIFRAME_BIAS);
1147 
1148  if (rframe == NULL) {
1149  cpl_msg_error(fctid, "Missing raw frame (%s)", GIFRAME_BIAS);
1150 
1151  giraffe_image_delete(mbias);
1152  mbias = NULL;
1153 
1154  giraffe_paf_delete(qc);
1155  qc = NULL;
1156 
1157  return 1;
1158  }
1159 
1160  bias = giraffe_image_new(CPL_TYPE_DOUBLE);
1161  status = giraffe_image_load(bias, cpl_frame_get_filename(rframe), 0);
1162 
1163  if (status != 0) {
1164  cpl_msg_error(fctid, "Could not load bias '%s'!",
1165  cpl_frame_get_filename(rframe));
1166 
1167  giraffe_image_delete(bias);
1168  bias = NULL;
1169 
1170  giraffe_image_delete(mbias);
1171  mbias = NULL;
1172 
1173  giraffe_paf_delete(qc);
1174  qc = NULL;
1175 
1176  return 1;
1177 
1178  }
1179 
1180  properties = giraffe_image_get_properties(bias);
1181  cx_assert(properties != NULL);
1182 
1183  giraffe_propertylist_copy(qclog, "ARCFILE", properties, GIALIAS_ARCFILE);
1184  giraffe_propertylist_copy(qclog, "TPL.ID", properties, GIALIAS_TPLID);
1185 
1186  cpl_propertylist_update_string(qclog, "PRO.CATG",
1187  cpl_frame_get_tag(pframe));
1188  cpl_propertylist_set_comment(qclog, "PRO.CATG",
1189  "Pipeline product category");
1190 
1191  properties = giraffe_image_get_properties(mbias);
1192  cx_assert(properties != NULL);
1193 
1194  giraffe_propertylist_copy(qclog, "PRO.DATAAVG",
1195  properties, GIALIAS_DATAMEAN);
1196  giraffe_propertylist_copy(qclog, "PRO.DATARMS",
1197  properties, GIALIAS_DATASIG);
1198  giraffe_propertylist_copy(qclog, "PRO.DATAMED",
1199  properties, GIALIAS_DATAMEDI);
1200  giraffe_propertylist_copy(qclog, "PRO.DATANCOM",
1201  properties, GIALIAS_DATANCOM);
1202 
1203 
1204  /*
1205  * Create screened test image for statistics computation
1206  */
1207 
1208  _mbias = giraffe_image_get(mbias);
1209  _mbdata = cpl_image_get_data(_mbias);
1210 
1211  nx = cpl_image_get_size_x(_mbias);
1212  ny = cpl_image_get_size_y(_mbias);
1213 
1214  nvalid = 0;
1215 
1216  for (i = 0; i < nx * ny; i++) {
1217 
1218  if (_mbdata[i] >= low && _mbdata[i] < high) {
1219  ++nvalid;
1220  }
1221 
1222  }
1223 
1224  _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1225  _tdata = cpl_image_get_data(_test);
1226 
1227  j = 0;
1228 
1229  for (i = 0; i < nx * ny; i++) {
1230 
1231  if (_mbdata[i] >= low && _mbdata[i] < high) {
1232  _tdata[j++] = _mbdata[i];
1233  }
1234 
1235  }
1236 
1237  cpl_propertylist_update_double(properties, GIALIAS_QCMBIASMED,
1238  cpl_image_get_median(_test));
1239  cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASMED,
1240  "Median master bias level (ADU)");
1241 
1242  cpl_propertylist_update_double(properties, GIALIAS_QCMBIASAVG,
1243  cpl_image_get_mean(_test));
1244  cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASAVG,
1245  "Mean master bias level (ADU)");
1246 
1247  cpl_propertylist_update_double(properties, GIALIAS_QCMBIASRMS,
1248  cpl_image_get_stdev(_test));
1249  cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASRMS,
1250  "RMS of master bias level (ADU)");
1251 
1252  cpl_image_delete(_test);
1253  _test = NULL;
1254 
1255  giraffe_propertylist_copy(qclog, "QC.BIAS.MASTER.MEDIAN",
1256  properties, GIALIAS_QCMBIASMED);
1257  giraffe_propertylist_copy(qclog, "QC.BIAS.MASTER.MEAN",
1258  properties, GIALIAS_QCMBIASAVG);
1259  giraffe_propertylist_copy(qclog, "QC.BIAS.MASTER.RMS",
1260  properties, GIALIAS_QCMBIASRMS);
1261 
1262 
1263  /*
1264  * Compute read out noise on raw frames if at least 2 raw
1265  * biases are available.
1266  */
1267 
1268  if (cpl_frameset_count_tags(set, GIFRAME_BIAS) > 1) {
1269 
1270  cpl_frame* _frame = NULL;
1271 
1272  cpl_image* diff = NULL;
1273 
1274  GiImage* _bias;
1275 
1276 
1277  nsigma = 5;
1278  memset(sigma, 0, nsigma * sizeof(cxdouble));
1279 
1280  _frame = cpl_frameset_find(set, GIFRAME_BIAS);
1281  _frame = cpl_frameset_find(set, NULL);
1282 
1283  _bias = giraffe_image_new(CPL_TYPE_DOUBLE);
1284  status = giraffe_image_load(_bias, cpl_frame_get_filename(_frame), 0);
1285 
1286  if (status != 0) {
1287  cpl_msg_error(fctid, "Could not load bias '%s'! Aborting ...",
1288  cpl_frame_get_filename(_frame));
1289 
1290  giraffe_image_delete(_bias);
1291  _bias = NULL;
1292 
1293  giraffe_image_delete(mbias);
1294  mbias = NULL;
1295 
1296  giraffe_image_delete(bias);
1297  bias = NULL;
1298 
1299  giraffe_paf_delete(qc);
1300  qc = NULL;
1301 
1302  return 1;
1303  }
1304 
1305  diff = cpl_image_duplicate(giraffe_image_get(bias));
1306 
1307  if (diff == NULL) {
1308  cpl_msg_error(fctid, "Cannot compute bias difference image! "
1309  "Aborting ...");
1310 
1311  giraffe_image_delete(_bias);
1312  _bias = NULL;
1313 
1314  giraffe_image_delete(mbias);
1315  mbias = NULL;
1316 
1317  giraffe_image_delete(bias);
1318  bias = NULL;
1319 
1320  giraffe_paf_delete(qc);
1321  qc = NULL;
1322 
1323  return 1;
1324  }
1325 
1326  cpl_image_subtract(diff, giraffe_image_get(_bias));
1327 
1328  giraffe_image_delete(_bias);
1329 
1330 
1331  i = 0;
1332 
1333  /* Lower left window */
1334 
1335  w.x0 = wstart;
1336  w.y0 = wstart;
1337  w.x1 = w.x0 + wsize;
1338  w.y1 = w.y0 + wsize;
1339 
1340  giraffe_error_push();
1341 
1342  sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1343 
1344  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1345  --nsigma;
1346  }
1347 
1348  giraffe_error_pop();
1349 
1350 
1351  /* Lower right window */
1352 
1353  w.x0 = cpl_image_get_size_x(diff) - wstart - wsize;
1354  w.x1 = w.x0 + wsize;
1355 
1356  giraffe_error_push();
1357 
1358  sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1359 
1360  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1361  --nsigma;
1362  }
1363 
1364  giraffe_error_pop();
1365 
1366 
1367  /* Upper right window */
1368 
1369  w.y0 = cpl_image_get_size_y(diff) - wstart - wsize;
1370  w.y1 = w.y0 + wsize;
1371 
1372  giraffe_error_push();
1373 
1374  sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1375 
1376  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1377  --nsigma;
1378  }
1379 
1380  giraffe_error_pop();
1381 
1382 
1383  /* Upper left window */
1384 
1385  w.x0 = wstart;
1386  w.x1 = w.x0 + wsize;
1387 
1388  giraffe_error_push();
1389 
1390  sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1391 
1392  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1393  --nsigma;
1394  }
1395 
1396  giraffe_error_pop();
1397 
1398 
1399  /* Central window */
1400 
1401  w.x0 = 1024;
1402  w.y0 = 1998;
1403  w.x1 = 1124;
1404  w.y1 = 2098;
1405 
1406  giraffe_error_push();
1407 
1408  sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1409 
1410  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1411  --nsigma;
1412  }
1413 
1414  giraffe_error_pop();
1415 
1416 
1417  for (i = 0; i < nsigma; i++) {
1418  sigma[i] /= sqrt(2.);
1419  }
1420 
1421  if (nsigma < 1) {
1422  cpl_msg_error(fctid, "Could not compute image statistics in any "
1423  "window! Aborting ...");
1424 
1425  cpl_image_delete(diff);
1426  diff = NULL;
1427 
1428  giraffe_image_delete(mbias);
1429  mbias = NULL;
1430 
1431  giraffe_image_delete(bias);
1432  bias = NULL;
1433 
1434  giraffe_paf_delete(qc);
1435  qc = NULL;
1436 
1437  return 1;
1438  }
1439 
1440 
1441  _sigma = cpl_vector_wrap(nsigma, sigma);
1442 
1443  median = cpl_vector_get_median(_sigma);
1444 
1445  cpl_vector_unwrap(_sigma);
1446  _sigma = NULL;
1447 
1448  cpl_image_delete(diff);
1449  diff = NULL;
1450 
1451 
1452  cpl_propertylist_update_double(properties, GIALIAS_QCRON, median);
1453  cpl_propertylist_set_comment(properties, GIALIAS_QCRON,
1454  "Readout noise (raw)");
1455 
1456  giraffe_propertylist_copy(qclog, "QC.OUT1.RON.RAW", properties,
1457  GIALIAS_QCRON);
1458  }
1459 
1460  giraffe_image_delete(bias);
1461  bias = NULL;
1462 
1463 
1464  /*
1465  * Compute read out noise on master bias frame
1466  */
1467 
1468  k = 0;
1469  nsigma = 5;
1470  memset(sigma, 0, nsigma * sizeof(cxdouble));
1471 
1472 
1473  /* Lower left window */
1474 
1475  w.x0 = wstart;
1476  w.y0 = wstart;
1477  w.x1 = w.x0 + wsize;
1478  w.y1 = w.y0 + wsize;
1479 
1480  _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1481  _mbdata = cpl_image_get_data(_smbias);
1482 
1483  nvalid = 0;
1484 
1485  for (i = 0; i < wsize * wsize; i++) {
1486 
1487  if (_mbdata[i] >= low && _mbdata[i] < high) {
1488  ++nvalid;
1489  }
1490 
1491  }
1492 
1493  _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1494  _tdata = cpl_image_get_data(_test);
1495 
1496  j = 0;
1497 
1498  for (i = 0; i < wsize * wsize; i++) {
1499 
1500  if (_mbdata[i] >= low && _mbdata[i] < high) {
1501  _tdata[j++] = _mbdata[i];
1502  }
1503 
1504  }
1505 
1506  giraffe_error_push();
1507 
1508  sigma[k++] = cpl_image_get_stdev(_test);
1509 
1510  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1511  --nsigma;
1512  }
1513 
1514  giraffe_error_pop();
1515 
1516  cpl_image_delete(_smbias);
1517  _smbias = NULL;
1518 
1519  cpl_image_delete(_test);
1520  _test = NULL;
1521 
1522  /* Lower right window */
1523 
1524  w.x0 = cpl_image_get_size_x(_mbias) - wstart - wsize;
1525  w.x1 = w.x0 + wsize;
1526 
1527  _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1528  _mbdata = cpl_image_get_data(_smbias);
1529 
1530  nvalid = 0;
1531 
1532  for (i = 0; i < wsize * wsize; i++) {
1533 
1534  if (_mbdata[i] >= low && _mbdata[i] < high) {
1535  ++nvalid;
1536  }
1537 
1538  }
1539 
1540  _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1541  _tdata = cpl_image_get_data(_test);
1542 
1543  j = 0;
1544 
1545  for (i = 0; i < wsize * wsize; i++) {
1546 
1547  if (_mbdata[i] >= low && _mbdata[i] < high) {
1548  _tdata[j++] = _mbdata[i];
1549  }
1550 
1551  }
1552 
1553  giraffe_error_push();
1554 
1555  sigma[k++] = cpl_image_get_stdev(_test);
1556 
1557  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1558  --nsigma;
1559  }
1560 
1561  giraffe_error_pop();
1562 
1563  cpl_image_delete(_smbias);
1564  _smbias = NULL;
1565 
1566  cpl_image_delete(_test);
1567  _test = NULL;
1568 
1569  /* Upper right window */
1570 
1571  w.y0 = cpl_image_get_size_y(_mbias) - wstart - wsize;
1572  w.y1 = w.y0 + wsize;
1573 
1574  _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1575  _mbdata = cpl_image_get_data(_smbias);
1576 
1577  nvalid = 0;
1578 
1579  for (i = 0; i < wsize * wsize; i++) {
1580 
1581  if (_mbdata[i] >= low && _mbdata[i] < high) {
1582  ++nvalid;
1583  }
1584 
1585  }
1586 
1587  _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1588  _tdata = cpl_image_get_data(_test);
1589 
1590  j = 0;
1591 
1592  for (i = 0; i < wsize * wsize; i++) {
1593 
1594  if (_mbdata[i] >= low && _mbdata[i] < high) {
1595  _tdata[j++] = _mbdata[i];
1596  }
1597 
1598  }
1599 
1600  giraffe_error_push();
1601 
1602  sigma[k++] = cpl_image_get_stdev(_test);
1603 
1604  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1605  --nsigma;
1606  }
1607 
1608  giraffe_error_pop();
1609 
1610  cpl_image_delete(_smbias);
1611  _smbias = NULL;
1612 
1613  cpl_image_delete(_test);
1614  _test = NULL;
1615 
1616  /* Upper left window */
1617 
1618  w.x0 = wstart;
1619  w.x1 = w.x0 + wsize;
1620 
1621  _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1622  _mbdata = cpl_image_get_data(_smbias);
1623 
1624  nvalid = 0;
1625 
1626  for (i = 0; i < wsize * wsize; i++) {
1627 
1628  if (_mbdata[i] >= low && _mbdata[i] < high) {
1629  ++nvalid;
1630  }
1631 
1632  }
1633 
1634  _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1635  _tdata = cpl_image_get_data(_test);
1636 
1637  j = 0;
1638 
1639  for (i = 0; i < wsize * wsize; i++) {
1640 
1641  if (_mbdata[i] >= low && _mbdata[i] < high) {
1642  _tdata[j++] = _mbdata[i];
1643  }
1644 
1645  }
1646 
1647  giraffe_error_push();
1648 
1649  sigma[k++] = cpl_image_get_stdev(_test);
1650 
1651  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1652  --nsigma;
1653  }
1654 
1655  giraffe_error_pop();
1656 
1657  cpl_image_delete(_smbias);
1658  _smbias = NULL;
1659 
1660  cpl_image_delete(_test);
1661  _test = NULL;
1662 
1663  /* Central window */
1664 
1665  w.x0 = 1024;
1666  w.y0 = 1998;
1667  w.x1 = 1124;
1668  w.y1 = 2098;
1669 
1670  _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1671  _mbdata = cpl_image_get_data(_smbias);
1672 
1673  nvalid = 0;
1674 
1675  for (i = 0; i < wsize * wsize; i++) {
1676 
1677  if (_mbdata[i] >= low && _mbdata[i] < high) {
1678  ++nvalid;
1679  }
1680 
1681  }
1682 
1683  _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1684  _tdata = cpl_image_get_data(_test);
1685 
1686  j = 0;
1687 
1688  for (i = 0; i < wsize * wsize; i++) {
1689 
1690  if (_mbdata[i] >= low && _mbdata[i] < high) {
1691  _tdata[j++] = _mbdata[i];
1692  }
1693 
1694  }
1695 
1696  giraffe_error_push();
1697 
1698  sigma[k++] = cpl_image_get_stdev(_test);
1699 
1700  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1701  --nsigma;
1702  }
1703 
1704  giraffe_error_pop();
1705 
1706  cpl_image_delete(_smbias);
1707  _smbias = NULL;
1708 
1709  cpl_image_delete(_test);
1710  _test = NULL;
1711 
1712  if (nsigma < 1) {
1713  cpl_msg_error(fctid, "Could not compute image statistics in any "
1714  "window! Aborting ...");
1715 
1716  giraffe_image_delete(mbias);
1717  mbias = NULL;
1718 
1719  giraffe_paf_delete(qc);
1720  qc = NULL;
1721 
1722  return 1;
1723  }
1724 
1725  _sigma = cpl_vector_wrap(nsigma, sigma);
1726 
1727  median = cpl_vector_get_median(_sigma);
1728 
1729  cpl_vector_unwrap(_sigma);
1730  _sigma = NULL;
1731 
1732  cpl_propertylist_update_double(properties, GIALIAS_QCMRON, median);
1733  cpl_propertylist_set_comment(properties, GIALIAS_QCMRON, "Readout noise "
1734  "(master)");
1735 
1736  giraffe_propertylist_copy(qclog, "QC.OUT1.RON.MASTER", properties,
1737  GIALIAS_QCMRON);
1738 
1739 
1740  /*
1741  * Compute structure along the x and y axes of the master bias.
1742  */
1743 
1744  _test = cpl_image_collapse_create(_mbias, 0);
1745  cpl_image_divide_scalar(_test, cpl_image_get_size_y(_mbias));
1746 
1747  mean = cpl_image_get_mean(_test);
1748 
1749 
1750  /*
1751  * Compute screened mean value
1752  */
1753 
1754  nvalid = 0;
1755  sum = 0.;
1756 
1757  _tdata = cpl_image_get_data(_test);
1758 
1759  for (i = 0; i < cpl_image_get_size_x(_test); i++) {
1760 
1761  if ((_tdata[i] > mean - sthreshold) &&
1762  (_tdata[i] < mean + sthreshold)) {
1763  sum += _tdata[i];
1764  ++nvalid;
1765  }
1766 
1767  }
1768 
1769  smean = sum / nvalid;
1770 
1771 
1772  /*
1773  * Compute RMS with respect to the screened mean value
1774  */
1775 
1776  nvalid = 0;
1777  sum = 0.;
1778 
1779  for (i = 0; i < cpl_image_get_size_x(_test); i++) {
1780 
1781  if ((_tdata[i] > mean - sthreshold) &&
1782  (_tdata[i] < mean + sthreshold)) {
1783  sum += pow(_tdata[i] - smean, 2.);
1784  ++nvalid;
1785  }
1786 
1787  }
1788 
1789  sum = sqrt(sum / (nvalid - 1));
1790 
1791  cpl_propertylist_update_double(properties, GIALIAS_QCSTRUCTX, sum);
1792  cpl_propertylist_set_comment(properties, GIALIAS_QCSTRUCTX,
1793  "Structure along the x axis");
1794 
1795  giraffe_propertylist_copy(qclog, "QC.OUT1.STRUCT.X", properties,
1796  GIALIAS_QCSTRUCTX);
1797 
1798  cpl_image_delete(_test);
1799  _test = NULL;
1800 
1801 
1802  _test = cpl_image_collapse_create(_mbias, 1);
1803  cpl_image_divide_scalar(_test, cpl_image_get_size_x(_mbias));
1804 
1805  mean = cpl_image_get_mean(_test);
1806 
1807 
1808  /*
1809  * Compute screened mean value
1810  */
1811 
1812  nvalid = 0;
1813  sum = 0.;
1814 
1815  _tdata = cpl_image_get_data(_test);
1816 
1817  for (i = 0; i < cpl_image_get_size_y(_test); i++) {
1818 
1819  if ((_tdata[i] > mean - sthreshold) &&
1820  (_tdata[i] < mean + sthreshold)) {
1821  sum += _tdata[i];
1822  ++nvalid;
1823  }
1824 
1825  }
1826 
1827  smean = sum / nvalid;
1828 
1829 
1830  /*
1831  * Compute RMS with respect to the screened mean value
1832  */
1833 
1834  nvalid = 0;
1835  sum = 0.;
1836 
1837  _tdata = cpl_image_get_data(_test);
1838 
1839  for (i = 0; i < cpl_image_get_size_y(_test); i++) {
1840 
1841  if ((_tdata[i] > mean - sthreshold) &&
1842  (_tdata[i] < mean + sthreshold)) {
1843  sum += pow(_tdata[i] - smean, 2.);
1844  ++nvalid;
1845  }
1846 
1847  }
1848 
1849  sum = sqrt(sum / (nvalid - 1));
1850 
1851  cpl_propertylist_update_double(properties, GIALIAS_QCSTRUCTY, sum);
1852  cpl_propertylist_set_comment(properties, GIALIAS_QCSTRUCTY,
1853  "Structure along the y axis");
1854 
1855  giraffe_propertylist_copy(qclog, "QC.OUT1.STRUCT.Y", properties,
1856  GIALIAS_QCSTRUCTY);
1857 
1858  cpl_image_delete(_test);
1859  _test = NULL;
1860 
1861 
1862  /*
1863  * Write QC1 log and save updated master bias.
1864  */
1865 
1866  giraffe_image_save(mbias, cpl_frame_get_filename(pframe));
1867 
1868  giraffe_image_delete(mbias);
1869  mbias = NULL;
1870 
1871  giraffe_qclog_close(qc);
1872  qc = NULL;
1873 
1874  return 0;
1875 
1876 }
1877 
1878 
1879 /*
1880  * Build table of contents, i.e. the list of available plugins, for
1881  * this module. This function is exported.
1882  */
1883 
1884 int
1885 cpl_plugin_get_info(cpl_pluginlist* list)
1886 {
1887 
1888  cpl_recipe* recipe = cx_calloc(1, sizeof *recipe);
1889  cpl_plugin* plugin = &recipe->interface;
1890 
1891 
1892  cpl_plugin_init(plugin,
1893  CPL_PLUGIN_API,
1894  GIRAFFE_BINARY_VERSION,
1895  CPL_PLUGIN_TYPE_RECIPE,
1896  "gimasterbias",
1897  "Creates a master bias image from a set of raw biases.",
1898  "For detailed information please refer to the "
1899  "GIRAFFE pipeline user manual.\nIt is available at "
1900  "http://www.eso.org/pipelines.",
1901  "Giraffe Pipeline",
1902  PACKAGE_BUGREPORT,
1904  gimasterbias_create,
1905  gimasterbias_exec,
1906  gimasterbias_destroy);
1907 
1908  cpl_pluginlist_append(list, plugin);
1909 
1910  return 0;
1911 
1912 }
cxint giraffe_image_add_info(GiImage *image, const GiRecipeInfo *info, const cpl_frameset *set)
Add additional frame information to an image.
Definition: giimage.c:781
cpl_frame * giraffe_get_frame(const cpl_frameset *set, const cxchar *tag, cpl_frame_group group)
Get a frame from a frame set.
Definition: giframe.c:736
GiImage * giraffe_stacking_stack_images(GiImage **img_array, const GiStackingConfig *config)
Stack a list of images using one of four different kinds of stacking and return the resulting image...
Definition: gistacking.c:579
cxint giraffe_trim_raw_areas(GiImage *image)
Remove pre- and overscan ares from an image.
Definition: gibias.c:2922
cxint giraffe_image_load(GiImage *self, const cxchar *filename, cxint position)
Gets image data and properties from a file.
Definition: giimage.c:544
cxint giraffe_image_save(GiImage *self, const cxchar *filename)
Write a Giraffe image to a file.
Definition: giimage.c:578
void giraffe_stacking_config_destroy(GiStackingConfig *config)
Destroys a setup structure for the stacking of images.
Definition: gistacking.c:797
void giraffe_image_delete(GiImage *self)
Destroys an image.
Definition: giimage.c:189
cxdouble giraffe_propertylist_get_conad(const cpl_propertylist *properties)
Retrieve the ADU to electrons conversion factor from the given properties.
Definition: giutils.c:1274
cxint giraffe_propertylist_copy(cpl_propertylist *self, const cxchar *name, const cpl_propertylist *other, const cxchar *othername)
Copy a property from one list to another.
Definition: giutils.c:909
GiImage * giraffe_image_new(cpl_type type)
Creates an empty image container.
Definition: giimage.c:73
GiStackingConfig * giraffe_stacking_config_create(cpl_parameterlist *list)
Creates a setup structure for the stacking of images.
Definition: gistacking.c:681
GiImage * giraffe_image_create(cpl_type type, cxint nx, cxint ny)
Creates an image container of a given type.
Definition: giimage.c:103
const cxchar * giraffe_get_license(void)
Get the pipeline copyright and license.
Definition: giutils.c:284
void giraffe_stacking_config_add(cpl_parameterlist *list)
Adds parameters for the stacking of images.
Definition: gistacking.c:820
cpl_image * giraffe_image_get(const GiImage *self)
Gets the image data.
Definition: giimage.c:226
cxint giraffe_image_set_properties(GiImage *self, cpl_propertylist *properties)
Attaches a property list to an image.
Definition: giimage.c:320
cpl_frame * giraffe_frame_create_image(GiImage *image, const cxchar *tag, cpl_frame_level level, cxbool save, cxbool update)
Create an image product frame.
Definition: giframe.c:401
cpl_propertylist * giraffe_image_get_properties(const GiImage *self)
Get the properties of an image.
Definition: giimage.c:290

This file is part of the GIRAFFE Pipeline Reference Manual 2.14.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Wed Mar 11 2015 13:19:41 by doxygen 1.8.9.1 written by Dimitri van Heesch, © 1997-2004