IIINSTRUMENT Pipeline Reference Manual 1.3.14
detmon/detmon_ronbias.c
1/* $Id: detmon.c,v 1.11 2013-07-19 12:00:24 jtaylor Exp $
2 *
3 * This file is part of the irplib package
4 * Copyright (C) 2002, 2003 European Southern Observatory
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * $Author: jtaylor $
23 * $Date: 2013-07-19 12:00:24 $
24 * $Revision: 1.11 $
25 * $Name: not supported by cvs2svn $
26 */
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31
32/*---------------------------------------------------------------------------
33 Includes
34 ---------------------------------------------------------------------------*/
35
36#include "detmon_ronbias.h"
37#include "detmon.h"
38
39#include "irplib_ksigma_clip.h"
40#include "irplib_hist.h"
41#include "irplib_utils.h"
42
43#include <math.h>
44#include <string.h>
45#include <assert.h>
46#include <float.h>
47
49/*--------------------------------------------------------------------------*/
50
51/*
52 * @defgroup detmon Detector monitoring functions
53 */
54
55/*--------------------------------------------------------------------------*/
56
57/*---------------------------------------------------------------------------
58 Defines
59 ---------------------------------------------------------------------------*/
60
61/* Computes the square of an euclidean distance bet. 2 points */
62#define pdist(x1,y1,x2,y2) (((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)))
63
64#define cpl_drand() ((double)rand()/(double)RAND_MAX)
65
66enum pixeltypes
67{
68 HOT = 0,
69 DEAD = 1,
70 NOISY = 2
71};
72
73enum stackingtypes
74{
75 MINMAX = 0,
76 MEAN = 1,
77 MEDIAN = 2,
78 KSIGMA = 3
79};
80
81enum readouts
82{
83 HORIZONTAL = 1,
84 VERTICAL = 2
85};
86
87
88static struct
89{
90 /* Inputs */
91 const char *method;
92 const char *pmethod;
93 irplib_ronbias_method method_bitmask;
94 int prescan_llx;
95 int prescan_lly;
96 int prescan_urx;
97 int prescan_ury;
98 int overscan_llx;
99 int overscan_lly;
100 int overscan_urx;
101 int overscan_ury;
102 cpl_size preoverscan_degree;
103 int random_nsamples;
104 int random_sizex;
105 int random_sizey;
106 int criteria;
107 int ref_llx;
108 int ref_lly;
109 int ref_urx;
110 int ref_ury;
111 const char *stacking_method;
112 int stacking_ks_low;
113 int stacking_ks_high;
114 int stacking_ks_iter;
115 int master_shift_x;
116 int master_shift_y;
117 int ron_llx;
118 int ron_lly;
119 int ron_urx;
120 int ron_ury;
121 int exts;
122 int nb_extensions;
123} detmon_ronbias_config;
124
125#define NIR TRUE
126#define OPT FALSE
127
128/*---------------------------------------------------------------------------
129 Private function prototypes
130 ---------------------------------------------------------------------------*/
131
132/* Functions for RON/Bias recipe, detmon_ronbias() */
133
134static cpl_error_code
135detmon_ronbias_retrieve_parlist(const char *,
136 const char *,
137 const cpl_parameterlist *,
138 cpl_boolean);
139
140static cpl_error_code
141detmon_ronbias_random(const cpl_imagelist *,
142 const cpl_image *, cpl_propertylist *);
143
144static cpl_error_code
145detmon_ronbias_histo(const cpl_imagelist *,
146 const cpl_image *, cpl_propertylist *);
147
148static cpl_error_code
149detmon_compute_bias_ron_and_stats_on_preoverscan(const cpl_imagelist *, /*const cpl_image *,*/
150 cpl_propertylist *, cpl_image **);
151
152static cpl_error_code
153detmon_compute_bias_stats_and_ron_in_region(const cpl_imagelist *,
154 const cpl_image *, cpl_propertylist *);
155
156static cpl_image *
157detmon_ronbias_master(const cpl_imagelist *,
158 cpl_mask **, cpl_mask **, cpl_mask **,
159 cpl_propertylist *);
160
161static cpl_error_code
162detmon_ronbias_save(const cpl_parameterlist *,
163 cpl_frameset *,
164 const char *,
165 const char *,
166 const char *,
167 const cpl_propertylist *,
168 const cpl_propertylist *,
169 const cpl_propertylist *,
170 const cpl_propertylist *,
171 const cpl_propertylist *,
172 const cpl_propertylist *,
173 const cpl_propertylist *,
174 const char *,
175 const cpl_image *,
176 const cpl_image *,
177 const cpl_mask *,
178 const cpl_mask *,
179 const cpl_mask *,
180 cpl_propertylist *,
181 const int,
182 const int,
183 cpl_frameset *,
184 int);
185
186static int
187detmon_ronbias_dfs_set_groups(cpl_frameset *, const char *);
188
189static cpl_image *
190detmon_build_synthetic_from_pre_overscan(const cpl_image * prescan,
191 const cpl_image * overscan)
192 CPL_ATTR_ALLOC;
193
194static cpl_error_code
195detmon_ronbias_dutycycl(const cpl_frameset *, cpl_propertylist *);
196
197
198
199/* The following 2 functions are duplicated from cpl_det */
200
201
202
203static cpl_bivector *
204irplib_bivector_gen_rect_poisson(const int *r,
205 const int np,
206 const int homog);
207
208/* End of duplicated code */
209
210
211cpl_error_code
212detmon_ronbias_check_defaults(const cpl_frameset *, const int whichext);
213
214
215/* RONBIAS FILLING PARLIST */
216
217
218
219/*---------------------------------------------------------------------------*/
220
221/*
222 * @brief Fill input parameters with default values
223 * @param parlist parameters list
224 * @param recipe_name recipe name
225 * @param pipeline_name pipeline name
226
227 * @return CPL_ERROR_NONE on success.
228 */
229
230/*---------------------------------------------------------------------------*/
231
232cpl_error_code
233detmon_ronbias_fill_parlist_default(cpl_parameterlist * parlist,
234 const char *recipe_name,
235 const char *pipeline_name)
236{
237 const cpl_error_code error =
238 detmon_ronbias_fill_parlist(parlist, recipe_name, pipeline_name,
239 "ALL", /* --method */
240 "NORM",/* --pmethod */
241 1, /* --preoverscan_degree */
242 -1, /* --random_nsamples */
243 -1, /* --random_sizex */
244 -1, /* --random_sizey */
245 0, /* --criteria */
246 -1, /* --ref_llx */
247 -1, /* --ref_lly */
248 -1, /* --ref_urx */
249 -1, /* --ref_ury */
250 "MEAN",/* --stacking_method */
251 3, /* --stacking_ks_low */
252 3, /* --stacking_ks_high */
253 5, /* --stacking_ks_iter */
254 0, /* --master_shift_x */
255 0, /* --master_shift_y */
256 -1, /* --ron_llx */
257 -1, /* --ron_lly */
258 -1, /* --ron_urx */
259 -1, /* --ron_ury */
260 0, /* --exts */
261 OPT);
262 cpl_ensure_code(!error, error);
263
264 return cpl_error_get_code();
265}
266
267
268
269/*---------------------------------------------------------------------------*/
270
271/*
272 * @brief Fill input parameters with default values
273 * @param parlist parameters list
274 * @param recipe_name recipe name
275 * @param pipeline_name pipeline name
276 * @param method adopted method
277 * @param pmethod adopted pre-method
278 * @param preoverscan_degree degree used ti fit pre-overscan regions
279 * @param random_nsamples number of samples used for random computation
280 * @param random_sizex x size of rectangle area for random computation
281 * @param random_sizey x size of rectangle area for random computation
282 * @param criteria
283 * @param ref_llx reference region lower left x
284 * @param ref_lly reference region lower left y
285 * @param ref_urx reference region upper right x
286 * @param ref_ury reference region upper right y
287 * @param stacking_method frame stacking method
288 * @param stacking_ks_low kappa value to kappa sigma low intensity pixels
289 * @param stacking_ks_high kappa value to kappa sigma high intensity pixels
290 * @param stacking_ks_iter kappa value to kappa sigma number of iterations
291 * @param master_shift_x x shift value applied to master
292 * @param master_shift_y y shift value applied to master
293 * @param ron_llx reference region lower left x to compute RON
294 * @param ron_lly reference region lower left y to compute RON
295 * @param ron_urx reference region upper right x to compute RON
296 * @param ron_ury reference region upper right y to compute RON
297 * @param exts image extension to be reduced
298 * @param opt_nir switch to specify if in input are OPT or NIR data
299
300 * @return CPL_ERROR_NONE on success.
301 */
302
303/*---------------------------------------------------------------------------*/
304
305cpl_error_code
306detmon_ronbias_fill_parlist(cpl_parameterlist * parlist,
307 const char *recipe_name,
308 const char *pipeline_name,
309 const char * method,
310 const char * pmethod,
311 const int preoverscan_degree,
312 const int random_nsamples,
313 const int random_sizex,
314 const int random_sizey,
315 const int criteria,
316 const int ref_llx,
317 const int ref_lly,
318 const int ref_urx,
319 const int ref_ury,
320 const char * stacking_method,
321 const int stacking_ks_low,
322 const int stacking_ks_high,
323 const int stacking_ks_iter,
324 const int master_shift_x,
325 const int master_shift_y,
326 const int ron_llx,
327 const int ron_lly,
328 const int ron_urx,
329 const int ron_ury,
330 const int exts,
331 cpl_boolean opt_nir)
332{
333
334 const char * meth_desc_opt =
335 "Method to be used when computing bias. Methods appliable: "
336 "<RANDOM | HISTO | PREOVERSCAN | REGION | ALL>. By default ALL "
337 "methods are applied. More than a method can be chosen; in that "
338 "case selected methods must be separated by a single space and put "
339 "together between inverted commas (ex. --method=\"HISTO REGION\")."
340 "\n RANDOM: Bias is computed as the mean value on a given number "
341 "(--random.nsamples) of boxes (dimensions --random.sizex and "
342 "--random.sizey) randomly taken accross the detector.\n HISTO: "
343 "An histogram of the pixels of the image is built.\n PREOVERSCAN: "
344 "Mean, median and RMS values computed and designated areas. \n "
345 "REGION: Mean, median and RMS values on reference region.";
346
347 const char * meth_desc_nir =
348 "Method to be used when computing bias. Methods appliable: "
349 "<RANDOM | HISTO | REGION | ALL>. By default ALL "
350 "methods are applied. More than a method can be chosen; in that "
351 "case selected methods must be separated by a single space and put "
352 "together between inverted commas (ex. --method=\"HISTO REGION\")."
353 "\n RANDOM: Bias is computed as the mean value on a given number "
354 "(--random.nsamples) of boxes (dimensions --random.sizex and "
355 "--random.sizey) randomly taken accross the detector.\n HISTO: "
356 "An histogram of the pixels of the image is built.\n "
357 "REGION: Mean, median and RMS values on reference region.";
358
359 const char * method_desc = opt_nir == OPT ? meth_desc_opt : meth_desc_nir;
360
361 const cpl_error_code error =
362 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 22,
363 "method",
364 method_desc,
365 "CPL_TYPE_STRING", method,
366
367 "pmethod",
368 "Pre-method for RANDOM, HISTO and REGION."
369 "Difference raw frames or not",
370 "CPL_TYPE_STRING", pmethod,
371
372 "preoverscan.degree",
373 "Degree used for pre-overscan method",
374 "CPL_TYPE_INT", preoverscan_degree,
375
376 "random.nsamples",
377 "Number of samples",
378 "CPL_TYPE_INT", random_nsamples,
379
380 "random.sizex",
381 "X size of the boxes",
382 "CPL_TYPE_INT", random_sizex,
383
384 "random.sizey",
385 "Y size of the boxes",
386 "CPL_TYPE_INT", random_sizey,
387
388 "criteria",
389 "Criteria",
390 "CPL_TYPE_INT", criteria,
391
392 "ref.llx",
393 "x coordinate of the lower-left point "
394 "of the reference region of the frame",
395 "CPL_TYPE_INT", ref_llx,
396
397 "ref.lly",
398 "y coordinate of the lower-left point "
399 "of the reference region of the frame",
400 "CPL_TYPE_INT", ref_lly,
401
402 "ref.urx",
403 "x coordinate of the upper-right point "
404 "of the reference region of the frame",
405 "CPL_TYPE_INT", ref_urx,
406
407 "ref.ury",
408 "y coordinate of the upper-right point "
409 "of the reference region of the frame",
410 "CPL_TYPE_INT", ref_ury,
411
412 "stacking.method",
413 "Method to be used when stacking the master. Posible values < MINMAX | MEAN | MEDIAN | KSIGMA >",
414 "CPL_TYPE_STRING", stacking_method,
415
416 "stacking.ks.low",
417 "Low threshold for kappa-sigma clipping",
418 "CPL_TYPE_INT", stacking_ks_low,
419
420 "stacking.ks.high",
421 "High threshold for kappa-sigma clipping",
422 "CPL_TYPE_INT", stacking_ks_high,
423
424 "stacking.ks.iter",
425 "Nb of iterations for kappa-sigma clipping",
426 "CPL_TYPE_INT", stacking_ks_iter,
427
428 "master.shift.x",
429 "Master shift X",
430 "CPL_TYPE_INT", master_shift_x,
431
432 "master.shift.y",
433 "Master shift Y",
434 "CPL_TYPE_INT", master_shift_y,
435
436 "ron.llx",
437 "x coordinate of the lower-left point "
438 "of the RON frame",
439 "CPL_TYPE_INT", ron_llx,
440
441 "ron.lly",
442 "y coordinate of the lower-left point "
443 "of the RON frame",
444 "CPL_TYPE_INT", ron_lly,
445
446 "ron.urx",
447 "x coordinate of the upper-right point "
448 "of the RON frame",
449 "CPL_TYPE_INT", ron_urx,
450
451 "ron.ury",
452 "y coordinate of the upper-right point "
453 "of the RON frame", "CPL_TYPE_INT", ron_ury,
454
455 "exts",
456 "Activate the multi-exts option",
457 "CPL_TYPE_INT", exts);
458
459
460 cpl_ensure_code(!error, error);
461
462 return cpl_error_get_code();
463}
464
465
466
467#define DETMON_MAX_PARAM 19
468
469/*---------------------------------------------------------------------------*/
470
471/*
472 * @brief Retrieve input parameters
473 * @param pipeline_name Input image
474 * @param recipe_name Input image
475 * @param parlist Shift to apply on the x-axis
476 * @param opt_nir switch to specify if in input are OPT or NIR data
477 * @return CPL_ERROR_NONE on success.
478 */
479
480/*---------------------------------------------------------------------------*/
481static cpl_error_code
482detmon_ronbias_retrieve_parlist(const char *pipeline_name,
483 const char *recipe_name,
484 const cpl_parameterlist * parlist,
485 cpl_boolean opt_nir)
486{
487 char *par_name;
488 const cpl_parameter *par;
489
490 char m1[DETMON_MAX_PARAM+1] = "";
491 char m2[DETMON_MAX_PARAM+1] = "";
492 char m3[DETMON_MAX_PARAM+1] = "";
493
494 /* --method */
495 par_name = cpl_sprintf("%s.%s.method", pipeline_name, recipe_name);
496 assert(par_name != NULL);
497 par = cpl_parameterlist_find_const(parlist, par_name);
498 detmon_ronbias_config.method = cpl_parameter_get_string(par);
499 cpl_free(par_name);
500
501 detmon_ronbias_config.method_bitmask = 0;
502
503 sscanf(detmon_ronbias_config.method,
504 "%" CPL_STRINGIFY(DETMON_MAX_PARAM) "s "
505 "%" CPL_STRINGIFY(DETMON_MAX_PARAM) "s "
506 "%" CPL_STRINGIFY(DETMON_MAX_PARAM) "s", m1, m2, m3);
507
508 if(!strcmp(m1, "RANDOM") || !strcmp(m2, "RANDOM")
509 || !strcmp(m3, "RANDOM"))
510 detmon_ronbias_config.method_bitmask += RANDOM;
511
512 if(!strcmp(m1, "HISTO") || !strcmp(m2, "HISTO") || !strcmp(m3, "HISTO"))
513 detmon_ronbias_config.method_bitmask += HISTO;
514
515 if(!strcmp(m1, "PREOVERSCAN") || !strcmp(m2, "PREOVERSCAN")
516 || !strcmp(m3, "PREOVERSCAN")) {
517 if (opt_nir == NIR) {
518 /* Just in case some advance user reads himself in the code and
519 tries to trick the interface providing an option no contained
520 in the man-page */
521 cpl_msg_warning(cpl_func, "PREOVERSCAN is not appliable for NIR");
522 } else {
523 detmon_ronbias_config.method_bitmask += PREOVERSCAN;
524 }
525 }
526 if(!strcmp(m1, "REGION") || !strcmp(m2, "REGION")
527 || !strcmp(m3, "REGION"))
528 detmon_ronbias_config.method_bitmask += REGION;
529
530 if(!strcmp(m1, "ALL")) {
531 if (opt_nir == OPT) {
532 detmon_ronbias_config.method_bitmask =
533 RANDOM | HISTO | PREOVERSCAN | REGION;
534 } else {
535 detmon_ronbias_config.method_bitmask =
536 RANDOM | HISTO | REGION;
537 }
538 }
539
540 /* --pmethod */
541 par_name = cpl_sprintf("%s.%s.pmethod", pipeline_name, recipe_name);
542 assert(par_name != NULL);
543 par = cpl_parameterlist_find_const(parlist, par_name);
544 detmon_ronbias_config.pmethod = cpl_parameter_get_string(par);
545 cpl_free(par_name);
546
547 /* --preoverscan.degree */
548 detmon_ronbias_config.preoverscan_degree =
549 detmon_retrieve_par_int("preoverscan.degree", pipeline_name,
550 recipe_name, parlist);
551
552 /* --nsamples */
553 detmon_ronbias_config.random_nsamples =
554 detmon_retrieve_par_int("random.nsamples", pipeline_name,
555 recipe_name, parlist);
556
557 /* --sizex */
558 detmon_ronbias_config.random_sizex =
559 detmon_retrieve_par_int("random.sizex", pipeline_name,
560 recipe_name, parlist);
561
562 /* --sizey */
563 detmon_ronbias_config.random_sizey =
564 detmon_retrieve_par_int("random.sizey", pipeline_name,
565 recipe_name, parlist);
566
567 /* --criteria */
568 detmon_ronbias_config.criteria =
569 detmon_retrieve_par_int("criteria", pipeline_name, recipe_name,
570 parlist);
571
572 /* --ref.llx */
573 detmon_ronbias_config.ref_llx =
574 detmon_retrieve_par_int("ref.llx", pipeline_name, recipe_name,
575 parlist);
576 /* --ref.lly */
577 detmon_ronbias_config.ref_lly =
578 detmon_retrieve_par_int("ref.lly", pipeline_name, recipe_name,
579 parlist);
580 /* --ref.urx */
581 detmon_ronbias_config.ref_urx =
582 detmon_retrieve_par_int("ref.urx", pipeline_name, recipe_name,
583 parlist);
584 /* --ref.ury */
585 detmon_ronbias_config.ref_ury =
586 detmon_retrieve_par_int("ref.ury", pipeline_name, recipe_name,
587 parlist);
588
589 /* --stacking.method */
590 par_name =
591 cpl_sprintf("%s.%s.stacking.method", pipeline_name, recipe_name);
592 assert(par_name != NULL);
593 par = cpl_parameterlist_find_const(parlist, par_name);
594 detmon_ronbias_config.stacking_method = cpl_parameter_get_string(par);
595 cpl_free(par_name);
596
597 /* --stacking.ks.low */
598 detmon_ronbias_config.stacking_ks_low =
599 detmon_retrieve_par_int("stacking.ks.low", pipeline_name,
600 recipe_name, parlist);
601 /* --stacking.ks.high */
602 detmon_ronbias_config.stacking_ks_high =
603 detmon_retrieve_par_int("stacking.ks.high", pipeline_name,
604 recipe_name, parlist);
605 /* --stacking.ks.iter */
606 detmon_ronbias_config.stacking_ks_iter =
607 detmon_retrieve_par_int("stacking.ks.iter", pipeline_name,
608 recipe_name, parlist);
609 /* --master.shift.x */
610 detmon_ronbias_config.master_shift_x =
611 detmon_retrieve_par_int("master.shift.x", pipeline_name,
612 recipe_name, parlist);
613 /* --master.shift.y */
614 detmon_ronbias_config.master_shift_y =
615 detmon_retrieve_par_int("master.shift.y", pipeline_name,
616 recipe_name, parlist);
617 /* --ron.llx */
618 detmon_ronbias_config.ron_llx =
619 detmon_retrieve_par_int("ron.llx", pipeline_name, recipe_name,
620 parlist);
621 /* --ron.lly */
622 detmon_ronbias_config.ron_lly =
623 detmon_retrieve_par_int("ron.lly", pipeline_name, recipe_name,
624 parlist);
625 /* --ron.urx */
626 detmon_ronbias_config.ron_urx =
627 detmon_retrieve_par_int("ron.urx", pipeline_name, recipe_name,
628 parlist);
629 /* --ron.ury */
630 detmon_ronbias_config.ron_ury =
631 detmon_retrieve_par_int("ron.ury", pipeline_name, recipe_name,
632 parlist);
633 /* --exts */
634 detmon_ronbias_config.exts =
635 detmon_retrieve_par_int("exts", pipeline_name, recipe_name,
636 parlist);
637
638 if(cpl_error_get_code()) {
639 cpl_msg_error(cpl_func, "Failed to retrieve the input parameters");
640 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
641 }
642
643
644 return CPL_ERROR_NONE;
645}
646
647/*---------------------------------------------------------------------------*/
648
649/*
650 * @brief Check parameter defaults
651 * @param set Input set of frames
652 * @param whichext extension to be reduced
653 * @return CPL_ERROR_NONE on success.
654 */
655
656/*---------------------------------------------------------------------------*/
657cpl_error_code
658detmon_ronbias_check_defaults(const cpl_frameset * set,
659 const int whichext)
660{
661 const cpl_frame * fr = cpl_frameset_get_position_const(set, 0);
662
663 cpl_propertylist * plist =
664 cpl_propertylist_load(cpl_frame_get_filename(fr), whichext);
665
666 const int naxis1 = cpl_propertylist_get_int(plist, "NAXIS1");
667 const int naxis2 = cpl_propertylist_get_int(plist, "NAXIS2");
668
669 if(detmon_ronbias_config.method_bitmask & PREOVERSCAN)
670 {
671 const int nx = cpl_propertylist_get_int(plist, "ESO DET OUT1 NX");
672 const int ny = cpl_propertylist_get_int(plist, "ESO DET OUT1 NY");
673
674 int prscsize;
675 int ovscsize;
676
677 if (naxis1 != nx)
678 {
679 prscsize =
680 cpl_propertylist_get_int(plist, "ESO DET OUT1 PRSCX");
681 ovscsize =
682 cpl_propertylist_get_int(plist, "ESO DET OUT1 OVSCX");
683
684 cpl_error_ensure(cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(), goto cleanup,"error");
685
686 detmon_ronbias_config.prescan_llx = 1;
687 detmon_ronbias_config.prescan_lly = 1;
688 detmon_ronbias_config.prescan_urx = prscsize;
689 detmon_ronbias_config.prescan_ury = naxis2;
690 detmon_ronbias_config.overscan_llx = naxis1 - ovscsize;
691 detmon_ronbias_config.overscan_lly = 1;
692 detmon_ronbias_config.overscan_urx = naxis1;
693 detmon_ronbias_config.overscan_ury = naxis2;
694 } else if (naxis2 != ny)
695 {
696 prscsize =
697 cpl_propertylist_get_int(plist, "ESO DET OUT1 PRSCY");
698 ovscsize =
699 cpl_propertylist_get_int(plist, "ESO DET OUT1 OVSCY");
700 cpl_error_ensure(cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(), goto cleanup,"error");
701
702 detmon_ronbias_config.prescan_llx = 1;
703 detmon_ronbias_config.prescan_lly = 1;
704 detmon_ronbias_config.prescan_urx = naxis1;
705 detmon_ronbias_config.prescan_ury = prscsize;
706 detmon_ronbias_config.overscan_llx = 1;
707 detmon_ronbias_config.overscan_lly = naxis2 - ovscsize;
708 detmon_ronbias_config.overscan_urx = naxis1;
709 detmon_ronbias_config.overscan_ury = naxis2;
710 } else
711 {
712 cpl_msg_error(cpl_func,
713 "No PREOVERSCAN areas found");
714 cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT);
715 goto cleanup;
716 }
717 }
718
719 if(detmon_ronbias_config.ref_llx == -1)
720 detmon_ronbias_config.ref_llx = naxis1 / 8;
721 if(detmon_ronbias_config.ref_lly == -1)
722 detmon_ronbias_config.ref_lly = naxis2 / 8;
723 if(detmon_ronbias_config.ref_urx == -1)
724 detmon_ronbias_config.ref_urx = naxis1 * 7 / 8;
725 if(detmon_ronbias_config.ref_ury == -1)
726 detmon_ronbias_config.ref_ury = naxis2 * 7 / 8;
727
728 if(detmon_ronbias_config.ron_llx == -1)
729 detmon_ronbias_config.ron_llx = 1;
730 if(detmon_ronbias_config.ron_lly == -1)
731 detmon_ronbias_config.ron_lly = 1;
732 if(detmon_ronbias_config.ron_urx == -1)
733 detmon_ronbias_config.ron_urx = naxis1;
734 if(detmon_ronbias_config.ron_ury == -1)
735 detmon_ronbias_config.ron_ury = naxis2;
736
737cleanup:
738 cpl_propertylist_delete(plist);
739 return cpl_error_get_code();
740}
741
742
743/*---------------------------------------------------------------------------*/
744
745/*
746 * @brief save a ronbias results on a FITS file
747 * @param parlist input parameters
748 * @param tag input frame tag
749 * @param recipe_name input recipe name
750 * @param pipeline_name input pipeline id
751 * @param pafregexp regular expression to remove from FITS header
752 *
753 * @param pro_master pro catg master frame
754 * @param pro_xstr pro catg xstructure
755 * @param pro_ystr pro catg ystructure
756 * @param pro_synth pro catg synthetic frame
757 * @param pro_bpmhot pro catg hot pix BPM
758 * @param pro_pmpcold pro catg cold pix BPM
759 * @param pro_ppmdev pro catg deviant pix BPM
760 *
761 * @param package package name
762 * @param compare function used for comparison
763 * @param opt_nir switch to specify if in input are OPT or NIR data
764
765 * @return CPL_ERROR_NONE on success.
766 */
767
768/*---------------------------------------------------------------------------*/
769cpl_error_code
770detmon_ronbias(cpl_frameset * frameset,
771 const cpl_parameterlist * parlist,
772 const char *tag,
773 const char *recipe_name,
774 const char *pipeline_name,
775 const char *pafregexp,
776 const cpl_propertylist * pro_master,
777 const cpl_propertylist * pro_xstr, /* Unsupported*/
778 const cpl_propertylist * pro_ystr, /* Unsupported*/
779 const cpl_propertylist * pro_synth,
780 const cpl_propertylist * pro_bpmhot,
781 const cpl_propertylist * pro_bpmcold,
782 const cpl_propertylist * pro_bpmdev,
783 const char *package,
784 int (*compare) (const cpl_frame *, const cpl_frame *),
785 cpl_boolean opt_nir)
786{
787
788 cpl_size nsets;
789 int i;
790
791 cpl_size * selection = NULL;
792 cpl_frameset * cur_fset = NULL;
793 cpl_propertylist * qclist = NULL;
794 cpl_image * synthetic = NULL;
795 cpl_image * masterbias = NULL;
796 cpl_imagelist * rawbiases = NULL;
797 cpl_mask * bpmhot = NULL;
798 cpl_mask * bpmcold = NULL;
799 cpl_mask * bpmdev = NULL;
800
801 /* Test entries */
802 cpl_ensure_code(frameset != NULL, CPL_ERROR_NULL_INPUT);
803 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
804 cpl_ensure_code(tag != NULL, CPL_ERROR_NULL_INPUT);
805 cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
806 cpl_ensure_code(pipeline_name != NULL, CPL_ERROR_NULL_INPUT);
807 cpl_ensure_code(pro_master != NULL, CPL_ERROR_NULL_INPUT);
808 cpl_ensure_code(pro_bpmhot != NULL, CPL_ERROR_NULL_INPUT);
809 cpl_ensure_code(pro_bpmcold != NULL, CPL_ERROR_NULL_INPUT);
810 cpl_ensure_code(pro_bpmdev != NULL, CPL_ERROR_NULL_INPUT);
811 cpl_ensure_code(package != NULL, CPL_ERROR_NULL_INPUT);
812
813 if(detmon_ronbias_dfs_set_groups(frameset, tag)) {
814 cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames");
815 }
816
817 /*
818 * First of all test the entries.
819 * See if the selected method(s) is/are appliable.
820 * See if necessary parameters for those selected have been provided.
821 */
822
823 /* clreturn_if(detmon_ronbias_test_entries());
824 */
825 /*
826 * This function reads all inputs parameters from parlist
827 * and stores them in a global variable detmon_ronbias_config.
828 * Similar to detmon_lg_retrieve_parlist(). See detmon.c
829 */
830 detmon_ronbias_retrieve_parlist(pipeline_name,
831 recipe_name, parlist, opt_nir);
832
833 /* Extra input check for PREOVERSCAN */
834 if(detmon_ronbias_config.method_bitmask & PREOVERSCAN)
835 cpl_ensure_code(pro_synth != NULL, CPL_ERROR_NULL_INPUT);
836
837
838 /* Labelise all input frames */
839 if(compare == NULL)
840 nsets = 1;
841 else {
842 cpl_msg_info(cpl_func, "Identify the different settings");
843 selection = cpl_frameset_labelise(frameset, compare, &nsets);
844 if(selection == NULL)
845 cpl_msg_error(cpl_func, "Cannot labelise input frames");
846 }
847
848 /* Extract settings and reduce each of them */
849 for(i = 0; i < nsets; i++) {
850 int j;
851 int first_ext = 0;
852 int last_ext = 1;
853
854 detmon_ronbias_config.nb_extensions = 1;
855
856 /* Reduce data set nb i */
857 cpl_msg_info(cpl_func, "Reduce data set nb %d out of %" CPL_SIZE_FORMAT "",
858 i + 1, nsets);
859
860 cur_fset = nsets == 1 ?
861 cpl_frameset_duplicate(frameset) :
862 cpl_frameset_extract(frameset, selection, i);
863 skip_if(cur_fset == NULL);
864
865 if(detmon_ronbias_config.exts > 0) {
866 first_ext = detmon_ronbias_config.exts;
867 last_ext = first_ext + 1;
868 } else if(detmon_ronbias_config.exts < 0) {
869 const cpl_frame *cur_frame =
870 cpl_frameset_get_position_const(cur_fset, 0);
871 /* Get the nb of extensions */
872 detmon_ronbias_config.nb_extensions =
873 cpl_frame_get_nextensions(cur_frame);
874 first_ext = 1;
875 last_ext = detmon_ronbias_config.nb_extensions + 1;
876 }
877
878 if (last_ext - first_ext > 1) {
879 skip_if(detmon_ronbias_save(parlist, frameset,
880 recipe_name,
881 pipeline_name, pafregexp,
882 pro_master, pro_xstr,
883 pro_ystr, pro_synth,
884 pro_bpmhot,
885 pro_bpmcold, pro_bpmdev,
886 package, NULL, NULL, NULL,
887 NULL, NULL, NULL,
888 0, 0, cur_fset, 0));
889 }
890
891 for(j = first_ext; j < last_ext; j++) {
892 int whichext;
893
894 qclist = cpl_propertylist_new();
895
896 rawbiases
897 = cpl_imagelist_load_frameset(cur_fset,
898 CPL_TYPE_FLOAT, 1, j);
899 skip_if(rawbiases == NULL);
900
901 skip_if(detmon_ronbias_check_defaults(cur_fset, j));
902
903 skip_if(detmon_ronbias_dutycycl(cur_fset, qclist));
904
905 masterbias = detmon_ronbias_master(rawbiases,
906 &bpmhot, &bpmcold,
907 &bpmdev, qclist);
908 skip_if(masterbias == NULL);
909
910 /*
911 * Following, a function corresponding each of the
912 * possible methods is to be found.
913 */
914
915 if(detmon_ronbias_config.method_bitmask & RANDOM) {
916 skip_if(detmon_ronbias_random(rawbiases, masterbias,
917 qclist));
918 }
919
920 if(detmon_ronbias_config.method_bitmask & HISTO) {
921 skip_if(detmon_ronbias_histo(rawbiases, masterbias,
922 qclist));
923 }
924
925 if(detmon_ronbias_config.method_bitmask & PREOVERSCAN) {
926 skip_if(detmon_compute_bias_ron_and_stats_on_preoverscan(rawbiases,
927 /*masterbias,*/
928 qclist, &synthetic));
929 }
930
931 if(detmon_ronbias_config.method_bitmask & REGION) {
932 skip_if(detmon_compute_bias_stats_and_ron_in_region(rawbiases,
933 masterbias,qclist));
934 }
935
936 /*
937 * This function takes the QC list where all the results of the
938 * methods applied are stored, and compares them.
939 * No action defined yet if comparison reveals important differences.
940 */
941#if 0
942 detmon_ronbias_check(qclist);
943#endif
944
945 /* Definition of the extension of the output where to save
946 the products. If input are multiextension but only
947 computation on a single extension is required, it is 0 */
948 whichext = first_ext > 1 ? 0 : j;
949
950 skip_if(detmon_ronbias_save(parlist, frameset,
951 recipe_name,
952 pipeline_name, pafregexp,
953 pro_master, pro_xstr,
954 pro_ystr, pro_synth,
955 pro_bpmhot,
956 pro_bpmcold, pro_bpmdev,
957 package, masterbias, synthetic,
958 bpmhot, bpmcold, bpmdev,
959 qclist, 0, 0, cur_fset,
960 whichext));
961
962 cpl_image_delete(synthetic);
963 cpl_image_delete(masterbias);
964 cpl_mask_delete(bpmhot);
965 cpl_mask_delete(bpmcold);
966 cpl_mask_delete(bpmdev);
967 cpl_imagelist_delete(rawbiases);
968 cpl_propertylist_delete(qclist);
969
970 qclist = NULL;
971 rawbiases = NULL;
972 masterbias = NULL;
973 bpmhot = NULL;
974 bpmcold = NULL;
975 bpmdev = NULL;
976 synthetic = NULL;
977 } /* for each extension */
978
979 cpl_frameset_delete(cur_fset);
980 cur_fset = NULL;
981
982 } /* for each setting */
983
984 end_skip;
985
986 cpl_free(selection);
987
988 cpl_frameset_delete(cur_fset);
989
990 cpl_image_delete(synthetic);
991 cpl_image_delete(masterbias);
992 cpl_mask_delete(bpmhot);
993 cpl_mask_delete(bpmcold);
994 cpl_mask_delete(bpmdev);
995 cpl_imagelist_delete(rawbiases);
996 cpl_propertylist_delete(qclist);
997
998 return cpl_error_get_code();
999}
1000
1001/*---------------------------------------------------------------------------*/
1002/*
1003 * @brief Computes bias RON using random sampling method
1004 * @param rawbiases input image list
1005 * @param masterbias input master bias
1006 * @param qclist input/output propertylist with QC parameters
1007 * @return CPL_ERROR_NONE on success.
1008
1009 */
1010/*---------------------------------------------------------------------------*/
1011static cpl_error_code
1012detmon_ronbias_random(const cpl_imagelist * rawbiases,
1013 const cpl_image * masterbias,
1014 cpl_propertylist * qclist)
1015{
1016 int nraws = cpl_imagelist_get_size(rawbiases);
1017 int i;
1018 double bias = DBL_MAX; /* Avoid (false) uninit warning */
1019 double bias_error;
1020
1021 double ron_error;
1022 double *ron =
1023 (double *) cpl_malloc(sizeof(double) * nraws);
1024
1025 cpl_vector *v;
1026 double stdev = 0;
1027 cpl_error_code error = CPL_ERROR_NONE;
1028
1029 /* As we are applying to diff frames instead of raw frames,
1030 there is one less to compute on */
1031 if(!strcmp(detmon_ronbias_config.pmethod, "DIF"))
1032 {
1033 nraws--;
1034 /* As we are applying to diff frames instead of raw frames,
1035 there is one less to compute on */
1036 for(i = 0; i < nraws; i++)
1037 {
1038 const cpl_image *c1_raw =
1039 cpl_imagelist_get_const(rawbiases, i);
1040 const cpl_image *c2_raw =
1041 cpl_imagelist_get_const(rawbiases, i + 1);
1042 /*FIXME: See if const modifier is necessary */
1043 const cpl_image *c_raw = cpl_image_subtract_create(c1_raw,
1044 c2_raw);
1045 error = cpl_flux_get_noise_window(c_raw, NULL,
1046 detmon_ronbias_config.random_sizex / 2,
1047 detmon_ronbias_config.random_nsamples,
1048 ron + i, &ron_error);
1049 cpl_image_delete((cpl_image*)c_raw);
1050 if (error != CPL_ERROR_NONE)
1051 {
1052 break;
1053 }
1054 }
1055 } else
1056 {
1057 for(i = 0; i < nraws; i++)
1058 {
1059 const cpl_image *c_raw = cpl_imagelist_get_const(rawbiases, i);
1060 skip_if(cpl_flux_get_noise_window(c_raw, NULL,
1061 detmon_ronbias_config.random_sizex / 2,
1062 detmon_ronbias_config.random_nsamples,
1063 ron + i, &ron_error));
1064 }
1065 }
1066
1067 /*FIXME: Calls to noise_window could be out from if() and
1068 coded only once */
1069 if (error == CPL_ERROR_NONE)
1070 {
1071 irplib_flux_get_bias_window(masterbias, NULL,
1072 detmon_ronbias_config.random_sizex / 2,
1073 detmon_ronbias_config.random_nsamples,
1074 &bias, &bias_error);
1075
1076 v = cpl_vector_wrap(nraws, ron);
1077 stdev = cpl_vector_get_median_const(v);
1078 cpl_vector_unwrap(v);
1079
1080
1081 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_RANDOM_VAL, bias));
1082 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_RANDOM_VAL,
1083 DETMON_QC_BIAS_RANDOM_VAL_C));
1084
1085 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_RANDOM_RON, stdev));
1086 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_RANDOM_RON,
1087 DETMON_QC_BIAS_RANDOM_RON_C));
1088 }
1089
1090 irplib_flux_get_bias_window(masterbias, NULL,
1091 detmon_ronbias_config.random_sizex / 2,
1092 detmon_ronbias_config.random_nsamples,
1093 &bias, &bias_error);
1094
1095 v = cpl_vector_wrap(nraws, ron);
1096 if (v)
1097 {
1098 stdev = cpl_vector_get_median_const(v);
1099 cpl_vector_unwrap(v);
1100 }
1101
1102 error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_RANDOM_VAL, bias);
1103 error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_RANDOM_VAL,
1104 DETMON_QC_BIAS_RANDOM_VAL_C);
1105
1106
1107 error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_RANDOM_RON, stdev);
1108 error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_RANDOM_RON,
1109 DETMON_QC_BIAS_RANDOM_RON_C);
1110
1111 end_skip;
1112 if (ron)
1113 cpl_free(ron);
1114 return cpl_error_get_code();
1115}
1116/*
1117 * @brief Computes bias RON using histogram method
1118 * @param rawbiases input image list
1119 * @param masterbias input master bias
1120 * @param qclist input/output propertylist with QC parameters
1121 * @return CPL_ERROR_NONE on success.
1122
1123 */
1124static cpl_error_code
1125detmon_ronbias_histo(const cpl_imagelist * rawbiases,
1126 const cpl_image * masterbias,
1127 cpl_propertylist * qclist)
1128{
1129 int nraws = cpl_imagelist_get_size(rawbiases);
1130 int i;
1131
1132 double mbias = DBL_MAX;
1133 double mfwhm = DBL_MAX;
1134 double mmax = DBL_MAX;
1135
1136 cpl_vector * fwhms;
1137 cpl_vector * maxs;
1138
1139 double mean_fwhm = DBL_MAX;
1140
1141 if(!strcmp(detmon_ronbias_config.pmethod, "DIF")) nraws--;
1142
1143 fwhms = cpl_vector_new(nraws);
1144 maxs = cpl_vector_new(nraws);
1145
1146 for(i = 0; i < nraws; i++) {
1147 /*FIXME: See if it is necessary to have const */
1148 const cpl_image * c_raw;
1149 double bias = DBL_MAX;
1150 double fwhm = DBL_MAX;
1151 double max = DBL_MAX;
1152
1153 if(strcmp(detmon_ronbias_config.pmethod, "DIF")) {
1154 c_raw = cpl_imagelist_get_const(rawbiases, i);
1155 } else {
1156 const cpl_image *c1_raw = cpl_imagelist_get_const(rawbiases, i);
1157 const cpl_image * c2_raw = cpl_imagelist_get_const(rawbiases, i+1);
1158 c_raw = cpl_image_subtract_create(c1_raw, c2_raw);
1159 }
1160
1161 skip_if(detmon_ronbias_histo_reduce(c_raw, &bias, &fwhm, &max));
1162
1163 skip_if(bias == DBL_MAX || fwhm == DBL_MAX || max == DBL_MAX);
1164
1165 if(!strcmp(detmon_ronbias_config.pmethod, "DIF"))
1166 cpl_image_delete((cpl_image *)c_raw);
1167
1168 skip_if(cpl_vector_set(maxs, i, max));
1169 skip_if(cpl_vector_set(fwhms, i, fwhm));
1170
1171 /* FIXME: Add properly a hist-saving in debug-mode */
1172 }
1173
1174 skip_if(cpl_vector_divide_scalar(fwhms, CPL_MATH_FWHM_SIG));
1175
1176 detmon_ronbias_histo_reduce(masterbias, &mbias, &mfwhm, &mmax);
1177
1178 skip_if(mbias == DBL_MAX || mfwhm == DBL_MAX || mmax == DBL_MAX);
1179
1180 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_HISTO_VAL,
1181 mbias));
1182 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_HISTO_VAL,
1183 DETMON_QC_BIAS_HISTO_VAL_C));
1184 mean_fwhm = cpl_vector_get_mean(fwhms);
1185
1186 skip_if(mean_fwhm == DBL_MAX);
1187 skip_if(cpl_error_get_code());
1188
1189 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_HISTO_RON,
1190 mean_fwhm));
1191 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_HISTO_RON,
1192 DETMON_QC_BIAS_HISTO_RON_C));
1193
1194 end_skip;
1195
1196 cpl_vector_delete(fwhms);
1197 cpl_vector_delete(maxs);
1198
1199 return cpl_error_get_code();
1200}
1201
1202/*---------------------------------------------------------------------------*/
1203
1204/*
1205 * @brief Computes histogram on input image and get bias, fwhm and max
1206 * @param c_raw Input image
1207 * @param bias output bias of histogram
1208 * @param fwhm output fwhm of histogram
1209 * @param max output max of histogram
1210 * @return CPL_ERROR_NONE on success.
1211
1212 */
1213
1214/*---------------------------------------------------------------------------*/
1215cpl_error_code
1216detmon_ronbias_histo_reduce(const cpl_image * c_raw,
1217 double * bias,
1218 double * fwhm,
1219 double * max)
1220{
1221 unsigned long uj;
1222 irplib_hist *hist;
1223 unsigned long maxwhere = 0;
1224
1225 cpl_image * dupi;
1226 unsigned long x1a = 1;
1227 unsigned long x2a = 1;
1228
1229 double x1 = 0;
1230 double x2 = 0;
1231
1232 double maxwhere_interp;
1233 double max_interp;
1234 double a, b, c;
1235 cpl_matrix * coeffs =cpl_matrix_new(3, 3);
1236 cpl_matrix * rhs =cpl_matrix_new(3, 1);
1237 int p, q;
1238 cpl_matrix * result = NULL;
1239
1240 dupi = cpl_image_duplicate(c_raw);
1241
1242 /* FIXME: Still to decide if it is necessary to remove bad pixels
1243 in advance or not*/
1244
1245 hist = irplib_hist_new();
1246 irplib_hist_fill(hist, dupi);
1247
1248 cpl_image_delete(dupi);
1249
1250 irplib_hist_get_max(hist, &maxwhere);
1251
1252 for( p = 0; p< 3; p++){
1253 unsigned long bi = irplib_hist_get_value(hist, maxwhere-1+p);
1254 cpl_matrix_set(rhs, p, 0, bi);
1255 for( q= 0; q< 3; q++) {
1256 cpl_matrix_set(coeffs, p,q,pow((maxwhere-1+p),q));
1257 }
1258 }
1259
1260 result = cpl_matrix_solve(coeffs, rhs);
1261
1262 a = cpl_matrix_get(result, 2, 0);
1263 b = cpl_matrix_get(result, 1, 0);
1264 c = cpl_matrix_get(result, 0, 0);
1265
1266 maxwhere_interp = -0.5 * b / (2 * a);
1267 max_interp = -1 * b * b / (4 * a) + c;
1268
1269 cpl_matrix_delete(coeffs);
1270 cpl_matrix_delete(rhs);
1271 cpl_matrix_delete(result);
1272
1273 /* Look for the points of half-maximum */
1274 for(uj = 0; uj < maxwhere; uj++) {
1275 if(irplib_hist_get_value(hist, uj) <= max_interp / 2 &&
1276 irplib_hist_get_value(hist, uj + 1) > max_interp / 2) {
1277 x1a = uj;
1278 }
1279 }
1280 for(uj = maxwhere; uj < irplib_hist_get_nbins(hist)-1; uj++) {
1281 if(irplib_hist_get_value(hist, uj) >= max_interp / 2 &&
1282 irplib_hist_get_value(hist, uj + 1) < max_interp / 2) {
1283 x2a = uj;
1284 }
1285 }
1286
1287 x1 = (max_interp / 2 - irplib_hist_get_value(hist, x1a)) /
1288 (irplib_hist_get_value(hist, x1a + 1) -
1289 irplib_hist_get_value(hist, x1a)) + x1a;
1290 x2 = (max_interp / 2 - irplib_hist_get_value(hist, x2a)) /
1291 (irplib_hist_get_value(hist, x2a + 1) -
1292 irplib_hist_get_value(hist, x2a)) + x2a;
1293
1294 *fwhm = (x2 - x1) * irplib_hist_get_bin_size(hist);
1295
1296 *max = max_interp;
1297
1298 *bias = maxwhere_interp * irplib_hist_get_bin_size(hist) +
1299 irplib_hist_get_start(hist);
1300
1301 irplib_hist_delete(hist);
1302
1303 return cpl_error_get_code();
1304}
1305/*---------------------------------------------------------------------------*/
1306
1307/*
1308 * @brief Computes RON and statistics on pre/overscan bias regions
1309 * @param rawbiases Input image list
1310 * @param qclist input/output propertylist with QC parameters
1311 * @param synthetic input synthetic image
1312 * @return CPL_ERROR_NONE on success.
1313
1314 */
1315
1316/*---------------------------------------------------------------------------*/
1317static cpl_error_code
1318detmon_compute_bias_ron_and_stats_on_preoverscan(const cpl_imagelist * rawbiases,
1319 cpl_propertylist * qclist,
1320 cpl_image ** synthetic)
1321{
1322 int i;
1323 int nx, ny;
1324 int nraws;
1325
1326 cpl_vector *meanspre;
1327 cpl_vector *medspre;
1328 cpl_vector *rmsspre;
1329 cpl_vector *meansover;
1330 cpl_vector *medsover;
1331 cpl_vector *rmssover;
1332
1333 cpl_error_code error;
1334
1335 nraws = cpl_imagelist_get_size(rawbiases);
1336 cpl_ensure_code(nraws != -1, CPL_ERROR_ILLEGAL_INPUT);
1337
1338 nx = cpl_image_get_size_x(cpl_imagelist_get_const(rawbiases, 0));
1339 ny = cpl_image_get_size_y(cpl_imagelist_get_const(rawbiases, 0));
1340 cpl_ensure_code(nx != -1 && ny != -1, CPL_ERROR_ILLEGAL_INPUT);
1341
1342 if(nx < detmon_ronbias_config.prescan_urx ||
1343 nx < detmon_ronbias_config.overscan_urx ||
1344 ny < detmon_ronbias_config.prescan_ury ||
1345 ny < detmon_ronbias_config.overscan_ury) {
1346 cpl_msg_warning(cpl_func, "PREOVERSCAN method not applied. Given "
1347 "limits of prescan and overscan area "
1348 "exceed image size. Please check and rerun.");
1349 return CPL_ERROR_NONE;
1350 }
1351
1352 meanspre = cpl_vector_new(nraws);
1353 medspre = cpl_vector_new(nraws);
1354 rmsspre = cpl_vector_new(nraws);
1355 meansover = cpl_vector_new(nraws);
1356 medsover = cpl_vector_new(nraws);
1357 rmssover = cpl_vector_new(nraws);
1358
1359 for(i = 0; i < nraws; i++) {
1360 double mean = 0;
1361 double stdev = 0;
1362 double median_prescan, median_overscan;
1363
1364 cpl_image *prescan = NULL;
1365 cpl_image *overscan = NULL;
1366
1367 const cpl_image *c_raw = cpl_imagelist_get_const(rawbiases, i);
1368
1369 cpl_ensure_code(c_raw != NULL, CPL_ERROR_ILLEGAL_INPUT);
1370
1371 prescan =
1372 cpl_image_extract(c_raw,
1373 detmon_ronbias_config.prescan_llx,
1374 detmon_ronbias_config.prescan_lly,
1375 detmon_ronbias_config.prescan_urx,
1376 detmon_ronbias_config.prescan_ury);
1377 cpl_ensure_code(prescan != NULL, CPL_ERROR_ILLEGAL_INPUT);
1378 overscan =
1379 cpl_image_extract(c_raw,
1380 detmon_ronbias_config.overscan_llx,
1381 detmon_ronbias_config.overscan_lly,
1382 detmon_ronbias_config.overscan_urx,
1383 detmon_ronbias_config.overscan_ury);
1384 cpl_ensure_code(overscan != NULL, CPL_ERROR_ILLEGAL_INPUT);
1385
1386 if(i == 0) {
1387 *synthetic = detmon_build_synthetic_from_pre_overscan(prescan,
1388 overscan);
1389 cpl_msg_info(cpl_func, "Creating SYNTHETIC frame");
1390 if(*synthetic == NULL) {
1391 cpl_msg_error(cpl_func, "Error creating SYNTHETIC frame");
1392 return CPL_ERROR_UNSPECIFIED;
1393 }
1394 }
1395
1396 median_prescan = cpl_image_get_median(prescan);
1397 median_overscan = cpl_image_get_median(overscan);
1398 cpl_image_delete(prescan);
1399 cpl_image_delete(overscan);
1400
1401 error = irplib_ksigma_clip(c_raw,
1402 detmon_ronbias_config.
1403 prescan_llx,
1404 detmon_ronbias_config.
1405 prescan_lly,
1406 detmon_ronbias_config.
1407 prescan_urx,
1408 detmon_ronbias_config.
1409 prescan_ury,
1410 (double) detmon_ronbias_config.
1411 stacking_ks_low,
1412 detmon_ronbias_config.
1413 stacking_ks_iter, 1e-5,
1414 &mean, &stdev);
1415 cpl_ensure_code(!error, error);
1416
1417 cpl_ensure_code(mean != 0 && stdev != 0, CPL_ERROR_UNSPECIFIED);
1418
1419 error = cpl_vector_set(medspre, i, median_prescan);
1420 cpl_ensure_code(!error, error);
1421
1422 error = cpl_vector_set(meanspre, i, mean);
1423 cpl_ensure_code(!error, error);
1424 error = cpl_vector_set(rmsspre, i, stdev);
1425 cpl_ensure_code(!error, error);
1426 error = irplib_ksigma_clip(c_raw,
1427 detmon_ronbias_config.
1428 overscan_llx,
1429 detmon_ronbias_config.
1430 overscan_lly,
1431 detmon_ronbias_config.
1432 overscan_urx,
1433 detmon_ronbias_config.
1434 overscan_ury,
1435 (double) detmon_ronbias_config.
1436 stacking_ks_low,
1437 detmon_ronbias_config.
1438 stacking_ks_iter, 1e-5,
1439 &mean, &stdev);
1440 cpl_ensure_code(!error, error);
1441
1442 cpl_ensure_code(mean != 0 && stdev != 0, CPL_ERROR_UNSPECIFIED);
1443
1444 error = cpl_vector_set(medsover, i, median_overscan);
1445 cpl_ensure_code(!error, error);
1446
1447 error = cpl_vector_set(meansover, i, mean);
1448 cpl_ensure_code(!error, error);
1449 error = cpl_vector_set(rmssover, i, stdev);
1450 cpl_ensure_code(!error, error);
1451
1452 }
1453
1454 error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_PRESCAN_MEAN,
1455 cpl_vector_get_mean(meanspre));
1456
1457 error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_PRESCAN_MEAN,
1458 DETMON_QC_BIAS_PRESCAN_MEAN_C);
1459
1460 cpl_ensure_code(!error, error);
1461 error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_PRESCAN_MED,
1462 cpl_vector_get_mean(medspre));
1463 error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_PRESCAN_MED,
1464 DETMON_QC_BIAS_PRESCAN_MED_C);
1465
1466 cpl_ensure_code(!error, error);
1467 error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_PRESCAN_RON,
1468 cpl_vector_get_mean(rmsspre));
1469
1470 error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_PRESCAN_RON,
1471 DETMON_QC_BIAS_PRESCAN_RON_C);
1472 cpl_ensure_code(!error, error);
1473
1474 error =
1475 cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_OVERSCAN_MEAN,
1476 cpl_vector_get_mean(meansover));
1477 error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_OVERSCAN_MEAN,
1478 DETMON_QC_BIAS_OVERSCAN_MEAN_C);
1479 cpl_ensure_code(!error, error);
1480 error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_OVERSCAN_MED,
1481 cpl_vector_get_mean(medsover));
1482 error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_OVERSCAN_MED,
1483 DETMON_QC_BIAS_OVERSCAN_MED_C);
1484 cpl_ensure_code(!error, error);
1485 error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_OVERSCAN_RON,
1486 cpl_vector_get_mean(rmssover));
1487 error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_OVERSCAN_RON,
1488 DETMON_QC_BIAS_OVERSCAN_RON_C);
1489 cpl_ensure_code(!error, error);
1490
1491 /* The following seems not to be necessary.
1492 Pending of revision to be removed */
1493 /*
1494 error =
1495 cpl_propertylist_append_double(qclist,
1496 "ESO QC BIAS PRESCAN MEAN STDEV",
1497 cpl_vector_get_stdev(meanspre));
1498 cpl_ensure_code(!error, error);
1499 error =
1500 cpl_propertylist_append_double(qclist,
1501 "ESO QC BIAS PRESCAN MED STDEV",
1502 cpl_vector_get_stdev(medspre));
1503 cpl_ensure_code(!error, error);
1504 error =
1505 cpl_propertylist_append_double(qclist,
1506 "ESO QC BIAS PRESCAN RMS STDEV",
1507 cpl_vector_get_stdev(rmsspre));
1508 cpl_ensure_code(!error, error);
1509
1510 error =
1511 cpl_propertylist_append_double(qclist,
1512 "ESO QC BIAS OVERSCAN MEAN STDEV",
1513 cpl_vector_get_stdev(meansover));
1514 cpl_ensure_code(!error, error);
1515 error =
1516 cpl_propertylist_append_double(qclist,
1517 "ESO QC BIAS OVERSCAN MED STDEV",
1518 cpl_vector_get_stdev(medsover));
1519 cpl_ensure_code(!error, error);
1520 error =
1521 cpl_propertylist_append_double(qclist,
1522 "ESO QC BIAS OVERSCAN RMS STDEV",
1523 cpl_vector_get_stdev(rmssover));
1524 cpl_ensure_code(!error, error);
1525 */
1526
1527 cpl_vector_delete(meanspre);
1528 cpl_vector_delete(medspre);
1529 cpl_vector_delete(rmsspre);
1530 cpl_vector_delete(meansover);
1531 cpl_vector_delete(medsover);
1532 cpl_vector_delete(rmssover);
1533
1534 return CPL_ERROR_NONE;
1535}
1536
1537/*---------------------------------------------------------------------------*/
1538
1539/*
1540 * @brief Get RON on bias frames and statistics on master bias on region for QC
1541 * @param rawbiases Input image list
1542 * @param masterbias Input master bias
1543 * @param qclist input/output propertylist with QC parameters
1544 * @return CPL_ERROR_NONE on success.
1545 */
1546
1547/*---------------------------------------------------------------------------*/
1548static cpl_error_code
1549detmon_compute_bias_stats_and_ron_in_region(const cpl_imagelist * rawbiases,
1550 const cpl_image * masterbias,
1551 cpl_propertylist * qclist)
1552{
1553
1554 int nraws = cpl_imagelist_get_size(rawbiases);
1555 int i;
1556
1557 int nx =
1558 cpl_image_get_size_x(cpl_imagelist_get_const(rawbiases, 0));
1559 int ny =
1560 cpl_image_get_size_y(cpl_imagelist_get_const(rawbiases, 0));
1561
1562 cpl_vector *rmssreg;
1563 cpl_error_code error;
1564
1565 const cpl_image * c_raw;
1566 double median, mbias, mstdev;
1567
1568 if(!strcmp(detmon_ronbias_config.pmethod, "DIF")) nraws--;
1569
1570 rmssreg = cpl_vector_new(nraws);
1571
1572 if(nx < detmon_ronbias_config.ref_urx ||
1573 ny < detmon_ronbias_config.ref_ury) {
1574 cpl_msg_warning(cpl_func, "REGION method not applied. Given "
1575 "limits of prescan and overscan area "
1576 "exceed image size. Please check and rerun.");
1577 return CPL_ERROR_NONE;
1578 }
1579
1580 for(i = 0; i < nraws; i++) {
1581 double mean = 0;
1582 double stdev = 0;
1583 if(strcmp(detmon_ronbias_config.pmethod, "DIF")) {
1584 c_raw = cpl_imagelist_get_const(rawbiases, i);
1585 } else {
1586 const cpl_image *c1_raw = cpl_imagelist_get_const(rawbiases, i);
1587 const cpl_image * c2_raw = cpl_imagelist_get_const(rawbiases, i+1);
1588 c_raw = cpl_image_subtract_create(c1_raw, c2_raw);
1589 }
1590 error = irplib_ksigma_clip(c_raw,
1591 detmon_ronbias_config.ref_llx,
1592 detmon_ronbias_config.ref_lly,
1593 detmon_ronbias_config.ref_urx,
1594 detmon_ronbias_config.ref_ury,
1595 (double) detmon_ronbias_config.
1596 stacking_ks_low,
1597 detmon_ronbias_config.
1598 stacking_ks_iter, 1e-5,
1599 &mean, &stdev);
1600 cpl_ensure_code(!error, error);
1601 /* cpl_vector_set(rmssreg, i, cpl_image_get_stdev_window(c_raw,
1602 detmon_ronbias_config.ref_llx,
1603 detmon_ronbias_config.ref_lly,
1604 detmon_ronbias_config.ref_urx,
1605 detmon_ronbias_config.ref_ury));
1606 */
1607 error = cpl_vector_set(rmssreg, i, stdev);
1608 cpl_ensure_code(!error, error);
1609 if(!strcmp(detmon_ronbias_config.pmethod, "DIF")) cpl_image_delete((cpl_image *)c_raw);
1610 }
1611
1612 median = cpl_image_get_median_window(masterbias,
1613 detmon_ronbias_config.ref_llx,
1614 detmon_ronbias_config.ref_lly,
1615 detmon_ronbias_config.ref_urx,
1616 detmon_ronbias_config.ref_ury);
1617 error = irplib_ksigma_clip(masterbias,
1618 detmon_ronbias_config.ref_llx,
1619 detmon_ronbias_config.ref_lly,
1620 detmon_ronbias_config.ref_urx,
1621 detmon_ronbias_config.ref_ury,
1622 (double) detmon_ronbias_config.
1623 stacking_ks_low,
1624 detmon_ronbias_config.
1625 stacking_ks_iter, 1e-5,
1626 &mbias, &mstdev);
1627
1628 error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_REGION_MED,
1629 median);
1630 error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_REGION_MED,
1631 DETMON_QC_BIAS_REGION_MED_C);
1632 cpl_ensure_code(!error, error);
1633
1634 error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_REGION_VAL,
1635 mbias);
1636 error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_REGION_VAL,
1637 DETMON_QC_BIAS_REGION_VAL_C);
1638 cpl_ensure_code(!error, error);
1639 error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_REGION_RON,
1640 cpl_vector_get_mean(rmssreg));
1641 error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_REGION_RON,
1642 DETMON_QC_BIAS_REGION_RON_C);
1643 cpl_ensure_code(!error, error);
1644 /*
1645 error =
1646 cpl_propertylist_append_double(qclist, "ESO QC BIAS REGION RMS STDEV",
1647 cpl_vector_get_stdev(rmssreg));
1648 cpl_ensure_code(!error, error);
1649 */
1650 cpl_vector_delete(rmssreg);
1651
1652 return cpl_error_get_code();
1653}
1654
1655/*---------------------------------------------------------------------------*/
1656
1657/*
1658 * @brief Determines master bias and QC parameters
1659 * @param rawbiases Input raw images
1660 * @param bpmhot hot pixel bpm
1661 * @param bpmcold cold pixel bpm
1662 * @param bpmdev deviant pixel bpm
1663 * @param qclist fits header
1664 * @return master bias on success or NULL
1665 */
1666
1667/*---------------------------------------------------------------------------*/
1668static cpl_image *
1669detmon_ronbias_master(const cpl_imagelist * rawbiases,
1670 cpl_mask ** bpmhot, cpl_mask ** bpmcold,
1671 cpl_mask ** bpmdev, cpl_propertylist * qclist)
1672{
1673 double mean = 0;
1674 double stdev = 0;
1675 cpl_image *masterbias = NULL;
1676 double dark_med, stdev_med,lower, upper;
1677 int hotpix_nb, coldpix_nb, devpix_nb;
1678 cpl_image * stdev_im = NULL;
1679
1680 if(!strcmp(detmon_ronbias_config.stacking_method, "MEAN"))
1681 masterbias = cpl_imagelist_collapse_create(rawbiases);
1682 if(!strcmp(detmon_ronbias_config.stacking_method, "MINMAX"))
1683 masterbias =
1684 cpl_imagelist_collapse_minmax_create(rawbiases, 0, 10000);
1685 if(!strcmp(detmon_ronbias_config.stacking_method, "KSIGMA"))
1686 masterbias =
1687 cpl_imagelist_collapse_sigclip_create(rawbiases, 3.0, 3.0, 0.9,
1688 CPL_COLLAPSE_MEAN, NULL);
1689 if(!strcmp(detmon_ronbias_config.stacking_method, "MEDIAN"))
1690 masterbias = cpl_imagelist_collapse_median_create(rawbiases);
1691
1692 skip_if(masterbias == NULL);
1693
1694 skip_if(irplib_ksigma_clip(masterbias, 1, 1,
1695 cpl_image_get_size_x(masterbias),
1696 cpl_image_get_size_y(masterbias),
1697 (double) detmon_ronbias_config.
1698 stacking_ks_low,
1699 detmon_ronbias_config.
1700 stacking_ks_iter, 1e-5,
1701 &mean, &stdev));
1702
1703 if(irplib_isnan(mean))
1704 cpl_msg_error(cpl_func, "We have an error in mean");
1705 if(irplib_isnan(stdev))
1706 cpl_msg_error(cpl_func, "We have an error in stdev");
1707
1708 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_MASTER_MEAN,
1709 mean));
1710 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_MASTER_MEAN,
1711 DETMON_QC_MASTER_MEAN_C));
1712
1713 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_MASTER_RMS,
1714 stdev));
1715 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_MASTER_RMS,
1716 DETMON_QC_MASTER_RMS_C));
1717
1718 /* Compute median-rms of the central part of the dark */
1719 dark_med = cpl_image_get_median(masterbias);
1720
1721 lower = dark_med - stdev * detmon_ronbias_config.stacking_ks_low;
1722 upper = dark_med + stdev * detmon_ronbias_config.stacking_ks_high;
1723
1724 /* Create the hot pixel map */
1725 cpl_mask_delete(*bpmhot);
1726 irplib_check(*bpmhot = cpl_mask_threshold_image_create(masterbias,
1727 upper, DBL_MAX),
1728 "Cannot compute the hot pixel map");
1729 hotpix_nb = cpl_mask_count(*bpmhot);
1730 skip_if (0);
1731
1732 /* Create the cold pixel map */
1733 cpl_mask_delete(*bpmcold);
1734 irplib_check(*bpmcold = cpl_mask_threshold_image_create(masterbias,
1735 -FLT_MAX, lower),
1736 "Cannot compute the cold pixel map");
1737 coldpix_nb = cpl_mask_count(*bpmcold);
1738 skip_if (0);
1739
1740 /* Create the deviant pixel map */
1741 stdev_im = irplib_imagelist_collapse_stdev_create(rawbiases);
1742 stdev_med = cpl_image_get_median(stdev_im);
1743
1744 skip_if(irplib_ksigma_clip(stdev_im, 1, 1,
1745 cpl_image_get_size_x(stdev_im),
1746 cpl_image_get_size_y(stdev_im),
1747 (double) detmon_ronbias_config.
1748 stacking_ks_low,
1749 detmon_ronbias_config.
1750 stacking_ks_iter, 1e-5,
1751 &mean, &stdev));
1752
1753 lower = stdev_med - stdev * detmon_ronbias_config.stacking_ks_low;
1754 upper = stdev_med + stdev * detmon_ronbias_config.stacking_ks_high;
1755
1756 cpl_mask_delete(*bpmdev);
1757 irplib_check(*bpmdev = cpl_mask_threshold_image_create(stdev_im,
1758 lower, upper),
1759 "Cannot compute the cold pixel map");
1760 cpl_mask_not(*bpmdev);
1761 devpix_nb = cpl_mask_count(*bpmdev);
1762 skip_if (0);
1763
1764
1765 skip_if(cpl_propertylist_append_int(qclist,DETMON_QC_NBCOLDPIX,coldpix_nb));
1766 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_NBCOLDPIX,
1767 DETMON_QC_NBCOLDPIX_C));
1768
1769 skip_if(cpl_propertylist_append_int(qclist,DETMON_QC_NBHOTPIX, hotpix_nb));
1770 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_NBHOTPIX,
1771 DETMON_QC_NBHOTPIX_C));
1772
1773 skip_if(cpl_propertylist_append_int(qclist,DETMON_QC_NBDEVPIX, devpix_nb));
1774 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_NBDEVPIX,
1775 DETMON_QC_NBDEVPIX_C));
1776
1777 end_skip;
1778
1779 cpl_image_delete(stdev_im);
1780
1781 if (cpl_error_get_code()) {
1782 cpl_image_delete(masterbias);
1783 masterbias = NULL;
1784 }
1785
1786 return masterbias;
1787}
1788
1789/*---------------------------------------------------------------------------*/
1790
1791/*
1792 * @brief save a ronbias results on a FITS file
1793 * @param parlist input parameters
1794 * @param frameset input frames
1795 * @param recipe_name input recipe name
1796 * @param pipeline_name input pipeline id
1797 * @param pafregexp regular expression to remove from FITS header
1798 * @param pro_master pro catg master frame
1799 * @param pro_xstr pro catg xstructure
1800 * @param pro_ystr pro catg ystructure
1801 * @param pro_synth pro catg synthetic frame
1802 * @param pro_bpmhot pro catg hot pix BPM
1803 * @param pro_pmpcold pro catg cold pix BPM
1804 * @param pro_ppmdev pro catg deviant pix BPM
1805 * @param package package name
1806 * @param masterbias master bias
1807 * @param synthetic synthetic frame
1808 * @param bpmhot hot pixel bpm
1809 * @param bpmcold cold pixel bpm
1810 * @param bpmdev deviant pixel bpm
1811 * @param qclist qc parameter (header)
1812 * @param flag_sets switch
1813 * @param which_set id to specify a given set
1814 * @param usedframes used frames
1815 * @param whichset id to specify a given set
1816 * @return CPL_ERROR_NONE on success.
1817 */
1818
1819/*---------------------------------------------------------------------------*/
1820static cpl_error_code
1821detmon_ronbias_save(const cpl_parameterlist * parlist,
1822 cpl_frameset * frameset,
1823 const char *recipe_name,
1824 const char *pipeline_name,
1825 const char *pafregexp,
1826 const cpl_propertylist * pro_master,
1827 const cpl_propertylist * pro_xstr, /* Unsupported*/
1828 const cpl_propertylist * pro_ystr, /* Unsupported*/
1829 const cpl_propertylist * pro_synth,
1830 const cpl_propertylist * pro_bpmhot,
1831 const cpl_propertylist * pro_bpmcold,
1832 const cpl_propertylist * pro_bpmdev,
1833 const char *package,
1834 const cpl_image * masterbias,
1835 const cpl_image * synthetic,
1836 const cpl_mask * bpmhot,
1837 const cpl_mask * bpmcold,
1838 const cpl_mask * bpmdev,
1839 cpl_propertylist * qclist,
1840 const int flag_sets,
1841 const int which_set,
1842 cpl_frameset * usedframes,
1843 int whichext)
1844{
1845
1846 cpl_frame *ref_frame;
1847 cpl_propertylist *plist = NULL;
1848 char *name_o = NULL; /* Avoid (false) uninit warning */
1849
1850 cpl_propertylist * paflist = NULL;
1851 cpl_propertylist * mainplist = NULL;
1852 cpl_propertylist * xplist = NULL;
1853 cpl_image * image = NULL;
1854
1855 cpl_propertylist * mypro_master =
1856 cpl_propertylist_duplicate(pro_master);
1857
1858 cpl_propertylist * mypro_synth = NULL;
1859 cpl_propertylist * mypro_bpmhot =
1860 cpl_propertylist_duplicate(pro_bpmhot);
1861 cpl_propertylist * mypro_bpmcold =
1862 cpl_propertylist_duplicate(pro_bpmcold);
1863 cpl_propertylist * mypro_bpmdev =
1864 cpl_propertylist_duplicate(pro_bpmdev);
1865
1866 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
1867 cpl_ensure_code(frameset != NULL, CPL_ERROR_NULL_INPUT);
1868 cpl_ensure_code(pafregexp != NULL, CPL_ERROR_NULL_INPUT);
1869 cpl_ensure_code(package != NULL, CPL_ERROR_NULL_INPUT);
1870 cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
1871 cpl_ensure_code(pipeline_name != NULL, CPL_ERROR_NULL_INPUT);
1872 cpl_ensure_code(usedframes != NULL, CPL_ERROR_NULL_INPUT);
1873
1874 if (pro_synth)
1875 mypro_synth = cpl_propertylist_duplicate(pro_synth);
1876
1877 /* Extra check while XSTR and YSTR are not supported */
1878 cpl_ensure_code(pro_xstr == NULL && pro_ystr == NULL,
1879 CPL_ERROR_UNSUPPORTED_MODE);
1880
1881 /* Extract extension headers if multi-extension */
1882 if (detmon_ronbias_config.exts < 0) {
1883 const char * filename =
1884 cpl_frame_get_filename(cpl_frameset_get_position(frameset, 0));
1885
1886
1887 xplist = cpl_propertylist_load_regexp(filename, whichext,
1888 "ESO DET", 0);
1889 skip_if(cpl_propertylist_append(xplist, qclist));
1890 }
1891
1892 cpl_msg_info(cpl_func,"dealing with extention %d",whichext);
1893
1894 /* This is only used later for PAF */
1895 /* Get FITS header from reference file */
1896 ref_frame = cpl_frameset_get_position(frameset, 0);
1897 skip_if(ref_frame == NULL);
1898
1899 skip_if((mainplist =
1900 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
1901 0)) == NULL);
1902
1903 /**************************/
1904 /* Write the MASTERBIAS */
1905 /**************************/
1906
1907 /* Set the file name for the table */
1908 if(!flag_sets) {
1909 name_o = cpl_sprintf("%s_masterbias.fits", recipe_name);
1910 assert(name_o != NULL);
1911 } else {
1912 name_o =
1913 cpl_sprintf("%s_masterbias_set%02d.fits", recipe_name,
1914 which_set);
1915 assert(name_o != NULL);
1916 }
1917 /* Save the MASTERBIAS image */
1918 if (whichext == 0) {
1919 cpl_propertylist_append(mypro_master, qclist);
1920
1921 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
1922 masterbias, CPL_BPP_IEEE_FLOAT, recipe_name,
1923 mypro_master, NULL, package, name_o));
1924 } else
1925 skip_if(cpl_image_save(masterbias,
1926 name_o, CPL_BPP_IEEE_FLOAT, xplist,
1927 CPL_IO_EXTEND));
1928
1929 /* Free */
1930 cpl_free(name_o);
1931 name_o = NULL;
1932
1933 /*****************************/
1934 /* Write the HOT PIXEL MAP */
1935 /*****************************/
1936
1937 /* Set the file name for the table */
1938 if(!flag_sets) {
1939 name_o = cpl_sprintf("%s_hotpixmap.fits", recipe_name);
1940 assert(name_o != NULL);
1941 } else {
1942 name_o =
1943 cpl_sprintf("%s_hotpixmap_set%02d.fits", recipe_name,
1944 which_set);
1945 assert(name_o != NULL);
1946 }
1947 /* Save the HOTBPM image */
1948 skip_if(0);
1949 image = cpl_image_new_from_mask(bpmhot);
1950 cpl_error_reset();
1951
1952 if (whichext == 0) {
1953 cpl_propertylist_append(mypro_bpmhot, qclist);
1954
1955 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
1956 image, CPL_BPP_IEEE_FLOAT, recipe_name,
1957 mypro_bpmhot, NULL, package, name_o));
1958 } else
1959 skip_if(cpl_image_save(image,
1960 name_o, CPL_BPP_IEEE_FLOAT, xplist,
1961 CPL_IO_EXTEND));
1962
1963 /* Free */
1964 cpl_free(name_o);
1965 cpl_image_delete(image);
1966 image = NULL;
1967 name_o = NULL;
1968
1969 /*****************************/
1970 /* Write the COLD PIXEL MAP */
1971 /*****************************/
1972
1973 /* Set the file name for the table */
1974 if(!flag_sets) {
1975 name_o = cpl_sprintf("%s_coldpixmap.fits", recipe_name);
1976 assert(name_o != NULL);
1977 } else {
1978 name_o =
1979 cpl_sprintf("%s_coldpixmap_set%02d.fits", recipe_name,
1980 which_set);
1981 assert(name_o != NULL);
1982 }
1983 /* Save the COLDBPM image */
1984 skip_if(0);
1985 image = cpl_image_new_from_mask(bpmcold);
1986 cpl_error_reset();
1987
1988 if (whichext == 0) {
1989 cpl_propertylist_append(mypro_bpmcold, qclist);
1990
1991 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
1992 image, CPL_BPP_IEEE_FLOAT, recipe_name,
1993 mypro_bpmcold, NULL, package, name_o));
1994 } else
1995 skip_if(cpl_image_save(image,
1996 name_o, CPL_BPP_IEEE_FLOAT, xplist,
1997 CPL_IO_EXTEND));
1998
1999 /* Free */
2000 cpl_free(name_o);
2001 cpl_image_delete(image);
2002 image = NULL;
2003 name_o = NULL;
2004
2005 /*****************************/
2006 /* Write the DEV PIXEL MAP */
2007 /*****************************/
2008
2009 /* Set the file name for the table */
2010 if(!flag_sets) {
2011 name_o = cpl_sprintf("%s_devpixmap.fits", recipe_name);
2012 assert(name_o != NULL);
2013 } else {
2014 name_o =
2015 cpl_sprintf("%s_devpixmap_set%02d.fits", recipe_name,
2016 which_set);
2017 assert(name_o != NULL);
2018 }
2019 /* Save the DEVBPM image */
2020 skip_if(0);
2021 image = cpl_image_new_from_mask(bpmdev);
2022 cpl_error_reset();
2023
2024 if (whichext == 0) {
2025 cpl_propertylist_append(mypro_bpmdev, qclist);
2026
2027 skip_if(cpl_dfs_save_image(frameset, NULL,parlist, usedframes, NULL,
2028 image, CPL_BPP_IEEE_FLOAT, recipe_name,
2029 mypro_bpmdev, NULL, package, name_o));
2030 } else
2031 skip_if(cpl_image_save(image,
2032 name_o, CPL_BPP_IEEE_FLOAT, xplist,
2033 CPL_IO_EXTEND));
2034
2035 /* Free */
2036 cpl_free(name_o);
2037 cpl_image_delete(image);
2038 image = NULL;
2039 name_o = NULL;
2040
2041 /*******************************/
2042 /* Write the SYNTHETIC */
2043 /*******************************/
2044 if(detmon_ronbias_config.method_bitmask & PREOVERSCAN) {
2045 /* Set the file name for the table */
2046 if(!flag_sets) {
2047 name_o = cpl_sprintf("%s_synthetic.fits", recipe_name);
2048 assert(name_o != NULL);
2049 } else {
2050 name_o =
2051 cpl_sprintf("%s_synthetic_set%02d.fits", recipe_name,
2052 which_set);
2053 assert(name_o != NULL);
2054 }
2055
2056 if (whichext == 0) {
2057 /* Save the SYNTHETIC image */
2058 cpl_propertylist_append(mypro_synth, qclist);
2059
2060 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
2061 NULL,synthetic, CPL_BPP_IEEE_DOUBLE,
2062 recipe_name, mypro_synth, NULL,
2063 package, name_o));
2064 } else
2065 skip_if(cpl_image_save(synthetic, name_o, CPL_BPP_IEEE_FLOAT,
2066 xplist, CPL_IO_EXTEND));
2067
2068 /* Free */
2069 cpl_free(name_o);
2070 name_o = NULL;
2071 }
2072
2073 /*******************************/
2074 /* Write the PAF file */
2075 /*******************************/
2076 if (qclist) {
2077 paflist = cpl_propertylist_new();
2078
2079 /* Set the file name for the PAF */
2080 if(detmon_ronbias_config.exts >= 0) {
2081 skip_if((plist =
2082 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
2083 detmon_ronbias_config.exts)) == NULL);
2084
2085 if(!flag_sets) {
2086 name_o = cpl_sprintf("%s.paf", recipe_name);
2087 assert(name_o != NULL);
2088 } else {
2089 name_o = cpl_sprintf("%s_set%02d.paf",
2090 recipe_name, which_set);
2091 assert(name_o != NULL);
2092 }
2093 } else {
2094 skip_if((plist =
2095 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
2096 whichext)) == NULL);
2097
2098
2099 if(!flag_sets) {
2100 name_o = cpl_sprintf("%s_ext%02d.paf",
2101 recipe_name, whichext);
2102 assert(name_o != NULL);
2103 } else {
2104 name_o = cpl_sprintf("%s_set%02d_ext%02d.paf",
2105 recipe_name,
2106 which_set, whichext);
2107 assert(name_o != NULL);
2108 }
2109 }
2110
2111 /* Get the keywords for the paf file */
2112 skip_if(cpl_propertylist_copy_property_regexp(paflist, plist,
2113 pafregexp, 0));
2114 skip_if(cpl_propertylist_copy_property_regexp(paflist, mainplist,
2115 pafregexp, 0));
2116
2117 skip_if(cpl_propertylist_append(paflist, qclist));
2118
2119 /* Save the PAF */
2120 skip_if(cpl_dfs_save_paf(pipeline_name, recipe_name, paflist, name_o));
2121
2122 }
2123
2124 end_skip;
2125
2126 cpl_propertylist_delete(plist);
2127 cpl_propertylist_delete(paflist);
2128 cpl_propertylist_delete(mainplist);
2129 cpl_propertylist_delete(xplist);
2130 cpl_free(name_o);
2131 cpl_image_delete(image);
2132
2133 cpl_propertylist_delete(mypro_master);
2134 cpl_propertylist_delete(mypro_synth);
2135 cpl_propertylist_delete(mypro_bpmhot);
2136 cpl_propertylist_delete(mypro_bpmcold);
2137 cpl_propertylist_delete(mypro_bpmdev);
2138
2139 return cpl_error_get_code();
2140}
2141
2142/*---------------------------------------------------------------------------*/
2143/*
2144 * @brief Classify input data with a given tag
2145 * @param set Input frameset
2146 * @param tag Input tag
2147 * @return 0 on success, -1 if failure
2148 */
2149/*---------------------------------------------------------------------------*/
2150static int
2151detmon_ronbias_dfs_set_groups(cpl_frameset * set, const char *tag)
2152{
2153
2154
2155 int nframes;
2156 int i;
2157
2158 /* Check entries */
2159 if(set == NULL)
2160 return -1;
2161
2162 /* Initialize */
2163 nframes = cpl_frameset_get_size(set);
2164
2165 /* Loop on frames */
2166 for(i = 0; i < nframes; i++) {
2167 cpl_frame* cur_frame = cpl_frameset_get_position(set, i);
2168 const char* cur_tag = cpl_frame_get_tag(cur_frame);
2169
2170 /* RAW frames */
2171 if(!strcmp(cur_tag, tag))
2172 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
2173 /* CALIB frames */
2174
2175 /* else if (!strcmp(tag, IIINSTRUMENT_CALIB_FLAT))
2176 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_CALIB) ;
2177 */
2178 }
2179 return 0;
2180}
2181
2182/*---------------------------------------------------------------------------*/
2183
2184/*
2185 * @brief build synthetic frame from pre-overscan images
2186 *
2187 * @param prescan prescan image
2188 * @param overscan overscan image
2189 *
2190 * @return CPL_ERROR_NONE on success.
2191 */
2192
2193/*---------------------------------------------------------------------------*/
2194static cpl_image *
2195detmon_build_synthetic_from_pre_overscan(const cpl_image * prescan,
2196 const cpl_image * overscan)
2197{
2198 cpl_size j;
2199
2200 int distance = detmon_ronbias_config.overscan_urx -
2201 detmon_ronbias_config.prescan_llx + 1;
2202
2203 double * mean_x = (double *) cpl_malloc(sizeof(double) * distance);
2204
2205 double * xvalues = (double *) cpl_malloc(sizeof(double) * distance);
2206
2207 cpl_vector *x = NULL;
2208 cpl_vector *y = NULL;
2209
2210 cpl_polynomial *poly = NULL;
2211 cpl_polynomial *poly2 = NULL;
2212
2213 cpl_matrix * samppos;
2214
2215 cpl_size pows[2] = { 0, 0 };
2216
2217 cpl_image * synthetic = NULL;
2218
2219 double initial = 0;
2220
2221 /* Initialize */
2222 for(j = 0; j < distance; j++) {
2223 *(mean_x + j) = 0;
2224 *(xvalues + j) = j;
2225 }
2226
2227 for(j = 0; j < cpl_image_get_size_x(prescan); j++) {
2228 *(mean_x + j) =
2229 cpl_image_get_mean_window(prescan, j + 1, 1, j + 1,
2230 cpl_image_get_size_y(prescan));
2231 }
2232
2233 for(j = 0; j < cpl_image_get_size_x(overscan); j++) {
2234 *(mean_x + distance - cpl_image_get_size_x(overscan) + j) =
2235 cpl_image_get_mean_window(overscan, j + 1, 1, j + 1,
2236 cpl_image_get_size_y(overscan));
2237 }
2238
2239 x = cpl_vector_wrap(distance, xvalues);
2240 y = cpl_vector_wrap(distance, mean_x);
2241
2242 poly = cpl_polynomial_new(1);
2243 samppos =
2244 cpl_matrix_wrap(1, cpl_vector_get_size(x), cpl_vector_get_data(x));
2245
2246 cpl_polynomial_fit(poly, samppos, NULL, y, NULL,
2247 CPL_FALSE, NULL, &detmon_ronbias_config.preoverscan_degree);
2248
2249 cpl_matrix_unwrap(samppos);
2250
2251 cpl_vector_unwrap(x);
2252 cpl_vector_unwrap(y);
2253
2254 initial = *mean_x;
2255
2256 cpl_free(xvalues);
2257 cpl_free(mean_x);
2258
2259 poly2 = cpl_polynomial_new(2);
2260
2261 j = 0;
2262 cpl_polynomial_set_coeff(poly2, pows, cpl_polynomial_get_coeff(poly, &j));
2263
2264 pows[0] = 1;
2265 j = 1;
2266 cpl_polynomial_set_coeff(poly2, pows, cpl_polynomial_get_coeff(poly, &j));
2267
2268 cpl_polynomial_delete(poly);
2269
2270 synthetic =
2271 cpl_image_new(distance, cpl_image_get_size_y(prescan),
2272 CPL_TYPE_DOUBLE);
2273
2274 if(cpl_image_fill_polynomial(synthetic, poly2, initial, 1, 1, 1)) {
2275 cpl_msg_error(cpl_func, "Error creating the synthetic frame");
2276 cpl_polynomial_delete(poly2);
2277 return NULL;
2278 }
2279
2280 cpl_polynomial_delete(poly2);
2281
2282 return synthetic;
2283}
2284
2285/*---------------------------------------------------------------------------*/
2286
2287/*
2288 * @brief computes dutycycle
2289 * @param frameset Input frameset
2290 * @param qclist header to hold qc parameter
2291 * @return CPL_ERROR_NONE on success.
2292 */
2293
2294/*---------------------------------------------------------------------------*/
2295static cpl_error_code
2296detmon_ronbias_dutycycl(const cpl_frameset * frameset,
2297 cpl_propertylist * qclist)
2298{
2299 const cpl_frame *first = 0;
2300 cpl_propertylist *plistfirst = 0;
2301 double tfirst;
2302 int nraws;
2303 const cpl_frame *last = 0;
2304 cpl_propertylist *plistlast = 0;
2305 double tlast;
2306 double dutycycl;
2307 cpl_error_code error;
2308
2309 first = cpl_frameset_get_position_const(frameset, 0);
2310 plistfirst = cpl_propertylist_load(cpl_frame_get_filename(first), 0);
2311 tfirst = cpl_propertylist_get_double(plistfirst, "MJD-OBS");
2312 nraws = cpl_frameset_get_size(frameset);
2313 last = cpl_frameset_get_position_const(frameset, nraws - 1);
2314 plistlast = cpl_propertylist_load(cpl_frame_get_filename(last), 0);
2315 tlast = cpl_propertylist_get_double(plistlast, "MJD-OBS");
2316 dutycycl = (tlast - tfirst) / (nraws - 1);
2317
2318 error = cpl_error_get_code();
2319 if (error != CPL_ERROR_NONE)
2320 {
2321 goto cleanup;
2322 }
2323 cpl_propertylist_append_double(qclist,DETMON_QC_DUTYCYCL, dutycycl);
2324 error = cpl_propertylist_set_comment(qclist,DETMON_QC_DUTYCYCL,
2325 DETMON_QC_DUTYCYCL_C);
2326
2327cleanup:
2328
2329 cpl_propertylist_delete(plistfirst);
2330 cpl_propertylist_delete(plistlast);
2331
2332 return error;
2333}
2334
2335
2336/* Start duplicated code */
2337
2338#define RECT_RON_HS 4
2339#define RECT_RON_SAMPLES 100
2340
2341/*---------------------------------------------------------------------------*/
2342
2343/*
2344 * @brief Computes bias level and ron in a region
2345 * @param diff Input difference image
2346 * @param zone_def Input zone definition
2347 * @param ron_hsize window half size to compute ron
2348 * @param ron_nsamp number of (randomly distributed) sampling windows
2349 * @param bias output bias level
2350 * @param error output error associated to bias level
2351 * @return CPL_ERROR_NONE on success.
2352 */
2353
2354/*---------------------------------------------------------------------------*/
2355cpl_error_code
2356irplib_flux_get_bias_window(const cpl_image * diff,
2357 const int *zone_def,
2358 int ron_hsize,
2359 int ron_nsamp, double *bias, double *error)
2360{
2361 const int hsize = ron_hsize < 0 ? RECT_RON_HS : ron_hsize;
2362 const int nsamples =
2363 ron_nsamp < 0 ? RECT_RON_SAMPLES : ron_nsamp;
2364 cpl_bivector *sample_reg;
2365 cpl_vector *rms_list;
2366 int rect[4];
2367 int zone[4];
2368 double *px;
2369 double *py;
2370 double *pr;
2371 int i;
2372
2373 /* Test entries */
2374 cpl_ensure_code(diff && bias, CPL_ERROR_NULL_INPUT);
2375
2376 /* Generate nsamples window centers in the image */
2377 if(zone_def != NULL) {
2378 rect[0] = zone_def[0] + hsize + 1; /* xmin */
2379 rect[1] = zone_def[1] - hsize - 1; /* xmax */
2380 rect[2] = zone_def[2] + hsize + 1; /* ymin */
2381 rect[3] = zone_def[3] - hsize - 1; /* ymax */
2382 } else {
2383 rect[0] = hsize + 1; /* xmin */
2384 rect[1] = cpl_image_get_size_x(diff) - hsize - 1; /* xmax */
2385 rect[2] = hsize + 1; /* ymin */
2386 rect[3] = cpl_image_get_size_y(diff) - hsize - 1; /* ymax */
2387 }
2388
2389 cpl_ensure_code(rect[0] < rect[1] && rect[2] < rect[3],
2390 CPL_ERROR_ILLEGAL_INPUT);
2391
2392 /* Generate n+1 regions, because the first region is always at (0,0) */
2393 /* and it would bias the measurement. */
2394 sample_reg =
2395 irplib_bivector_gen_rect_poisson(rect, nsamples + 1, nsamples + 1);
2396 cpl_ensure(sample_reg != NULL, CPL_ERROR_ILLEGAL_INPUT,
2397 CPL_ERROR_ILLEGAL_INPUT);
2398
2399 px = cpl_bivector_get_x_data(sample_reg);
2400 py = cpl_bivector_get_y_data(sample_reg);
2401
2402 /* Now, for each window center, extract a vignette and compute the */
2403 /* signal RMS in it. Store this rms into a table. */
2404 rms_list = cpl_vector_new(nsamples);
2405 cpl_ensure(rms_list != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2406 pr = cpl_vector_get_data(rms_list);
2407
2408 for(i = 0; i < nsamples; i++) {
2409 zone[0] = (int) px[i + 1] - hsize;
2410 zone[1] = (int) px[i + 1] + hsize;
2411 zone[2] = (int) py[i + 1] - hsize;
2412 zone[3] = (int) py[i + 1] + hsize;
2413 pr[i] = cpl_image_get_mean_window(diff,
2414 zone[0], zone[2], zone[1], zone[3]);
2415 }
2416 cpl_bivector_delete(sample_reg);
2417
2418 /* The error is the rms of the rms */
2419 if(error != NULL)
2420 *error = cpl_vector_get_stdev(rms_list);
2421
2422 /* The final computed RMS is the median of all values. */
2423 /* This call will modify the rms_list */
2424 *bias = cpl_vector_get_median(rms_list);
2425
2426 cpl_vector_delete(rms_list);
2427
2428 return CPL_ERROR_NONE;
2429}
2430
2431#undef RECT_RON_HS
2432#undef RECT_RON_SAMPLES
2433
2434/*---------------------------------------------------------------------------*/
2435
2436/*
2437 * @brief Generates Poisson distributed values
2438 * @param r Input values
2439 * @param np number of points
2440 * @param homog homogeneity factor
2441 * @return CPL_ERROR_NONE on success.
2442 */
2443
2444/*---------------------------------------------------------------------------*/
2445static cpl_bivector *
2446irplib_bivector_gen_rect_poisson(const int *r, const int np, const int homog)
2447{
2448 double min_dist;
2449 int i;
2450 int gnp;
2451 cpl_bivector *list;
2452 double cand_x, cand_y;
2453 int ok;
2454 int start_ndx;
2455 int xmin, xmax, ymin, ymax;
2456
2457 /* Corrected Homogeneity factor */
2458 const int homogc = 0 < homog && homog < np ? homog : np;
2459 double *px;
2460 double *py;
2461
2462 /* error handling: test arguments are correct */
2463 cpl_ensure(r, CPL_ERROR_NULL_INPUT, NULL);
2464 cpl_ensure(np > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
2465
2466 list = cpl_bivector_new(np);
2467 cpl_ensure(list, CPL_ERROR_NULL_INPUT, NULL);
2468 px = cpl_bivector_get_x_data(list);
2469 py = cpl_bivector_get_y_data(list);
2470
2471 xmin = r[0];
2472 xmax = r[1];
2473 ymin = r[2];
2474 ymax = r[3];
2475
2476 min_dist =
2477 CPL_MATH_SQRT1_2 * ((xmax - xmin) * (ymax - ymin) / (double) (homogc + 1));
2478 gnp = 1;
2479 px[0] = 0;
2480 py[0] = 0;
2481
2482 /* First: generate <homog> points */
2483 while(gnp < homogc) {
2484 /* Pick a random point within requested range */
2485 cand_x = cpl_drand() * (xmax - xmin) + xmin;
2486 cand_y = cpl_drand() * (ymax - ymin) + ymin;
2487
2488 /* Check the candidate obeys the minimal Poisson distance */
2489 ok = 1;
2490 for(i = 0; i < gnp; i++) {
2491 if(pdist(cand_x, cand_y, px[i], py[i]) < min_dist) {
2492 /* does not check Poisson law: reject point */
2493 ok = 0;
2494 break;
2495 }
2496 }
2497 if(ok) {
2498 /* obeys Poisson law: register the point as valid */
2499 px[gnp] = cand_x;
2500 py[gnp] = cand_y;
2501 gnp++;
2502 }
2503 }
2504
2505 /* Iterative process: */
2506 /* Pick points out of Poisson distance of the last <homogc-1> points. */
2507 start_ndx = 0;
2508 while(gnp < np) {
2509 /* Pick a random point within requested range */
2510 cand_x = cpl_drand() * (xmax - xmin) + xmin;
2511 cand_y = cpl_drand() * (ymax - ymin) + ymin;
2512
2513 /* Check the candidate obeys the minimal Poisson distance */
2514 ok = 1;
2515 for(i = 0; i < homogc; i++) {
2516 if(pdist(cand_x,
2517 cand_y,
2518 px[start_ndx + i], py[start_ndx + i]) < min_dist) {
2519 /* does not check Poisson law: reject point */
2520 ok = 0;
2521 break;
2522 }
2523 }
2524 if(ok) {
2525 /* obeys Poisson law: register the point as valid */
2526 px[gnp] = cand_x;
2527 py[gnp] = cand_y;
2528 gnp++;
2529 }
2530 }
2531
2532 /* Iterative process: */
2533 /* Pick points out of Poisson distance of the last <homogc-1> points. */
2534 start_ndx = 0;
2535 while(gnp < np) {
2536 /* Pick a random point within requested range */
2537 cand_x = cpl_drand() * (xmax - xmin) + xmin;
2538 cand_y = cpl_drand() * (ymax - ymin) + ymin;
2539
2540 /* Check the candidate obeys the minimal Poisson distance */
2541 ok = 1;
2542 for(i = 0; i < homogc; i++) {
2543 if(pdist(cand_x,
2544 cand_y,
2545 px[start_ndx + i], py[start_ndx + i]) < min_dist) {
2546 /* does not check Poisson law: reject point */
2547 ok = 0;
2548 break;
2549 }
2550 }
2551 if(ok) {
2552 /* obeys Poisson law: register the point as valid */
2553 px[gnp] = cand_x;
2554 py[gnp] = cand_y;
2555 gnp++;
2556 start_ndx++;
2557 }
2558 }
2559 return list;
2560}
2561
2562/* End of duplicated code */
2563
2564
2565/*---------------------------------------------------------------------------*/
2582/*---------------------------------------------------------------------------*/
2583cpl_image *
2584irplib_imagelist_collapse_stdev_create(const cpl_imagelist * imlist)
2585{
2586
2587
2588
2589
2590
2591
2592 /* Check inputs */
2593 cpl_ensure(imlist != NULL, CPL_ERROR_NULL_INPUT, NULL);
2594 cpl_ensure(cpl_imagelist_is_uniform(imlist) == 0, CPL_ERROR_ILLEGAL_INPUT,
2595 NULL);
2596
2597 /* Create mean image with its first iterative value = first image */
2598 cpl_image* mean = cpl_image_duplicate(cpl_imagelist_get_const(imlist, 0));
2599 cpl_image_fill_rejected(mean, 0.0);
2600 cpl_image_accept_all(mean);
2601
2602 cpl_image* stdev = cpl_image_new(cpl_image_get_size_x(mean),
2603 cpl_image_get_size_y(mean),
2604 CPL_TYPE_FLOAT);
2605
2606 for (int i = 1; i < cpl_imagelist_get_size(imlist); i++) {
2607 cpl_image* delta = cpl_image_subtract_create(cpl_imagelist_get_const(imlist, i),
2608 mean);
2609 cpl_image_fill_rejected(delta, 0.0);
2610 cpl_image_accept_all(delta);
2611
2612 cpl_image* sq_delta = cpl_image_multiply_create(delta, delta);
2613
2614 cpl_image_multiply_scalar(sq_delta, ((double) i / (double)(i+1)));
2615 cpl_image_add(stdev, sq_delta);
2616
2617 cpl_image_divide_scalar(delta, i + 1);
2618 cpl_image_add(mean, delta);
2619
2620 cpl_image_delete(delta);
2621 cpl_image_delete(sq_delta);
2622 }
2623
2624 cpl_image_divide_scalar(stdev, cpl_imagelist_get_size(imlist) - 1);
2625 cpl_image_power(stdev, 0.5);
2626
2627 cpl_image_delete(mean);
2628
2629 return stdev;
2630}