GIRAFFE Pipeline Reference Manual

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

This file is part of the GIRAFFE Pipeline Reference Manual 2.16.12.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Mon Dec 2 2024 11:59:44 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2004