X-shooter Pipeline Reference Manual 3.8.15
xsh_detmon_lg.c
Go to the documentation of this file.
1/* $Id: xsh_detmon_lg.c,v 1.31 2013-08-07 09:32:37 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/*
23 * $Author: jtaylor $
24 * $Date: 2013-08-07 09:32:37 $
25 * $Revision: 1.31 $
26 * $Name: not supported by cvs2svn $
27 *
28 */
29
30#ifdef HAVE_CONFIG_H
31#include <config.h>
32#endif
33
34/*---------------------------------------------------------------------------
35 Includes
36 ---------------------------------------------------------------------------*/
37
38#include <cpl.h>
39#include <cpl_fft.h>
40#include "hdrl.h"
41
42#include "xsh_detmon.h"
43#include "xsh_detmon_utils.h"
44#include "xsh_detmon_lg.h"
45#include "xsh_detmon_lg_impl.h"
46#include "xsh_detmon_dfs.h"
47#include "xsh_dfs.h"
48#include "xsh_ksigma_clip.h"
49#include "irplib_utils.h"
50#include "irplib_hist.h"
51#include <complex.h>
52
53
54#include <math.h>
55#include <string.h>
56#include <assert.h>
57
59/*
60 * @defgroup irplib_xsh_detmon Detector monitoring functions
61 */
62
63/*--------------------------------------------------------------------------*/
64
65/*---------------------------------------------------------------------------
66 Defines
67 ---------------------------------------------------------------------------*/
68/*method for calculating Fixed Pattern Noise (FPN)*/
70{
72 FPN_HISTOGRAM, /*default*/
74};
76static struct
77{
78 const char * method;
79 /* Inputs */
80 int order;
81 double kappa;
82 int niter;
85 int llx;
86 int lly;
87 int urx;
88 int ury;
91 int m;
92 int n;
93 int llx1;
94 int lly1;
95 int urx1;
96 int ury1;
97 int llx2;
98 int lly2;
99 int urx2;
100 int ury2;
101 int llx3;
102 int lly3;
103 int urx3;
104 int ury3;
105 int llx4;
106 int lly4;
107 int urx4;
108 int ury4;
109 int llx5;
110 int lly5;
111 int urx5;
112 int ury5;
113 int nx;
114 int ny;
115 cpl_boolean wholechip;
116 cpl_boolean autocorr;
117 cpl_boolean intermediate;
118 cpl_boolean collapse;
119 cpl_boolean rescale;
120 cpl_boolean pix2pix;
121 cpl_boolean bpmbin;
123 double tolerance;
124 cpl_boolean pafgen;
125 const char * pafname;
126 /* Outputs */
127 double cr;
128 int exts;
131 cpl_boolean lamp_ok;
132 /* by kmirny */
133 int (* load_fset) (const cpl_frameset *, cpl_type, cpl_imagelist *);
134 cpl_imagelist * (* load_fset_wrp) (const cpl_frameset *, cpl_type, int);
139 cpl_boolean split_coeffs;
141
142/* static const char* COL_NAME_DET1_WIN1_UIT1 = "DET1_WIN1_UIT1"; */
143/*---------------------------------------------------------------------------
144 Private function prototypes
145 ---------------------------------------------------------------------------*/
146/* Functions for the Linearity/Gain recipe, xsh_detmon_lg() */
147
148/* Parameters */
149static cpl_error_code
151 const char *, const cpl_parameterlist *,
152 cpl_boolean);
153
154
155static cpl_error_code
156xsh_detmon_lg_split_onoff(const cpl_frameset *,
157 cpl_frameset *,
158 cpl_frameset *,
159 const char *, const char * /*, cpl_boolean*/);
160
161static cpl_error_code
162xsh_detmon_lg_reduce(const cpl_frameset *,
163 const cpl_frameset *,
164 int* index_on, int* index_off,
165 double* exptime_on, double* exptime_off,
166 int *next_index_on, int* next_index_off,
167 cpl_imagelist **,
168 cpl_table *,
169 cpl_table *,
170 cpl_image **,
171 cpl_imagelist *,
172 cpl_imagelist *,
173 cpl_propertylist *,
174 cpl_propertylist *,
175 cpl_propertylist *,
176 cpl_propertylist *,
177 int (* load_fset) (const cpl_frameset *,
178 cpl_type,
179 cpl_imagelist *),
180 const cpl_boolean, int);
181
182
183
184
185static cpl_error_code
186xsh_detmon_lin_table_fill_row(cpl_table *, double,
187 cpl_imagelist *,
188 const cpl_imagelist *,
189 const cpl_imagelist *,
190 int, int, int, int,
191 const int,
192 const int,
193 unsigned);
194
195static cpl_error_code
196xsh_detmon_gain_table_fill_row(cpl_table * gain_table,
197 double c_dit,int c_ndit,
198 cpl_imagelist * autocorr_images,
199 cpl_imagelist * diff_flats,
200 const cpl_imagelist * ons,
201 const cpl_imagelist * offs,
202 double kappa, int nclip,
203 int llx, int lly, int urx, int ury,
204 int m, int n,
205 double saturation_limit,
206 double gain_threshold,
207 const int pos, unsigned mode, int* rows_affected);
208
209
210static cpl_error_code
211xsh_detmon_check_saturation_on_pair(cpl_imagelist * autocorr_images,
212 cpl_imagelist * diff_flats,
213 const cpl_imagelist * ons,
214 const cpl_imagelist * offs,
215 double kappa, int nclip,
216 int llx, int lly, int urx, int ury,
217 double saturation_limit,
218 const int pos, unsigned mode,
219 int* rows_linear_affected);
220
221static cpl_error_code
222xsh_detmon_lg_save(const cpl_parameterlist *,
223 cpl_frameset *,
224 const char *,
225 const char *,
226 const char *,
227 const cpl_propertylist *,
228 const cpl_propertylist *,
229 const cpl_propertylist *,
230 const cpl_propertylist *,
231 const cpl_propertylist *,
232 const cpl_propertylist *,
233 const char *,
234 cpl_imagelist *,
235 cpl_table *,
236 cpl_table *,
237 cpl_image *,
238 cpl_imagelist *,
239 cpl_imagelist *,
240 cpl_propertylist *,
241 cpl_propertylist *,
242 cpl_propertylist *,
243 cpl_propertylist *,
244 const int, const int, const cpl_frameset *,
245 int);
246
247static cpl_error_code
248xsh_detmon_lg_qc_ptc(const cpl_table *,
249 cpl_propertylist *, unsigned, int);
250
251static cpl_error_code
252xsh_detmon_lg_qc_med(const cpl_table *,
253 cpl_propertylist *, int);
254
255
256static double
257irplib_pfits_get_dit(const cpl_propertylist *);
258
259static double
260irplib_pfits_get_dit_opt(const cpl_propertylist *);
261static double
262irplib_pfits_get_prop_double(const cpl_propertylist * plist,
263 const char* prop_name);
264
265static cpl_image * xsh_detmon_bpixs(const cpl_imagelist *,
266 cpl_boolean, const double, int *);
267
268static double
269xsh_detmon_autocorr_factor(const cpl_image *,
270 cpl_image **, int, int);
271
272
273
274static cpl_error_code
275xsh_detmon_opt_contamination(const cpl_imagelist *,
276 const cpl_imagelist *,
277 unsigned mode, cpl_propertylist *);
278
279#if 0
280xsh_detmon_opt_lampcr(cpl_frameset *, int);
281#endif
282
283int
284xsh_detmon_lg_dfs_set_groups(cpl_frameset *, const char *, const char *);
285
286static cpl_error_code
287xsh_detmon_lg_reduce_all(const cpl_table *,
288 cpl_propertylist *,
289 cpl_propertylist *,
290 cpl_propertylist *,
291 cpl_propertylist *,
292 cpl_imagelist **,
293 cpl_image **,
294 const cpl_imagelist *,
295 const cpl_table *, int, cpl_boolean);
296
297static cpl_error_code
298xsh_detmon_lg_check_defaults(const cpl_image *);
299
300static cpl_error_code
301xsh_detmon_lg_rescale(cpl_imagelist *);
302
303static cpl_error_code
304xsh_detmon_lg_reduce_init(cpl_table *,
305 cpl_table *,
306 cpl_imagelist **,
307 const cpl_boolean);
308
309
310static cpl_error_code
311xsh_detmon_add_adl_column(cpl_table *, cpl_boolean);
312
313static cpl_error_code
314xsh_detmon_lg_lamp_stab(const cpl_frameset *,
315 const cpl_frameset *,
316 cpl_boolean, int);
317
318
319static cpl_error_code
320xsh_detmon_lg_reduce_dit(const cpl_frameset * set_on,
321 int* index_on, double* exptime_on,
322 const int dit_nb,
323 int * dit_nskip,
324 const cpl_frameset * set_off,
325 int * index_off, double* exptime_off,
326 int* next_on, int* next_off,
327 cpl_table * linear_table,
328 cpl_table * gain_table,
329 cpl_imagelist * linearity_inputs,
330 cpl_propertylist * qclist,
331 cpl_boolean opt_nir,
332 cpl_imagelist * autocorr_images,
333 cpl_imagelist * diff_flats,
334 cpl_imagelist * opt_offs,
335 int whichext,
336 int * rows_linear_affected,
337 int * rows_gain_affected);
338
339static cpl_error_code
340xsh_detmon_lg_core(cpl_frameset * cur_fset_on,
341 cpl_frameset * cur_fset_off,
342 int * index_on,
343 int * index_off,
344 double * exptime_on,
345 double * exptime_off,
346 int whichext,
347 int whichset,
348 const char * recipe_name,
349 const char * pipeline_name,
350 const char * pafregexp,
351 const cpl_propertylist * pro_lintbl,
352 const cpl_propertylist * pro_gaintbl,
353 const cpl_propertylist * pro_coeffscube,
354 const cpl_propertylist * pro_bpm,
355 const cpl_propertylist * pro_corr,
356 const cpl_propertylist * pro_diff,
357 const char * package,
358 int (* load_fset) (const cpl_frameset *,
359 cpl_type,
360 cpl_imagelist *),
361 int nsets, cpl_boolean opt_nir,
362 cpl_frameset * frameset, const cpl_parameterlist * parlist,
363 cpl_frameset * cur_fset);
364
365static cpl_error_code
366xsh_detmon_lg_lineff(double *, cpl_propertylist *, int, int);
367
368/*
369 static int
370 xsh_detmon_lg_compare_pairs(const cpl_frame *,
371 const cpl_frame *);
372 */
373static cpl_error_code
375 const cpl_boolean);
376
377
378static cpl_error_code
380 const cpl_boolean);
381
382static cpl_vector *
383xsh_detmon_lg_find_dits(const cpl_vector *,
384 double );
385
386static cpl_error_code
387xsh_detmon_lg_find_dits_ndits(const cpl_vector * exptimes,
388 const cpl_vector * vec_ndits,
389 double tolerance,
390 cpl_vector** diff_dits,
391 cpl_vector** diff_ndits);
392
393static cpl_error_code
394xsh_detmon_fpn_compute(const cpl_frameset *set_on,
395 int * index_on,
396 int last_linear_best,
397 cpl_propertylist *lint_qclist,
398 int llx,
399 int lly,
400 int urx,
401 int ury,
402 double gain,
403 int whichext,
405 int smooth_size);
406static double irplib_fpn_lg(const cpl_image* f1, int* range, double gain,
407 FPN_METHOD fpn_method, int, double* mse);
408static double irplib_calculate_total_noise(const cpl_image* pimage);
409
410static cpl_imagelist* irplib_load_fset_wrp(const cpl_frameset *,
411 cpl_type, int whichext);
412static cpl_imagelist * irplib_load_fset_wrp_ext(const cpl_frameset *,
413 cpl_type, int);
414
415static cpl_error_code irplib_table_create_column(cpl_table* ptable,
416 cpl_propertylist* plist);
417static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
418 cpl_propertylist* plist,
419 int row);
420
421static cpl_error_code
422xsh_detmon_pair_extract_next(const cpl_frameset * set,
423 int* index,
424 int* next_element,
425 double* dit_array,
426 /* int * with_equal_dit,
427 int onoff, */
428 cpl_frameset ** pair,
429 double tolerance);
430static cpl_error_code
431xsh_detmon_single_extract_next(const cpl_frameset * set,
432 int* index,
433 int* next_element,
434 double* dit_array,
435 cpl_frameset ** pair);
436
437/*
438 static int frame_get_ndit(const cpl_frame * pframe);
439 static cpl_error_code
440 irplib_frameset_get_ndit(const cpl_frameset * self, int* ndit);
441 */
442static cpl_error_code xsh_detmon_table_fill_invalid(cpl_table* ptable, double code);
443static void xsh_detmon_lg_add_empty_image(cpl_imagelist* imlist, int pos);
444static int xsh_detmon_lg_check_before_gain(const cpl_vector* x, const cpl_vector* y);
445/*---------------------------------------------------------------------------*/
452/*---------------------------------------------------------------------------*/
453static int irplib_pfits_get_ndit(const cpl_propertylist * plist)
454{
455 return cpl_propertylist_get_int(plist,"ESO DET NDIT");
456}
457
458
459
460/*----------------------------------------------------------------------------*/
481/*----------------------------------------------------------------------------*/
482cpl_error_code
483hdrldemo_detector_shotnoise_model(const cpl_image* ima_data, const double gain,
484 const double ron, cpl_image ** ima_errs)
485{
486 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
487 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
488 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
489 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
490
491 *ima_errs = cpl_image_duplicate(ima_data);
492 /* set negative values (= zero measurable electrons) to read out noise */
493 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
494
495 /* err_ADU = sqrt(counts/gain + ron * ron)*/
496
497 cpl_image_divide_scalar(*ima_errs, gain);
498 cpl_image_add_scalar(*ima_errs, ron * ron);
499 cpl_image_power(*ima_errs, 0.5);
500
501 return cpl_error_get_code();
502}
503
504
505
506static cpl_error_code
507xsh_detmon_lg_reduce_set(int i, cpl_frameset * frameset,
508 int nsets,
509 const char * tag_on,
510 const char * tag_off,
511 const char * recipe_name,
512 const char * pipeline_name,
513 const char * pafregexp,
514 const cpl_propertylist * pro_lintbl,
515 const cpl_propertylist * pro_gaintbl,
516 const cpl_propertylist * pro_coeffscube,
517 const cpl_propertylist * pro_bpm,
518 const cpl_propertylist * pro_corr,
519 const cpl_propertylist * pro_diff,
520 const char * package,
521 int (* load_fset)
522 (const cpl_frameset *, cpl_type, cpl_imagelist *),
523 const cpl_boolean opt_nir,
524 const cpl_parameterlist * parlist,
525 cpl_size* selection
526 );
527static double irplib_compute_err(double gain, double ron, double photon_noise);
528/* wrapper function for different cpl versions*/
529static cpl_error_code
530xsh_detmon_lg_dfs_save_imagelist(cpl_frameset * frameset,
531 const cpl_parameterlist * parlist,
532 const cpl_frameset *usedframes,
533 const cpl_imagelist *coeffs,
534 const char *recipe_name,
535 const cpl_propertylist *mypro_coeffscube,
536 const char * package,
537 const char * name_o);
538
539/*--------------------------------------------------------------------------*/
540static void irplib_free(char** pointer){
541
542 if(pointer && *pointer) {
543 cpl_free(*pointer);
544 *pointer=NULL;
545 }
546}
547
548static cpl_error_code
549xsh_detmon_lg_reduce_set(int i, cpl_frameset * frameset, int nsets,
550 const char * tag_on,
551 const char * tag_off,
552 const char * recipe_name,
553 const char * pipeline_name,
554 const char * pafregexp,
555 const cpl_propertylist * pro_lintbl,
556 const cpl_propertylist * pro_gaintbl,
557 const cpl_propertylist * pro_coeffscube,
558 const cpl_propertylist * pro_bpm,
559 const cpl_propertylist * pro_corr,
560 const cpl_propertylist * pro_diff,
561 const char * package,
562 int (* load_fset)
563 (const cpl_frameset *, cpl_type, cpl_imagelist *),
564 const cpl_boolean opt_nir,
565 const cpl_parameterlist * parlist,
566 cpl_size* selection
567 )
568{
569 int j;
570 int nexts = xsh_detmon_lg_config.nb_extensions;
571
572 double* exptime_on = 0;
573 double* exptime_off = 0;
574 int* index_on = 0;
575 int* index_off = 0;
576 cpl_frameset * cur_fset = NULL;
577 cpl_frameset* cur_fset_on = 0;
578 cpl_frameset* cur_fset_off = 0;
579
580 /* Reduce data set nb i */
581 cur_fset =
582 (nsets == 1) ? /* would be better (selection == 0) ? */
583 cpl_frameset_duplicate(frameset) : cpl_frameset_extract(frameset, selection, i);
584
585
586 skip_if(cur_fset == NULL);
587
588 /* Split input frameset into 2 sub-framesets for ON and OFF frames */
589 cur_fset_on = cpl_frameset_new();
590 cur_fset_off = cpl_frameset_new();
591 cpl_msg_info(cpl_func, "Splitting into ON and OFF sub-framesets");
592 skip_if (xsh_detmon_lg_split_onoff(cur_fset,
593 cur_fset_on, cur_fset_off,
594 tag_on, tag_off /*, opt_nir*/));
595 if (cpl_frameset_get_size(cur_fset_on) == 0)
596 {
597 cpl_msg_error(cpl_func, "No lamp frames in input");
598 skip_if(1);
599 }
600
601 if (cpl_frameset_get_size(cur_fset_off) == 0)
602 {
603 cpl_msg_error(cpl_func, "No dark / bias frames in input");
604 skip_if(1);
605 }
606 cpl_msg_info(cpl_func, "found on-frames[%" CPL_SIZE_FORMAT "] off-frames[%" CPL_SIZE_FORMAT "]",cpl_frameset_get_size(cur_fset_on), cpl_frameset_get_size(cur_fset_off));
607 /* Labelise each sub-frameset according to DIT values */
608 /* selection_on = cpl_frameset_labelise(cur_fset_on,
609 xsh_detmon_lg_compare_pairs,
610 &nsets_on);
611
612 skip_if (selection_on == NULL);
613 */
614 exptime_on = cpl_malloc(sizeof(double)*cpl_frameset_get_size(cur_fset_on));
615 exptime_off = cpl_malloc(sizeof(double)*cpl_frameset_get_size(cur_fset_off));
616
617 index_on = cpl_malloc(sizeof(int)*cpl_frameset_get_size(cur_fset_on));
618 index_off = cpl_malloc(sizeof(int)*cpl_frameset_get_size(cur_fset_off));
619 irplib_frameset_sort(cur_fset_on, index_on, exptime_on);
620 irplib_frameset_sort(cur_fset_off, index_off, exptime_off);
621 /* for (j = 0; j < cpl_frameset_get_size(cur_fset_on); j++)
622 {
623 cpl_msg_info(cpl_func, "%d: \t %d \t %f", j , index_on[j], exptime_on[j]);
624 }
625 */
626 /* TODO Check that each ON frame pair has a corresponding OFF frame*/
627
628 /* Test if they have equal nb of labels */
629 /* if (!xsh_detmon_lg_config.collapse) {
630 skip_if(nsets_on != nsets_off);
631 }
632 */
633 skip_if(xsh_detmon_check_order(exptime_on, cpl_frameset_get_size(cur_fset_on), xsh_detmon_lg_config.tolerance, xsh_detmon_lg_config.order));
634
635 if(xsh_detmon_lg_config.exts >= 0)
636 {
637 /*
638 * In the optical domain, the first 2 frames
639 * are used apart from the pairs.
640 */
641
642#if 0
643 if (xsh_detmon_lg_config.lamp_ok) {
644 skip_if(xsh_detmon_opt_lampcr(cur_fset, 0));
645 }
646#endif
647 skip_if(xsh_detmon_lg_core(cur_fset_on, cur_fset_off,
648 index_on,
649 index_off,
650 exptime_on,
651 exptime_off,
653 i,
654 recipe_name, pipeline_name, pafregexp,
655 pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff,
656 package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
657 } else {
658 for(j = 1; j <= nexts; j++) {
659 /*
660 * In the optical domain, the first 2 frames
661 * are used apart from the pairs.
662 */
663
664#if 0
665 if (xsh_detmon_lg_config.lamp_ok) {
666 skip_if(xsh_detmon_opt_lampcr(cur_fset, j));
667 }
668#endif
669
670 skip_if(xsh_detmon_lg_core(cur_fset_on, cur_fset_off,
671 index_on,
672 index_off,
673 exptime_on,
674 exptime_off,
675 j, i, recipe_name, pipeline_name,pafregexp, pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff, package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
676 }
677 }
678 end_skip;
679
680 cpl_frameset_delete(cur_fset);
681 cpl_frameset_delete(cur_fset_on);
682 cpl_frameset_delete(cur_fset_off);
683 cpl_free(index_on);
684 cpl_free(index_off);
685 cpl_free(exptime_on);
686 cpl_free(exptime_off);
687 return cpl_error_get_code();
688}
689
690/*
691 * @brief Reduce linearity and gain in the IR domain
692 * @param parlist List of required parameters
693 * @param frameset Input frameset
694 * @param tag_on Tag to identify the ON frames
695 * @param tag_off Tag to identify the OFF frames
696 * @param recipe_name Name of the recipe calling this function
697 * @param pipeline_name Name of the pipeline calling this function
698 * @param procatg_lintbl PRO.CATG keyword for the Linearity Table
699 * @param procatg_gaintbl PRO.CATG keyword for the Gain Table
700 * @param procatg_coeffscube PRO.CATG keyword for the
701 * Linearity Coefficients' Images
702 * @param procatg_bpm PRO.CATG required for the Bad Pixel Map
703 * @param procatg_corr PRO.CATG required for the Autocorrelation Images
704 * (Intermediate product - only created if required)
705 * @param procatg_diff PRO.CATG required for the Difference Images
706 * (Intermediate Product - only created if required)
707 * @param package PACKAGE (incl. VERSION) required
708 * for the DFS keywords
709 * @param compare Compare function used to classified frameset into
710 * different settings, if any.
711 * @param load_fset Loading function for preprocessing of input
712 frames with special data format (needed for
713 AMBER and MIDI processing)
714
715 * @param opt_nir Boolean parameter to activate/deactivate
716 * OPT-only / IR-only parts of the recipe
717 * @return 0 on success, -1 on fail.
718 * @note: The parlist contains the following parameters:
719 *
720 * @par1 kappa Kappa value used for the kappa-sigma clipping
721 * rejection of bad pixels when computing sigma for
722 * gain calculation
723 * @par2 niter Number of iterations for the kappa-sigma clipping
724 * @par3 threshold_min Minimum threshold of the k-sigma (Not applied)
725 * @par4 threshold_max Maximum threshold of the k-sigma (Not applied)
726 * @par5 llx Region of Interest (Default to the whole area)
727 * @par6 lly Region of Interest (Default to the whole area)
728 * @par7 urx Region of Interest (Default to the whole area)
729 * @par8 ury Region of Interest (Default to the whole area)
730 * @par9 ref_level Reference Level (Not applied)
731 * @par10 threshold Threshold (Not applied)
732 * @par11 intermediate Boolean to activate the production of
733 * Intermediate Products
734 * @par12 autocorr Boolean to activate autocorr method
735 * @par13 collapse Boolean to activate collapse of OFF frames
736 * @par14 rescale Boolean to activate pair rescaling
737 * @par15 m X-Shift of the autocorrelation
738 * @par16 n Y-Shift of the autocorrelation
739 * @par17 llx1 Region of Interest 1 (Only OPT)
740 * @par18 lly1 Region of Interest 1 (Only OPT)
741 * @par19 urx1 Region of Interest 1 (Only OPT)
742 * @par20 ury1 Region of Interest 1 (Only OPT)
743 * @par21 llx2 Region of Interest 2 (Only OPT)
744 * @par22 lly2 Region of Interest 2 (Only OPT)
745 * @par23 urx2 Region of Interest 2 (Only OPT)
746 * @par24 ury2 Region of Interest 2 (Only OPT)
747 * @par25 llx3 Region of Interest 3 (Only OPT)
748 * @par26 lly3 Region of Interest 3 (Only OPT)
749 * @par27 urx3 Region of Interest 3 (Only OPT)
750 * @par28 ury3 Region of Interest 3 (Only OPT)
751 * @par29 llx4 Region of Interest 4 (Only OPT)
752 * @par30 lly4 Region of Interest 4 (Only OPT)
753 * @par31 urx4 Region of Interest 4 (Only OPT)
754 * @par32 ury4 Region of Interest 4 (Only OPT)
755 * @par33 llx5 Region of Interest 5 (Only OPT)
756 * @par34 lly5 Region of Interest 5 (Only OPT)
757 * @par35 urx5 Region of Interest 5 (Only OPT)
758 * @par36 ury5 Region of Interest 5 (Only OPT)
759 * @par37 exts Integer to select extension
760 */
761
762/*--------------------------------------------------------------------------*/
763
764cpl_error_code
765xsh_detmon_lg(cpl_frameset * frameset,
766 const cpl_parameterlist * parlist,
767 const char * tag_on,
768 const char * tag_off,
769 const char * recipe_name,
770 const char * pipeline_name,
771 const char * pafregexp,
772 const cpl_propertylist * pro_lintbl,
773 const cpl_propertylist * pro_gaintbl,
774 const cpl_propertylist * pro_coeffscube,
775 const cpl_propertylist * pro_bpm,
776 const cpl_propertylist * pro_corr,
777 const cpl_propertylist * pro_diff,
778 const char * package,
779 int (* compare) (const cpl_frame *,
780 const cpl_frame *),
781 int (* load_fset) (const cpl_frameset *,
782 cpl_type,
783 cpl_imagelist *),
784 const cpl_boolean opt_nir)
785{
786 cpl_errorstate cleanstate = cpl_errorstate_get();
787 cpl_size nsets;
788 cpl_size * selection = NULL;
789 cpl_frame * first = NULL;
790 cpl_image * reference = NULL;
791
792 /*
793 * Variables used only inside the for() statement.
794 * However, there are declared here to ease
795 * memory management in error case.
796 */
797 cpl_frameset * cur_fset = NULL;
798 cpl_frameset * cur_fset_on = NULL;
799 cpl_frameset * cur_fset_off = 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_on != NULL, CPL_ERROR_NULL_INPUT);
805 cpl_ensure_code(tag_off != NULL, CPL_ERROR_NULL_INPUT);
806 cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
807 cpl_ensure_code(pipeline_name != NULL, CPL_ERROR_NULL_INPUT);
808 cpl_ensure_code(pro_lintbl != NULL, CPL_ERROR_NULL_INPUT);
809 cpl_ensure_code(pro_gaintbl != NULL, CPL_ERROR_NULL_INPUT);
810 cpl_ensure_code(pro_coeffscube != NULL, CPL_ERROR_NULL_INPUT);
811 cpl_ensure_code(pro_bpm != NULL, CPL_ERROR_NULL_INPUT);
812 cpl_ensure_code(pro_corr != NULL, CPL_ERROR_NULL_INPUT);
813 cpl_ensure_code(pro_diff != NULL, CPL_ERROR_NULL_INPUT);
814 cpl_ensure_code(package != NULL, CPL_ERROR_NULL_INPUT);
815
816 cpl_msg_info(cpl_func,"frameset size [%" CPL_SIZE_FORMAT "]", cpl_frameset_get_size(frameset));
817
818
819 skip_if (xsh_detmon_lg_dfs_set_groups(frameset, tag_on, tag_off));
820
821 /*
822 * First check of input consistency in NIR case:
823 * There must be a pair ON and a pair OFF for each DIT.
824 */
825
826 skip_if (xsh_detmon_lg_retrieve_parlist(pipeline_name, recipe_name,
827 parlist, opt_nir));
828
829 /*
830 * Retrieve first image to check some parameters' values and
831 * set default values which refer to the image.
832 */
833
834 first = cpl_frameset_get_position(frameset, 0);
835 irplib_ensure (first != NULL, CPL_ERROR_ILLEGAL_INPUT, "Empty data set! Provide %s and %s input frames",tag_on,tag_off);
836
839
840
841 xsh_detmon_lg_config.nb_extensions = 1;
842 if (xsh_detmon_lg_config.exts < 0) {
843 int i = 1;
844 xsh_detmon_lg_config.nb_extensions = cpl_frame_get_nextensions(first);
845 while (reference == NULL && i <= xsh_detmon_lg_config.nb_extensions) {
846 reference = cpl_image_load(cpl_frame_get_filename(first),
847 CPL_TYPE_FLOAT, 0, i);
848 if (reference == NULL) {
849 cpl_msg_warning(cpl_func, "Extension %d empty, skipping", i);
850 cpl_errorstate_set(cleanstate);
851 }
852 i++;
853 }
854 cpl_errorstate_set(cleanstate);
855 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
856 "No data found in any extension");
857 cpl_msg_info(cpl_func, "Using extension %d as reference", i - 1);
858 } else {
859 if (load_fset != NULL) {
860 cpl_frameset * new = cpl_frameset_new();
861 cpl_imagelist * p = cpl_imagelist_new();
862 cpl_frameset_insert(new, cpl_frame_duplicate(first));
863 (*load_fset)(new, CPL_TYPE_FLOAT, p);
864 reference = cpl_image_duplicate(cpl_imagelist_get(p, 0));
865 cpl_imagelist_delete(p);
866 cpl_frameset_delete(new);
867 } else {
868 cpl_msg_info(cpl_func,"name=%s",cpl_frame_get_filename(first));
869 reference = cpl_image_load(cpl_frame_get_filename(first),
870 CPL_TYPE_FLOAT, 0, xsh_detmon_lg_config.exts);
871 }
872 cpl_errorstate_set(cleanstate);
873 irplib_ensure (reference != NULL, CPL_ERROR_ILLEGAL_INPUT,
874 "No data found in requested extension %d",
876 }
877 skip_if (reference == NULL);
878
879 skip_if (xsh_detmon_lg_check_defaults(reference));
880
881 /* Labelise all input frames */
882
883 /*
884 * After each setting iteration, frameset will be modified (product
885 * frames will have been added), so it is better to duplicate it, keep
886 * it in its original state for the labelise-extract scheme.
887 */
888 if (compare == NULL) {
889 nsets = 1;
890 } else {
891 cpl_msg_info(cpl_func, "Identifying different settings");
892 selection = cpl_frameset_labelise(frameset, compare, &nsets);
893 skip_if (selection == NULL);
894 }
895
896 /* Extract settings and reduce each of them */
897 for(int i = 0; i < nsets; i++)
898 {
899 int fr_size = cpl_frameset_get_size(frameset);
900 int fr_size_new = 0;
901 cpl_msg_info(cpl_func, "Reduce data set nb %d out of %" CPL_SIZE_FORMAT "",
902 i + 1, nsets);
903 skip_if(xsh_detmon_lg_reduce_set(i, frameset, nsets, tag_on, tag_off,
904 recipe_name,
905 pipeline_name,
906 pafregexp,
907 pro_lintbl,
908 pro_gaintbl,
909 pro_coeffscube,
910 pro_bpm,
911 pro_corr,
912 pro_diff,
913 package,
914 load_fset,
915 opt_nir,
916 parlist,
917 selection));
918 fr_size_new = cpl_frameset_get_size(frameset);
919 /* the size of the frameset could be changed during the xsh_detmon_lg_reduce_set call
920 * so the size of the selection array should be adjusted with some fake values,
921 * to avoid reading of the not allocated memory
922 * see DFS08110 for the error description
923 * */
924 if (fr_size_new > fr_size)
925 {
926 selection = cpl_realloc(selection, fr_size_new * sizeof(selection[0]));
927 memset(selection + fr_size, -1, (fr_size_new - fr_size) * sizeof(selection[0]));
928 }
929 }
930
931 end_skip;
932
933 cpl_frameset_delete(cur_fset);
934 cpl_frameset_delete(cur_fset_on);
935 cpl_frameset_delete(cur_fset_off);
936 cpl_free(selection);
937 cpl_image_delete(reference);
938
939 return cpl_error_get_code();
940}
941
942/*---------------------------------------------------------------------------*/
973/*---------------------------------------------------------------------------*/
974
975static cpl_error_code
976xsh_detmon_lg_core(cpl_frameset * cur_fset_on,
977 cpl_frameset * cur_fset_off,
978 int * index_on,
979 int * index_off,
980 double * exptime_on,
981 double * exptime_off,
982 int whichext,
983 int whichset,
984 const char * recipe_name,
985 const char * pipeline_name,
986 const char * pafregexp,
987 const cpl_propertylist * pro_lintbl,
988 const cpl_propertylist * pro_gaintbl,
989 const cpl_propertylist * pro_coeffscube,
990 const cpl_propertylist * pro_bpm,
991 const cpl_propertylist * pro_corr,
992 const cpl_propertylist * pro_diff,
993 const char * package,
994 int (* load_fset) (const cpl_frameset *,
995 cpl_type,
996 cpl_imagelist *),
997 int nsets, cpl_boolean opt_nir,
998 cpl_frameset * frameset, const cpl_parameterlist * parlist,
999 cpl_frameset * cur_fset)
1000{
1001 cpl_table * gain_table = cpl_table_new(
1002 cpl_frameset_get_size(cur_fset_on) / 2);
1003 cpl_table * linear_table = cpl_table_new(
1004 cpl_frameset_get_size(cur_fset_on) / 2);
1005 cpl_imagelist * coeffs = NULL;
1006 cpl_image * bpm = NULL;
1007 cpl_imagelist * autocorr_images = NULL;
1008 cpl_imagelist * diff_flats = NULL;
1009 cpl_propertylist * gaint_qclist = NULL;
1010 cpl_propertylist * lint_qclist = NULL;
1011 cpl_propertylist * linc_qclist = NULL;
1012 cpl_propertylist * bpm_qclist = NULL;
1013
1014 int next_index_on = 0;
1015 int next_index_off = 0;
1016
1017 /* Reduce extension nb i */
1018 cpl_msg_info(cpl_func, "Reduce extension nb %d ", whichext);
1019
1020 /* FIXME: All other memory objects in use should be
1021 initialised here (except coeffs which can not be) */
1022 if (xsh_detmon_lg_config.intermediate) {
1023 autocorr_images = cpl_imagelist_new();
1024 diff_flats = cpl_imagelist_new();
1025 }
1026
1027 gaint_qclist = cpl_propertylist_new();
1028 lint_qclist = cpl_propertylist_new();
1029 linc_qclist = cpl_propertylist_new();
1030 bpm_qclist = cpl_propertylist_new();
1031
1032 /* Reduction done here */
1033 cpl_msg_info(cpl_func, "Starting data reduction");
1034 if (xsh_detmon_lg_reduce(cur_fset_on, cur_fset_off,
1035 index_on, index_off, exptime_on, exptime_off,
1036 &next_index_on, &next_index_off,
1037 &coeffs, gain_table,
1038 linear_table, &bpm, autocorr_images,
1039 diff_flats, gaint_qclist, lint_qclist,
1040 linc_qclist, bpm_qclist, load_fset,
1041 opt_nir, whichext) == CPL_ERROR_CONTINUE) {
1042 cpl_msg_info(cpl_func, "Empty extension %d", whichext);
1043 }
1044 if(cpl_table_has_column(linear_table,"ESO DET WIN1 UIT1") ) {
1045 cpl_table_name_column(linear_table, "ESO DET WIN1 UIT1","ESO_DET_WIN1_UIT1" );
1046 }
1047 if(cpl_table_has_column(linear_table,"ESO DET WIN1 UIT1") ) {
1048 cpl_table_name_column(gain_table, "ESO DET WIN1 UIT1","ESO_DET_WIN1_UIT1" );
1049 }
1050 /* Save the products for each setting */
1051 cpl_msg_info(cpl_func, "Saving the products");
1052 if (nsets == 1) {
1053 skip_if(
1054 xsh_detmon_lg_save(parlist, frameset, recipe_name,
1055 pipeline_name, pafregexp,
1056 pro_lintbl, pro_gaintbl,
1057 pro_coeffscube, pro_bpm,
1058 pro_corr, pro_diff, package,
1059 coeffs, gain_table, linear_table,
1060 bpm, autocorr_images, diff_flats,
1061 gaint_qclist, lint_qclist, linc_qclist,
1062 bpm_qclist, 0, 0, cur_fset, whichext));
1063 } else {
1064 skip_if(
1065 xsh_detmon_lg_save(parlist, frameset, recipe_name,
1066 pipeline_name, pafregexp,
1067 pro_lintbl, pro_gaintbl,
1068 pro_coeffscube, pro_bpm,
1069 pro_corr, pro_diff, package,
1070 coeffs, gain_table, linear_table,
1071 bpm, autocorr_images, diff_flats,
1072 gaint_qclist, lint_qclist, linc_qclist,
1073 bpm_qclist, 1, whichset+ 1, cur_fset,
1074 whichext));
1075 }
1076
1077 end_skip;
1078
1079 /* Free for each extension */
1080
1081 cpl_table_delete(gain_table);
1082 cpl_table_delete(linear_table);
1083 cpl_imagelist_delete(coeffs);
1084 cpl_propertylist_delete(gaint_qclist);
1085 cpl_propertylist_delete(lint_qclist);
1086 cpl_propertylist_delete(linc_qclist);
1087 if(bpm_qclist != NULL) cpl_propertylist_delete(bpm_qclist);
1088 cpl_image_delete(bpm);
1089 cpl_imagelist_delete(autocorr_images);
1090 cpl_imagelist_delete(diff_flats);
1091
1092 return cpl_error_get_code();
1093}
1094
1095
1096/*--------------------------------------------------------------------------*/
1097
1098/*
1099 * @brief Correlate two images with a given range of shifts
1100 * @param image1 Input image
1101 * @param image2 Input image
1102 * @param m Shift to apply on the x-axis
1103 * @param n Shift to apply on the y-axis
1104 * @return An image of size 2m+1 by 2n+1. Each pixel value
1105 * corresponds to the correlation of shift the position
1106 * of the pixel. Pixel in the centre (m+1, n+1),
1107 * corresponds to shift (0,0). Pixels to the left and
1108 * down correspond to negative shifts.
1109 *
1110 * @note At this moment, this function only accepts images to
1111 * have both the same size.
1112 */
1113
1114/*--------------------------------------------------------------------------*/
1115
1116cpl_image *
1117xsh_detmon_image_correlate(const cpl_image * image1,
1118 const cpl_image * image2,
1119 const int m, const int n)
1120{
1121 cpl_image *image1_padded = NULL;
1122 cpl_image *image2_padded = NULL;
1123 int nx, ny;
1124 int nx2, ny2;
1125
1126 cpl_image *corr_image_window = NULL;
1127
1128 cpl_image* image_ri1 = NULL;
1129 cpl_image* image_ri2 = NULL;
1130 cpl_error_code err = CPL_ERROR_NONE;
1131
1132 /* Test the entries */
1133 cpl_ensure(image1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1134 cpl_ensure(image2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1135
1136 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1137 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1138
1139 nx = cpl_image_get_size_x(image1);
1140 ny = cpl_image_get_size_y(image1);
1141
1142 nx2 = cpl_image_get_size_x(image2);
1143 ny2 = cpl_image_get_size_y(image2);
1144
1145 /* At this moment, the images must be of the same size */
1146 cpl_ensure(nx == nx2 && ny == ny2, CPL_ERROR_ILLEGAL_INPUT, NULL);
1147
1148 /* Pad the images with zeroes to avoid periodical effects of DFT */
1149 image1_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1150 cpl_image_copy(image1_padded, image1, m + 1, n + 1);
1151
1152 image2_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
1153 cpl_image_copy(image2_padded, image2, m + 1, n + 1);
1154
1155 /*New dimensions of the padded images */
1156 nx = nx + 2 * m;
1157 ny = ny + 2 * n;
1158
1159 image_ri1 = cpl_image_new(nx, ny, CPL_TYPE_FLOAT_COMPLEX);
1160 image_ri2 = cpl_image_new(nx, ny , CPL_TYPE_FLOAT_COMPLEX);
1161 /* Actually perform the FFT */
1162 cpl_fft_image(image_ri1, image1_padded, CPL_FFT_FORWARD);
1163 cpl_fft_image(image_ri2, image2_padded, CPL_FFT_FORWARD);
1164 err = cpl_error_get_code();
1165 cpl_image_delete(image1_padded);
1166 image1_padded = NULL;
1167 cpl_image_delete(image2_padded);
1168 image2_padded = NULL;
1169 if (err == CPL_ERROR_NONE)
1170 {
1171 /* Cleanup resources */
1172 cpl_image * corr_image = NULL;
1173 cpl_image * reorganised= NULL;
1174 cpl_image * image_ri_inv = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1175 cpl_image * image_in_inv = cpl_image_new(nx, ny,
1176 CPL_TYPE_FLOAT_COMPLEX);
1177 int i,j;
1178
1179 for (i = 1; i <= nx; i++)
1180 {
1181 for (j = 1; j <= ny; j++)
1182 {
1183 int rej = 0;
1184 double complex value1, value2, value;
1185 value1 = cpl_image_get_complex(image_ri1, i, j, &rej);
1186 value2 = cpl_image_get_complex(image_ri2, i, j, &rej);;
1187 value = conj(value1) * value2;
1188 cpl_image_set_complex(image_in_inv, i, j, value);
1189 }
1190 }
1191 cpl_image_delete(image_ri1);
1192 image_ri1 = NULL;
1193 cpl_image_delete(image_ri2);
1194 image_ri2 = NULL;
1195
1196 err = cpl_error_get_code();
1197 if (err == CPL_ERROR_NONE)
1198 {
1199
1200 /* Actually perform the FFT */
1201 cpl_fft_image(image_ri_inv, image_in_inv,CPL_FFT_BACKWARD);
1202 cpl_image_delete(image_in_inv);
1203
1204 /* Get the module of the inversed signal */
1205 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1206 for (i = 1; i <= nx; i++)
1207 {
1208 for (j = 1; j <= ny; j++)
1209 {
1210 int rej = 0;
1211 double value =0;
1212 value = cpl_image_get(image_ri_inv, i, j, &rej);
1213 cpl_image_set(corr_image, i, j, value);
1214 }
1215 }
1216 cpl_image_delete(image_ri_inv);
1217 err = cpl_error_get_code();
1218 if (err == CPL_ERROR_NONE)
1219 {
1220 /* Reorganise the pixels to the output */
1221 cpl_image * image =
1222 cpl_image_extract(corr_image, nx / 2 + 1, 1, nx, ny);
1223 reorganised = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1224
1225 cpl_image_copy(reorganised, image, 1, 1);
1226 cpl_image_delete(image);
1227 image = cpl_image_extract(corr_image, 1, 1, nx / 2, ny);
1228 cpl_image_copy(reorganised, image, nx / 2 + 1, 1);
1229 cpl_image_delete(image);
1230
1231 cpl_image_delete(corr_image);
1232
1233 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1234 image = cpl_image_extract(reorganised, 1, ny / 2 + 1, nx, ny);
1235 cpl_image_copy(corr_image, image, 1, 1);
1236 cpl_image_delete(image);
1237
1238 image = cpl_image_extract(reorganised, 1, 1, nx, ny / 2);
1239 cpl_image_copy(corr_image, image, 1, ny / 2 + 1);
1240 cpl_image_delete(image);
1241 /* Extract a window with the desired shifts */
1242 corr_image_window = cpl_image_extract(corr_image,
1243 nx / 2 + 1 - m,
1244 ny / 2 + 1 - n,
1245 nx / 2 + 1 + m, ny / 2 + 1 + n);
1246 }
1247 /* Free and return */
1248
1249 }
1250 cpl_image_delete(reorganised);
1251 cpl_image_delete(corr_image);
1252
1253 if(cpl_image_divide_scalar(corr_image_window,
1254 cpl_image_get_max(corr_image_window))) {
1255 cpl_image_delete(corr_image_window);
1256 return NULL;
1257 }
1258 }
1259 cpl_image_delete (image_ri1);
1260 cpl_image_delete (image_ri2);
1261 cpl_image_delete (image1_padded);
1262 cpl_image_delete (image2_padded);
1263 return corr_image_window;
1264}
1265
1266
1267
1268/*--------------------------------------------------------------------------*/
1269
1270/*
1271 * @brief Autocorrelate an image with a given range of shifts, using
1272 * cpl_image_fft()
1273 * @param input2 Input image
1274 * @param m Shift to apply on the x-axis
1275 * @param n Shift to apply on the y-axis
1276 * @return An image of size 2m+1 by 2n+1. Each pixel value
1277 * corresponds to the correlation of shift the position
1278 * of the pixel. Pixel in the centre (m+1, n+1),
1279 * corresponds to shift (0,0). Pixels to the left and
1280 * down correspond to negative shifts.
1281 */
1282
1283/*--------------------------------------------------------------------------*/
1284
1285cpl_image *
1286xsh_detmon_autocorrelate(const cpl_image * input2, const int m,
1287 const int n)
1288{
1289 cpl_image *im_re = NULL;
1290 cpl_image *im_im = NULL;
1291 int nx, ny;
1292 cpl_image *ifft_re = NULL;
1293 cpl_image *ifft_im = NULL;
1294 cpl_image *autocorr = NULL;
1295 cpl_image *autocorr_norm_double = NULL;
1296 cpl_image *autocorr_norm = NULL;
1297 cpl_image *reorganised = NULL;
1298 cpl_image *image = NULL;
1299 int p;
1300 cpl_error_code error;
1301 cpl_image *input;
1302
1303 cpl_ensure(input2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
1304
1305 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
1306 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
1307
1308 nx = cpl_image_get_size_x(input2) + 2 * m;
1309 ny = cpl_image_get_size_y(input2) + 2 * n;
1310
1311 p = 128;
1312 while(nx > p || ny > p) {
1313 p *= 2;
1314 }
1315
1316 input = cpl_image_cast(input2, CPL_TYPE_DOUBLE);
1317
1318 im_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1319 error = cpl_image_copy(im_re, input, 1, 1);
1320 cpl_image_delete(input);
1321
1322 cpl_ensure(!error, error, NULL);
1323
1324 im_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1325
1326 error = cpl_image_fft(im_re, im_im, CPL_FFT_DEFAULT);
1327 cpl_ensure(!error, error, NULL);
1328
1329 ifft_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1330 error = cpl_image_power(im_re, 2);
1331 cpl_ensure(!error, error, NULL);
1332
1333 error = cpl_image_add(ifft_re, im_re);
1334 cpl_ensure(!error, error, NULL);
1335
1336 cpl_image_delete(im_re);
1337
1338 error = cpl_image_power(im_im, 2);
1339 cpl_ensure(!error, error, NULL);
1340
1341 error = cpl_image_add(ifft_re, im_im);
1342 cpl_ensure(!error, error, NULL);
1343
1344 cpl_image_delete(im_im);
1345
1346 ifft_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1347
1348 error = cpl_image_fft(ifft_re, ifft_im, CPL_FFT_INVERSE);
1349 cpl_ensure(!error, error, NULL);
1350
1351 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1352
1353 error = cpl_image_power(ifft_re, 2);
1354 cpl_ensure(!error, error, NULL);
1355
1356 error = cpl_image_add(autocorr, ifft_re);
1357 cpl_ensure(!error, error, NULL);
1358
1359 cpl_image_delete(ifft_re);
1360
1361 error = cpl_image_power(ifft_im, 2);
1362 cpl_ensure(!error, error, NULL);
1363
1364 error = cpl_image_add(autocorr, ifft_im);
1365 cpl_ensure(!error, error, NULL);
1366
1367 cpl_image_delete(ifft_im);
1368
1369 /* Reorganise the pixels to the output */
1370 reorganised = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1371
1372 image = cpl_image_extract(autocorr, p / 2 + 1, 1, p, p);
1373 cpl_image_copy(reorganised, image, 1, 1);
1374 cpl_image_delete(image);
1375
1376 image = cpl_image_extract(autocorr, 1, 1, p / 2, p);
1377 cpl_image_copy(reorganised, image, p / 2 + 1, 1);
1378 cpl_image_delete(image);
1379
1380 cpl_image_delete(autocorr);
1381
1382 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
1383
1384 image = cpl_image_extract(reorganised, 1, p / 2 + 1, p, p);
1385 cpl_image_copy(autocorr, image, 1, 1);
1386 cpl_image_delete(image);
1387
1388 image = cpl_image_extract(reorganised, 1, 1, p, p / 2);
1389 cpl_image_copy(autocorr, image, 1, p / 2 + 1);
1390 cpl_image_delete(image);
1391
1392 cpl_image_delete(reorganised);
1393
1394 autocorr_norm_double =
1395 cpl_image_extract(autocorr, p / 2 + 1 - m, p / 2 + 1 - n,
1396 p / 2 + 1 + m, p / 2 + 1 + n);
1397
1398 cpl_image_delete(autocorr);
1399
1400 if(cpl_image_divide_scalar(autocorr_norm_double,
1401 cpl_image_get_max(autocorr_norm_double))) {
1402 cpl_image_delete(autocorr_norm_double);
1403 cpl_ensure(0, cpl_error_get_code(), NULL);
1404 }
1405
1406
1407 autocorr_norm = cpl_image_cast(autocorr_norm_double, CPL_TYPE_FLOAT);
1408 cpl_image_delete(autocorr_norm_double);
1409
1410 return autocorr_norm;
1411}
1412
1413/*---------------------------------------------------------------------------*/
1424/*---------------------------------------------------------------------------*/
1425cpl_error_code
1426xsh_detmon_lg_fill_parlist_nir_default(cpl_parameterlist * parlist,
1427 const char *recipe_name,
1428 const char *pipeline_name)
1429{
1430 const cpl_error_code error =
1431 xsh_detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1432 "PTC", /* --method */
1433 3, /* --order */
1434 3., /* --kappa */
1435 5, /* --niter */
1436 -1, /* --llx */
1437 -1, /* --lly */
1438 -1, /* --urx */
1439 -1, /* --ury */
1440 10000, /* --ref_level */
1441 "CPL_FALSE", /* --intermediate */
1442 "CPL_FALSE", /* --autocorr */
1443 "CPL_FALSE", /* --collapse */
1444 "CPL_TRUE", /* --rescale */
1445 "CPL_TRUE",/* --pix2pix */
1446 "CPL_FALSE", /* --bpmbin */
1447 -1, /* --filter */
1448 26, /* --m */
1449 26, /* --n */
1450 1e-3, /* --tolerance */
1451 "CPL_FALSE", /* --pafgen */
1452 recipe_name, /* --pafname */
1453 -1, /* --llx1 */
1454 -1, /* --lly1 */
1455 -1, /* --urx1 */
1456 -1, /* --ury1 */
1457 -1, /* --llx2 */
1458 -1, /* --lly2 */
1459 -1, /* --urx2 */
1460 -1, /* --ury2 */
1461 -1, /* --llx3 */
1462 -1, /* --lly3 */
1463 -1, /* --urx3 */
1464 -1, /* --ury3 */
1465 -1, /* --llx4 */
1466 -1, /* --lly4 */
1467 -1, /* --urx4 */
1468 -1, /* --ury4 */
1469 -1, /* --llx5 */
1470 -1, /* --lly5 */
1471 -1, /* --urx5 */
1472 -1, /* --ury5 */
1473 0, /* --exts */
1474 NIR); /* This is to specify OPT params */
1475
1476
1477 cpl_ensure_code(!error, error);
1478
1479 return cpl_error_get_code();
1480}
1481
1482/*---------------------------------------------------------------------------*/
1493/*---------------------------------------------------------------------------*/
1494cpl_error_code
1495xsh_detmon_lg_fill_parlist_opt_default(cpl_parameterlist * parlist,
1496 const char *recipe_name,
1497 const char *pipeline_name)
1498{
1499 const cpl_error_code error =
1500 xsh_detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
1501 "PTC", /* --method */
1502 3, /* --order */
1503 3., /* --kappa */
1504 5, /* --niter */
1505 -1, /* --llx */
1506 -1, /* --lly */
1507 -1, /* --urx */
1508 -1, /* --ury */
1509 10000, /* --ref_level */
1510 "CPL_FALSE", /* --intermediate */
1511 "CPL_FALSE", /* --autocorr */
1512 "CPL_TRUE", /* --collapse */
1513 "CPL_TRUE", /* --rescale */
1514 "CPL_FALSE", /* --pix2pix */
1515 "CPL_FALSE", /* --bpmbin */
1516 -1, /* --filter */
1517 26, /* --m */
1518 26, /* --n */
1519 1e-3, /* --tolerance */
1520 "CPL_FALSE", /* --pafgen */
1521 recipe_name, /* --pafname */
1522 -1, /* --llx1 */
1523 -1, /* --lly1 */
1524 -1, /* --urx1 */
1525 -1, /* --ury1 */
1526 -1, /* --llx2 */
1527 -1, /* --lly2 */
1528 -1, /* --urx2 */
1529 -1, /* --ury2 */
1530 -1, /* --llx3 */
1531 -1, /* --lly3 */
1532 -1, /* --urx3 */
1533 -1, /* --ury3 */
1534 -1, /* --llx4 */
1535 -1, /* --lly4 */
1536 -1, /* --urx4 */
1537 -1, /* --ury4 */
1538 -1, /* --llx5 */
1539 -1, /* --lly5 */
1540 -1, /* --urx5 */
1541 -1, /* --ury5 */
1542 0, /* --exts */
1543 OPT); /* This is to specify OPT params */
1544
1545 cpl_ensure_code(!error, error);
1546
1547 return cpl_error_get_code();
1548}
1549
1550cpl_error_code
1551xsh_detmon_lg_fill_parlist_default_mr(cpl_parameterlist * parlist,
1552 const char *recipe_name,
1553 const char *pipeline_name)
1554{
1555 char * group_name = cpl_sprintf("%s.%s", pipeline_name, recipe_name);
1556 char * par_name = cpl_sprintf("%s.%s", group_name, "regions-file");
1557 cpl_parameter * p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1558 "File containing regions, "
1559 "four comma separated points "
1560 "per line",
1561 group_name, "");
1562 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "regions-file");
1563 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1564 cpl_parameterlist_append(parlist, p);
1565 cpl_free(par_name);
1566 cpl_free(group_name);
1567
1568 group_name = cpl_sprintf("%s.%s", pipeline_name, recipe_name);
1569 par_name = cpl_sprintf("%s.%s", group_name, "regions");
1570 p = cpl_parameter_new_value(par_name, CPL_TYPE_STRING,
1571 "Colon separated list of regions, four "
1572 "points each, comma separated: "
1573 "llx,lly,urx,ury:llx,...",
1574 group_name, "");
1575 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "regions");
1576 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
1577 cpl_parameterlist_append(parlist, p);
1578 cpl_free(par_name);
1579 cpl_free(group_name);
1580
1581 return cpl_error_get_code();
1582}
1583
1584cpl_error_code
1586 const char *recipe_name,
1587 const char *pipeline_name)
1588{
1589 xsh_detmon_lg_fill_parlist_opt_default(parlist, recipe_name, pipeline_name);
1590 xsh_detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1591 return cpl_error_get_code();
1592}
1593
1594cpl_error_code
1596 const char *recipe_name,
1597 const char *pipeline_name)
1598{
1599 xsh_detmon_lg_fill_parlist_nir_default(parlist, recipe_name, pipeline_name);
1600 xsh_detmon_lg_fill_parlist_default_mr(parlist, recipe_name, pipeline_name);
1601
1602 return cpl_error_get_code();
1603}
1604
1605
1606/*---------------------------------------------------------------------------*/
1660/*---------------------------------------------------------------------------*/
1661cpl_error_code
1662xsh_detmon_lg_fill_parlist(cpl_parameterlist * parlist,
1663 const char *recipe_name, const char *pipeline_name,
1664 const char *method,
1665 int order,
1666 double kappa,
1667 int niter,
1668 int llx,
1669 int lly,
1670 int urx,
1671 int ury,
1672 int ref_level,
1673 const char *intermediate,
1674 const char *autocorr,
1675 const char *collapse,
1676 const char *rescale,
1677 const char *pix2pix,
1678 const char *bpmbin,
1679 int filter,
1680 int m,
1681 int n,
1682 double tolerance,
1683 const char *pafgen,
1684 const char * pafname,
1685 int llx1,
1686 int lly1,
1687 int urx1,
1688 int ury1,
1689 int llx2,
1690 int lly2,
1691 int urx2,
1692 int ury2,
1693 int llx3,
1694 int lly3,
1695 int urx3,
1696 int ury3,
1697 int llx4,
1698 int lly4,
1699 int urx4,
1700 int ury4,
1701 int llx5, int lly5, int urx5, int ury5, int exts,
1702 cpl_boolean opt_nir)
1703{
1704 const cpl_error_code error =
1705 xsh_detmon_fill_parlist(parlist, recipe_name, pipeline_name, 26,
1706 "method",
1707 "Method to be used when computing GAIN. Methods appliable: <PTC | MED>. By default PTC method will be applied.",
1708 "CPL_TYPE_STRING", method,
1709
1710 "order",
1711 "Polynomial order for the fit (Linearity)",
1712 "CPL_TYPE_INT", order,
1713 "kappa",
1714 "Kappa value for the kappa-sigma clipping (Gain)",
1715 "CPL_TYPE_DOUBLE", kappa,
1716 "niter",
1717 "Number of iterations to compute rms (Gain)",
1718 "CPL_TYPE_INT", niter,
1719 "llx",
1720 "x coordinate of the lower-left "
1721 "point of the region of interest. If not modified, default value will be 1.",
1722 "CPL_TYPE_INT", llx,
1723 "lly",
1724 "y coordinate of the lower-left "
1725 "point of the region of interest. If not modified, default value will be 1.",
1726 "CPL_TYPE_INT", lly,
1727 "urx",
1728 "x coordinate of the upper-right "
1729 "point of the region of interest. If not modified, default value will be X dimension of the input image.",
1730 "CPL_TYPE_INT", urx,
1731 "ury",
1732 "y coordinate of the upper-right "
1733 "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
1734 "CPL_TYPE_INT", ury,
1735 "ref_level",
1736 "User reference level",
1737 "CPL_TYPE_INT", ref_level,
1738 "intermediate",
1739 "De-/Activate intermediate products",
1740 "CPL_TYPE_BOOL", intermediate,
1741
1742 "autocorr",
1743 "De-/Activate the autocorr option",
1744 "CPL_TYPE_BOOL", autocorr,
1745
1746 "collapse",
1747 "De-/Activate the collapse option",
1748 "CPL_TYPE_BOOL", collapse,
1749 "rescale",
1750 "De-/Activate the image rescale option",
1751 "CPL_TYPE_BOOL", rescale,
1752 "pix2pix",
1753 "De-/Activate the computation with pixel to pixel accuracy",
1754 "CPL_TYPE_BOOL", pix2pix,
1755 "bpmbin",
1756 "De-/Activate the binary bpm option",
1757 "CPL_TYPE_BOOL", bpmbin,
1758 "m",
1759 "Maximum x-shift for the autocorr",
1760 "CPL_TYPE_INT", m,
1761 "filter",
1762 "Upper limit of Median flux to be filtered",
1763 "CPL_TYPE_INT", filter,
1764 "n",
1765 "Maximum y-shift for the autocorr",
1766 "CPL_TYPE_INT", n,
1767 "tolerance",
1768 "Tolerance for pair discrimination",
1769 "CPL_TYPE_DOUBLE", tolerance,
1770
1771 "pafgen",
1772 "Generate PAF file",
1773 "CPL_TYPE_BOOL", pafgen,
1774 "pafname",
1775 "Specific name for PAF file",
1776 "CPL_TYPE_STRING", pafname,
1777
1778
1779 "exts",
1780 "Activate the multi-exts option. Choose -1 to process all extensions. Choose an extension number"
1781 " to process the appropriate extension.",
1782 "CPL_TYPE_INT", exts,
1783
1784 "fpn_method",
1785 "Method for computing Fixed Pattern Noise (SMOOTH or HISTOGRAM)",
1786 "CPL_TYPE_STRING", "HISTOGRAM",
1787
1788 "fpn_smooth",
1789 "template size in pixels for smoothing during FPN computation (only for SMOOTH method)",
1790 "CPL_TYPE_INT", 13,
1791
1792 "saturation_limit",
1793 "all frames with mean saturation above the limit would not be used in linearity calculation",
1794 "CPL_TYPE_DOUBLE", 65535.0,
1795
1796 "gain_threshold",
1797 "all frames with mean flux above the threshold would not be used in gain calculation",
1798 "CPL_TYPE_DOUBLE", 65535.0
1799
1800 );
1801 xsh_detmon_fill_parlist(parlist, recipe_name, pipeline_name, 1,
1802 "coeffs_cube_split",
1803 "if TRUE, the recipe writes as many "
1804 "COEFFS_CUBE_Pi (i=0..order) as the value of "
1805 "the order parameter in a separate file",
1806 "CPL_TYPE_BOOL", "CPL_FALSE");
1807 /* OPT specific parameters */
1808 if(opt_nir == FALSE) {
1809 const cpl_error_code erroropt =
1810 xsh_detmon_fill_parlist(parlist, recipe_name, pipeline_name, 20,
1811 "llx1",
1812 "x coord of the lower-left point of the first "
1813 "field used for contamination measurement. If not modified, default value will be 1.",
1814 "CPL_TYPE_INT", llx1,
1815 "lly1",
1816 "y coord of the lower-left point of the first "
1817 "field used for contamination measurement. If not modified, default value will be 1.",
1818 "CPL_TYPE_INT", lly1,
1819 "urx1",
1820 "x coord of the upper-right point of the first "
1821 "field used for contamination measurement. If not modified, default value will be X dimension of the input image.",
1822 "CPL_TYPE_INT", urx1,
1823 "ury1",
1824 "y coord of the upper-right point of the first "
1825 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1826 "CPL_TYPE_INT", ury1,
1827 "llx2",
1828 "x coord of the lower-left point of the second "
1829 "field used for contamination measurement. If not modified, default value will be 1.",
1830 "CPL_TYPE_INT", llx2,
1831 "lly2",
1832 "y coord of the lower-left point of the second "
1833 "field used for contamination measurement. If not modified, default value will be 1.",
1834 "CPL_TYPE_INT", lly2,
1835 "urx2",
1836 "x coord of the upper-right point of the second "
1837 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1838 "CPL_TYPE_INT", urx2,
1839 "ury2",
1840 "y coord of the upper-right point of the second "
1841 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1842 "CPL_TYPE_INT", ury2,
1843 "llx3",
1844 "x coord of the lower-left point of the third "
1845 "field used for contamination measurement. If not modified, default value will be 1.",
1846 "CPL_TYPE_INT", llx3,
1847 "lly3",
1848 "y coord of the lower-left point of the third "
1849 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1850 "CPL_TYPE_INT", lly3,
1851 "urx3",
1852 "x coord of the upper-right point of the third "
1853 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1854 "CPL_TYPE_INT", urx3,
1855 "ury3",
1856 "y coord of the upper-right point of the third "
1857 "field used for contamination measurement. If not modified, default value will be Y dimension of the image.",
1858 "CPL_TYPE_INT", ury3,
1859 "llx4",
1860 "x coord of the lower-left point of the fourth "
1861 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
1862 "CPL_TYPE_INT", llx4,
1863 "lly4",
1864 "y coord of the lower-left point of the fourth "
1865 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
1866 "CPL_TYPE_INT", lly4,
1867 "urx4",
1868 "x coord of the upper-right point of the fourth "
1869 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1870 "CPL_TYPE_INT", urx4,
1871 "ury4",
1872 "y coord of the upper-right point of the fourth "
1873 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
1874 "CPL_TYPE_INT", ury4,
1875 "llx5",
1876 "x coord of the lower-left point of the fifth "
1877 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
1878 "CPL_TYPE_INT", llx5,
1879 "lly5",
1880 "y coord of the lower-left point of the fifth "
1881 "field used for contamination measurement. If not modified, default value will be 1.",
1882 "CPL_TYPE_INT", lly5,
1883 "urx5",
1884 "x coord of the upper-right point of the fifth "
1885 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
1886 "CPL_TYPE_INT", urx5,
1887
1888 "ury5",
1889 "y coord of the upper-right point of the fifth "
1890 "field used for contamination measurement. If not modified, default value will be half of Y dimension of the input image.",
1891 "CPL_TYPE_INT", ury5);
1892
1893
1894 cpl_ensure_code(!erroropt, erroropt);
1895 }
1896
1897 cpl_ensure_code(!error, error);
1898
1899 return cpl_error_get_code();
1900}
1901
1902/*---------------------------------------------------------------------------*/
1911/*---------------------------------------------------------------------------*/
1912static cpl_error_code
1913xsh_detmon_lg_retrieve_parlist(const char * pipeline_name,
1914 const char * recipe_name,
1915 const cpl_parameterlist * parlist,
1916 cpl_boolean opt_nir)
1917{
1918
1919 char * par_name;
1920 cpl_parameter * par;
1921
1922 /* --method */
1923 par_name = cpl_sprintf("%s.%s.method", pipeline_name, recipe_name);
1924 assert(par_name != NULL);
1925 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1926 xsh_detmon_lg_config.method = cpl_parameter_get_string(par);
1927 cpl_free(par_name);
1928
1929 /* --order */
1930 xsh_detmon_lg_config.order =
1931 xsh_detmon_retrieve_par_int("order", pipeline_name, recipe_name,
1932 parlist);
1933
1934 /* --kappa */
1935 xsh_detmon_lg_config.kappa =
1936 xsh_detmon_retrieve_par_double("kappa", pipeline_name, recipe_name,
1937 parlist);
1938
1939 /* --niter */
1940 xsh_detmon_lg_config.niter =
1941 xsh_detmon_retrieve_par_int("niter", pipeline_name, recipe_name,
1942 parlist);
1943
1944 /* --llx */
1946 xsh_detmon_retrieve_par_int("llx", pipeline_name, recipe_name,
1947 parlist);
1948
1949 /* --lly */
1951 xsh_detmon_retrieve_par_int("lly", pipeline_name, recipe_name,
1952 parlist);
1953
1954 /* --urx */
1956 xsh_detmon_retrieve_par_int("urx", pipeline_name, recipe_name,
1957 parlist);
1958
1959 /* --ury */
1961 xsh_detmon_retrieve_par_int("ury", pipeline_name, recipe_name,
1962 parlist);
1963
1964 /* --ref_level */
1965 xsh_detmon_lg_config.ref_level =
1966 xsh_detmon_retrieve_par_int("ref_level", pipeline_name, recipe_name,
1967 parlist);
1968
1969 /* --intermediate */
1970 par_name =
1971 cpl_sprintf("%s.%s.intermediate", pipeline_name, recipe_name);
1972 assert(par_name != NULL);
1973 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1974 xsh_detmon_lg_config.intermediate = cpl_parameter_get_bool(par);
1975 cpl_free(par_name);
1976
1977 /* --autocorr */
1978 par_name = cpl_sprintf("%s.%s.autocorr", pipeline_name, recipe_name);
1979 assert(par_name != NULL);
1980 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1981 xsh_detmon_lg_config.autocorr = cpl_parameter_get_bool(par);
1982 cpl_free(par_name);
1983
1984 /* --coeffs_cube_split */
1985 par_name = cpl_sprintf("%s.%s.coeffs_cube_split", pipeline_name, recipe_name);
1986 assert(par_name != NULL);
1987 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1988 xsh_detmon_lg_config.split_coeffs = cpl_parameter_get_bool(par);
1989 cpl_free(par_name);
1990
1991 /* --collapse */
1992 par_name = cpl_sprintf("%s.%s.collapse", pipeline_name, recipe_name);
1993 assert(par_name != NULL);
1994 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
1995 xsh_detmon_lg_config.collapse = cpl_parameter_get_bool(par);
1996 cpl_free(par_name);
1997
1998 /* --rescale */
1999 par_name = cpl_sprintf("%s.%s.rescale", pipeline_name, recipe_name);
2000 assert(par_name != NULL);
2001 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2002 xsh_detmon_lg_config.rescale = cpl_parameter_get_bool(par);
2003 cpl_free(par_name);
2004
2005 /* --pix2pix */
2006 par_name = cpl_sprintf("%s.%s.pix2pix", pipeline_name, recipe_name);
2007 assert(par_name != NULL);
2008 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2009 xsh_detmon_lg_config.pix2pix = cpl_parameter_get_bool(par);
2010 cpl_free(par_name);
2011
2012 /* --bpmbin */
2013 par_name = cpl_sprintf("%s.%s.bpmbin", pipeline_name, recipe_name);
2014 assert(par_name != NULL);
2015 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2016 xsh_detmon_lg_config.bpmbin = cpl_parameter_get_bool(par);
2017 cpl_free(par_name);
2018
2019 /* --filter */
2020 xsh_detmon_lg_config.filter =
2021 xsh_detmon_retrieve_par_int("filter", pipeline_name,
2022 recipe_name, parlist);
2023
2024 /* --m */
2026 xsh_detmon_retrieve_par_int("m", pipeline_name, recipe_name, parlist);
2027
2028 /* --n */
2030 xsh_detmon_retrieve_par_int("n", pipeline_name, recipe_name, parlist);
2031
2032 /* --tolerance */
2033 par_name = cpl_sprintf("%s.%s.tolerance", pipeline_name, recipe_name);
2034 assert(par_name != NULL);
2035 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2036 xsh_detmon_lg_config.tolerance = cpl_parameter_get_double(par);
2037 cpl_free(par_name);
2038
2039
2040 /* --pafgen */
2041 par_name = cpl_sprintf("%s.%s.pafgen", pipeline_name, recipe_name);
2042 assert(par_name != NULL);
2043 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2044 xsh_detmon_lg_config.pafgen = cpl_parameter_get_bool(par);
2045 cpl_free(par_name);
2046
2047 /* --pafname */
2048 par_name = cpl_sprintf("%s.%s.pafname", pipeline_name, recipe_name);
2049 assert(par_name != NULL);
2050 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2051 xsh_detmon_lg_config.pafname = cpl_parameter_get_string(par);
2052 cpl_free(par_name);
2053
2054 if(opt_nir == OPT) {
2055 /* --llx1 */
2057 xsh_detmon_retrieve_par_int("llx1", pipeline_name, recipe_name,
2058 parlist);
2059
2060 /* --lly1 */
2062 xsh_detmon_retrieve_par_int("lly1", pipeline_name, recipe_name,
2063 parlist);
2064
2065 /* --urx1 */
2067 xsh_detmon_retrieve_par_int("urx1", pipeline_name, recipe_name,
2068 parlist);
2069
2070 /* --ury1 */
2072 xsh_detmon_retrieve_par_int("ury1", pipeline_name, recipe_name,
2073 parlist);
2074
2075 /* --llx2 */
2077 xsh_detmon_retrieve_par_int("llx2", pipeline_name, recipe_name,
2078 parlist);
2079
2080 /* --lly2 */
2082 xsh_detmon_retrieve_par_int("lly2", pipeline_name, recipe_name,
2083 parlist);
2084
2085 /* --urx2 */
2087 xsh_detmon_retrieve_par_int("urx2", pipeline_name, recipe_name,
2088 parlist);
2089
2090 /* --ury2 */
2092 xsh_detmon_retrieve_par_int("ury2", pipeline_name, recipe_name,
2093 parlist);
2094
2095 /* --llx3 */
2097 xsh_detmon_retrieve_par_int("llx3", pipeline_name, recipe_name,
2098 parlist);
2099
2100 /* --lly3 */
2102 xsh_detmon_retrieve_par_int("lly3", pipeline_name, recipe_name,
2103 parlist);
2104
2105 /* --urx3 */
2107 xsh_detmon_retrieve_par_int("urx3", pipeline_name, recipe_name,
2108 parlist);
2109
2110 /* --ury3 */
2112 xsh_detmon_retrieve_par_int("ury3", pipeline_name, recipe_name,
2113 parlist);
2114
2115 /* --llx4 */
2117 xsh_detmon_retrieve_par_int("llx4", pipeline_name, recipe_name,
2118 parlist);
2119
2120 /* --lly4 */
2122 xsh_detmon_retrieve_par_int("lly4", pipeline_name, recipe_name,
2123 parlist);
2124
2125 /* --urx4 */
2127 xsh_detmon_retrieve_par_int("urx4", pipeline_name, recipe_name,
2128 parlist);
2129
2130 /* --ury4 */
2132 xsh_detmon_retrieve_par_int("ury4", pipeline_name, recipe_name,
2133 parlist);
2134
2135 /* --llx5 */
2137 xsh_detmon_retrieve_par_int("llx5", pipeline_name, recipe_name,
2138 parlist);
2139
2140 /* --lly5 */
2142 xsh_detmon_retrieve_par_int("lly5", pipeline_name, recipe_name,
2143 parlist);
2144
2145 /* --urx5 */
2147 xsh_detmon_retrieve_par_int("urx5", pipeline_name, recipe_name,
2148 parlist);
2149
2150 /* --ury5 */
2152 xsh_detmon_retrieve_par_int("ury5", pipeline_name, recipe_name,
2153 parlist);
2154 }
2155
2156 /* --exts */
2158 xsh_detmon_retrieve_par_int("exts", pipeline_name, recipe_name,
2159 parlist);
2160 /* --fpn_method */
2161 {
2163 par_name =
2164 cpl_sprintf("%s.%s.fpn_method", pipeline_name, recipe_name);
2165 assert(par_name != NULL);
2166 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2167 if (par)
2168 {
2169 const char * str_method = cpl_parameter_get_string(par);
2170 if (strcmp(str_method, "SMOOTH") == 0)
2171 {
2172 xsh_detmon_lg_config.fpn_method = FPN_SMOOTH;
2173 }
2174 else if (strcmp(str_method, "HISTOGRAM") == 0)
2175 {
2177 }
2178 }
2179 cpl_free(par_name);
2180 }
2181 /* --fpn_smooth */
2182 xsh_detmon_lg_config.fpn_smooth =
2183 xsh_detmon_retrieve_par_int("fpn_smooth", pipeline_name, recipe_name,
2184 parlist);
2185 /* --saturation_limit*/
2186 {
2187 xsh_detmon_lg_config.saturation_limit = 65535;
2188 par_name =
2189 cpl_sprintf("%s.%s.saturation_limit", pipeline_name, recipe_name);
2190 assert(par_name != NULL);
2191 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2192 if (par)
2193 {
2194 xsh_detmon_lg_config.saturation_limit = cpl_parameter_get_double(par);
2195 }
2196 cpl_free(par_name);
2197 }
2198
2199 /* --gain_threshold*/
2200 {
2201 xsh_detmon_lg_config.gain_threshold = 0;
2202 par_name =
2203 cpl_sprintf("%s.%s.gain_threshold", pipeline_name, recipe_name);
2204 assert(par_name != NULL);
2205 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
2206 if (par)
2207 {
2208 xsh_detmon_lg_config.gain_threshold = cpl_parameter_get_double(par);
2209 }
2210 cpl_free(par_name);
2211 }
2212
2213 if(cpl_error_get_code())
2214 {
2215 cpl_msg_error(cpl_func, "Failed to retrieve the input parameters");
2216 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
2217 }
2218
2219
2220 return cpl_error_get_code();
2221}
2222
2223/*---------------------------------------------------------------------------*/
2229/*---------------------------------------------------------------------------*/
2230static cpl_error_code
2231xsh_detmon_lg_check_defaults(const cpl_image * reference)
2232{
2233 const int nx = cpl_image_get_size_x(reference);
2234 const int ny = cpl_image_get_size_y(reference);
2235
2238
2239 xsh_detmon_lg_config.wholechip = CPL_FALSE;
2240
2241 if(xsh_detmon_lg_config.llx == -1)
2242 xsh_detmon_lg_config.llx = 1;
2243 if(xsh_detmon_lg_config.lly == -1)
2244 xsh_detmon_lg_config.lly = 1;
2245 if(xsh_detmon_lg_config.urx == -1)
2247 if(xsh_detmon_lg_config.ury == -1)
2249
2250 if (xsh_detmon_lg_config.llx == 1 &&
2251 xsh_detmon_lg_config.lly == 1 &&
2252 xsh_detmon_lg_config.urx == nx &&
2253 xsh_detmon_lg_config.ury == ny)
2254 xsh_detmon_lg_config.wholechip = CPL_TRUE;
2255
2256 if(xsh_detmon_lg_config.llx1 == -1)
2257 xsh_detmon_lg_config.llx1 = 1;
2258 if(xsh_detmon_lg_config.lly1 == -1)
2259 xsh_detmon_lg_config.lly1 = 1;
2260 if(xsh_detmon_lg_config.urx1 == -1)
2261 xsh_detmon_lg_config.urx1 = nx;
2262 if(xsh_detmon_lg_config.ury1 == -1)
2263 xsh_detmon_lg_config.ury1 = ny;
2264
2265 if(xsh_detmon_lg_config.llx2 == -1)
2266 xsh_detmon_lg_config.llx2 = 1;
2267 if(xsh_detmon_lg_config.lly2 == -1)
2268 xsh_detmon_lg_config.lly2 = 1;
2269 if(xsh_detmon_lg_config.urx2 == -1)
2270 xsh_detmon_lg_config.urx2 = nx / 2;
2271 if(xsh_detmon_lg_config.ury2 == -1)
2272 xsh_detmon_lg_config.ury2 = ny / 2;
2273
2274 if(xsh_detmon_lg_config.llx3 == -1)
2275 xsh_detmon_lg_config.llx3 = 1;
2276 if(xsh_detmon_lg_config.lly3 == -1)
2277 xsh_detmon_lg_config.lly3 = ny / 2;
2278 if(xsh_detmon_lg_config.urx3 == -1)
2279 xsh_detmon_lg_config.urx3 = nx / 2;
2280 if(xsh_detmon_lg_config.ury3 == -1)
2281 xsh_detmon_lg_config.ury3 = ny;
2282
2283 if(xsh_detmon_lg_config.llx4 == -1)
2284 xsh_detmon_lg_config.llx4 = nx / 2;
2285 if(xsh_detmon_lg_config.lly4 == -1)
2286 xsh_detmon_lg_config.lly4 = ny / 2;
2287 if(xsh_detmon_lg_config.urx4 == -1)
2288 xsh_detmon_lg_config.urx4 = nx;
2289 if(xsh_detmon_lg_config.ury4 == -1)
2290 xsh_detmon_lg_config.ury4 = ny;
2291
2292 if(xsh_detmon_lg_config.llx5 == -1)
2293 xsh_detmon_lg_config.llx5 = nx / 2;
2294 if(xsh_detmon_lg_config.lly5 == -1)
2295 xsh_detmon_lg_config.lly5 = 1;
2296 if(xsh_detmon_lg_config.urx5 == -1)
2297 xsh_detmon_lg_config.urx5 = nx;
2298 if(xsh_detmon_lg_config.ury5 == -1)
2299 xsh_detmon_lg_config.ury5 = ny / 2;
2300
2301 if(xsh_detmon_lg_config.intermediate == TRUE) {
2302 cpl_msg_warning(cpl_func, "PLEASE NOTE: The --intermediate option saves the difference and correlation images produced during autocorrelation computation. Therefore, --autocorr option has been automatically activated. If you didn't want to run this, please abort and rerun.");
2303 xsh_detmon_lg_config.autocorr = TRUE;
2304 }
2305
2306
2307 xsh_detmon_lg_config.lamp_stability = 0.0;
2308
2309 xsh_detmon_lg_config.lamp_ok = FALSE;
2310
2311 xsh_detmon_lg_config.cr = 0.0;
2312
2313 return cpl_error_get_code();
2314}
2315
2316/*---------------------------------------------------------------------------*/
2327/*---------------------------------------------------------------------------*/
2328static cpl_error_code
2329xsh_detmon_lg_split_onoff(const cpl_frameset * cur_fset,
2330 cpl_frameset * cur_fset_on,
2331 cpl_frameset * cur_fset_off,
2332 const char *tag_on,
2333 const char *tag_off)
2334{
2335 int nframes;
2336 int i;
2337
2338 cpl_frame * cur_frame_dup = NULL;
2339
2340#if 0
2341 const cpl_frame * first;
2342 const cpl_frame * second;
2343 const char * first_tag;
2344 const char * second_tag;
2345 skip_if((first = cpl_frameset_get_position_const(cur_fset, 0)) == NULL);
2346 skip_if((second = cpl_frameset_get_position_const(cur_fset, 1)) == NULL);
2347
2348 skip_if((first_tag = cpl_frame_get_tag(first)) == NULL);
2349 skip_if((second_tag = cpl_frame_get_tag(second)) == NULL);
2350 if (opt_nir == OPT &&
2351 ((!strcmp(first_tag, tag_on ) && !strcmp(second_tag, tag_off)) ||
2352 (!strcmp(first_tag, tag_off) && !strcmp(second_tag, tag_on )))) {
2353 xsh_detmon_lg_config.lamp_ok = TRUE;
2354 }
2355#endif
2356
2357 nframes = cpl_frameset_get_size(cur_fset);
2358 for(i = xsh_detmon_lg_config.lamp_ok ? 2 : 0; i < nframes; i++) {
2359 const cpl_frame * cur_frame =
2360 cpl_frameset_get_position_const(cur_fset, i);
2361 char * tag;
2362
2363 /* Duplication is required for insertion to a different frameset */
2364 cur_frame_dup = cpl_frame_duplicate(cur_frame);
2365 tag = (char *) cpl_frame_get_tag(cur_frame_dup);
2366
2367 /* Insertion in the corresponding sub-frameset */
2368 if(!strcmp(tag, tag_on)) {
2369 skip_if(cpl_frameset_insert(cur_fset_on, cur_frame_dup));
2370 } else if(!strcmp(tag, tag_off)) {
2371 skip_if(cpl_frameset_insert(cur_fset_off, cur_frame_dup));
2372 } else {
2373 cpl_frame_delete(cur_frame_dup);
2374 cur_frame_dup = NULL;
2375 }
2376 }
2377 cur_frame_dup = NULL;
2378
2379 end_skip;
2380
2381 cpl_frame_delete(cur_frame_dup);
2382
2383 return cpl_error_get_code();
2384}
2385
2386/*--------------------------------------------------------------------------*/
2408/*--------------------------------------------------------------------------*/
2409
2410static cpl_error_code
2411xsh_detmon_lg_reduce(const cpl_frameset * set_on,
2412 const cpl_frameset * set_off,
2413 int* index_on, int* index_off,
2414 double* exptime_on, double* exptime_off,
2415 int *next_index_on, int* next_index_off,
2416 cpl_imagelist ** coeffs_ptr,
2417 cpl_table * gain_table,
2418 cpl_table * linear_table,
2419 cpl_image ** bpm_ptr,
2420 cpl_imagelist * autocorr_images,
2421 cpl_imagelist * diff_flats,
2422 cpl_propertylist * gaint_qclist,
2423 cpl_propertylist * lint_qclist,
2424 cpl_propertylist * linc_qclist,
2425 cpl_propertylist * bpm_qclist,
2426 int (* load_fset) (const cpl_frameset *,
2427 cpl_type,
2428 cpl_imagelist *),
2429 const cpl_boolean opt_nir,
2430 int whichext)
2431{
2432 cpl_errorstate prestate = cpl_errorstate_get();
2433 const double D_INVALID_VALUE = -999;
2434 int i;
2435 cpl_imagelist * linearity_inputs = NULL;
2436 cpl_imagelist * opt_offs = NULL;
2437 int nsets;
2438 cpl_propertylist * reflist = NULL;
2439 int dit_nskip = 0;
2440 int rows_linear_affected = 1;
2441 int rows_gain_affected = 1;
2442 int last_linear_best = 0;
2443
2444 /* Test entries */
2445 cpl_ensure(set_on != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2446 cpl_ensure(set_off != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2447
2448 nsets = cpl_frameset_get_size(set_on) / 2;
2449
2450 xsh_detmon_lg_config.load_fset = load_fset;
2451 if(xsh_detmon_lg_config.collapse) {
2452 /*
2453 * When the 'collapse' option is used, there are no OFF pairs. We
2454 * construct a pair with the 2 first raw OFF frames, which will be
2455 * passed for each DIT value, to maintain the same API in the function
2456 * xsh_detmon_gain_table_fill_row().
2457 */
2458 const cpl_frame *first = cpl_frameset_get_position_const(set_off, 0);
2459 cpl_frame *dup_first = cpl_frame_duplicate(first);
2460
2461 const cpl_frame *second = cpl_frameset_get_position_const(set_off, 1);
2462 cpl_frame *dup_second = cpl_frame_duplicate(second);
2463
2464 cpl_frameset *raw_offs = cpl_frameset_new();
2465
2466 skip_if(cpl_frameset_insert(raw_offs, dup_first));
2467 skip_if(cpl_frameset_insert(raw_offs, dup_second));
2468
2469 opt_offs = cpl_imagelist_load_frameset(raw_offs, CPL_TYPE_FLOAT,
2470 0, whichext);
2471
2472 cpl_frameset_delete(raw_offs);
2473 if (opt_offs == NULL) {
2474 cpl_errorstate_set(prestate);
2475 return CPL_ERROR_CONTINUE;
2476 }
2477 }
2478
2479 skip_if(xsh_detmon_lg_reduce_init(gain_table,
2480 linear_table,
2481 &linearity_inputs,
2482 opt_nir));
2483/*
2484 if (!strcmp(xsh_detmon_lg_config.method, "PTC"))
2485 {
2486 cpl_msg_warning(cpl_func, "PTC method incompatible with lamp stability"
2487 "computation");
2488 }
2489*/
2490 /* do always lamp stability check */
2491 if(xsh_detmon_lg_lamp_stab(set_on, set_off,
2492 opt_nir, whichext)) {
2493 cpl_errorstate_set(prestate);
2494 }
2495
2496 if(!xsh_detmon_lg_config.collapse)
2497 {
2498 }
2499 /* Unselect all rows, to select only invalid ones */
2500 skip_if(cpl_table_unselect_all(linear_table));
2501 skip_if(cpl_table_unselect_all(gain_table));
2502
2503 /* Loop on every DIT value */
2504
2505 for(i = 0; i < nsets ; i++)
2506 {
2507 skip_if(xsh_detmon_lg_reduce_dit(set_on,
2508 index_on, exptime_on,
2509 i,
2510 &dit_nskip,
2511 set_off,
2512 index_off, exptime_off,
2513 next_index_on, next_index_off,
2514 linear_table,
2515 gain_table, linearity_inputs,
2516 lint_qclist, opt_nir,
2517 autocorr_images, diff_flats,
2518 opt_offs, whichext,
2519 &rows_linear_affected,&rows_gain_affected));
2520 /* TODO: the following if could be done directly inside the
2521 * function xsh_detmon_lg_reduce_dit
2522 */
2523 if (rows_linear_affected == 0)
2524 {
2525 cpl_msg_warning(cpl_func, "The rest frames would not be taken "
2526 "into linear calculation, check the messages above");
2527 cpl_table_select_row(linear_table, i);
2528 }
2529 else
2530 {
2531 last_linear_best = i;
2532 }
2533
2534 if (rows_gain_affected == 0)
2535 {
2536 cpl_msg_warning(cpl_func, "The rest frames would not be taken "
2537 "into gain calculation, check the messages above");
2538 cpl_table_select_row(gain_table, i);
2539 }
2540 else
2541 {
2542 int last_gain_best = i;
2543 }
2544
2545
2546
2547 }
2548
2549 skip_if(xsh_detmon_add_adl_column(linear_table, opt_nir));
2550
2551 /*
2552 * Removal of rows corresponding to frames above --filter threshold.
2553 * See calls to cpl_table_select_row() in xsh_detmon_lg_reduce_dit().
2554 */
2555 skip_if(cpl_table_erase_selected(gain_table));
2556 skip_if(cpl_table_erase_selected(linear_table));
2557
2558
2559 reflist = cpl_propertylist_new();
2560 skip_if(cpl_propertylist_append_bool(reflist, "ADU", FALSE));
2561 skip_if(cpl_table_sort(gain_table, reflist));
2562 /*
2563 * --Final reduction--
2564 * The following call to xsh_detmon_lg_reduce_all() makes the
2565 * computations which are over all posible DIT values.
2566 */
2567 skip_if(xsh_detmon_lg_reduce_all(linear_table,
2568 gaint_qclist, lint_qclist, linc_qclist,
2569 bpm_qclist, coeffs_ptr, bpm_ptr,
2570 linearity_inputs,
2571 gain_table, whichext, opt_nir));
2572 {
2573 /*FPN Computation*/
2574 double gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
2575 // cpl_propertylist_append_int(gaint_qclist, "NNNEXT", whichext);
2576 // cpl_msg_warning(cpl_func, "---------- ext %i" , whichext);
2577 cpl_error_code cplerr = cpl_error_get_code();
2578 if (cplerr != CPL_ERROR_NONE || (gain == 0.0))
2579 {
2580 cpl_msg_warning(cpl_func, "Cannot read gain from QC parameters - "
2581 "FPN will not be computed");
2582 cpl_error_reset();
2583 }
2584 else
2585 {
2586 xsh_detmon_fpn_compute(set_on, index_on, last_linear_best, lint_qclist,
2591 gain,
2592 whichext,
2593 xsh_detmon_lg_config.fpn_method,
2594 xsh_detmon_lg_config.fpn_smooth);
2595 }
2596 }
2597 /* change NaN in the gain table to the invalid value D_INVALID_VALUE*/
2598
2599 xsh_detmon_table_fill_invalid(gain_table, D_INVALID_VALUE);
2600 end_skip;
2601 cpl_imagelist_delete(linearity_inputs);
2602 cpl_imagelist_delete(opt_offs);
2603 cpl_propertylist_delete(reflist);
2604
2605 return cpl_error_get_code();
2606}
2607
2608static cpl_error_code xsh_detmon_table_fill_invalid(cpl_table* ptable, double code)
2609{
2610 int ncols = cpl_table_get_ncol(ptable);
2611 cpl_array* pnames = cpl_table_get_column_names(ptable);
2612 int nrows = cpl_table_get_nrow(ptable);
2613 int i = 0;
2614 for (i=0; i < ncols; i++)
2615 {
2616 int j = 0;
2617 for (j = 0; j< nrows; j++)
2618 {
2619 const char* colname = cpl_array_get_data_string_const(pnames)[i];
2620 int isnull;
2621 cpl_type type = cpl_table_get_column_type(ptable, colname);
2622 cpl_table_get(ptable, colname, j, &isnull);
2623 if(isnull == 1)
2624 {
2625 if (type == CPL_TYPE_DOUBLE)
2626 {
2627 cpl_table_set(ptable,colname,j, code);
2628 }
2629 else if (type == CPL_TYPE_FLOAT)
2630 {
2631 cpl_table_set_float(ptable,colname,j, (float)code);
2632 }
2633 }
2634 }
2635 }
2636 cpl_array_delete(pnames);
2637 return cpl_error_get_code();
2638}
2639
2640static cpl_error_code
2641xsh_detmon_fpn_compute(const cpl_frameset *set_on,
2642 int * index_on,
2643 int last_linear_best,
2644 cpl_propertylist *lint_qclist,
2645 int llx,
2646 int lly,
2647 int urx,
2648 int ury,
2649 double gain,
2650 int whichext,
2652 int smooth_size)
2653{
2654 double fpn = 0;
2655 const cpl_image* im1 = 0;
2656 int range[4];
2657 cpl_imagelist* ons = 0;
2658 cpl_frameset * pair_on = 0;
2659 int nsets_extracted = cpl_frameset_get_size(set_on);
2660 cpl_size * selection = NULL;
2661 double mse = 0;
2662 range[0] = llx;
2663 range[1] = lly;
2664 range[2] = urx;
2665 range[3] = ury;
2666
2667 /* Retrieve 2 ON frames with the highest DIT -
2668 * the last best 2 values in the index*/
2669 selection = cpl_malloc(sizeof(cpl_size) * nsets_extracted);
2670 memset(&selection[0], 0, sizeof(cpl_size) * nsets_extracted);
2671
2672 selection[index_on[last_linear_best*2 + 0] ] = 1;
2673 selection[index_on[last_linear_best*2 + 1] ] = 1;
2674 pair_on = cpl_frameset_extract(set_on, selection, 1);
2675 ons = xsh_detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2676
2677 skip_if(ons == NULL);
2678 skip_if((im1 = cpl_imagelist_get_const(ons, 0)) == NULL);
2679
2680 fpn = irplib_fpn_lg(im1, range, gain, fpn_method, smooth_size, &mse);
2681 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_FPN,
2682 fpn));
2683 skip_if(cpl_propertylist_append_double(lint_qclist, "ESO QC GAIN ERR",
2684 mse));
2685
2686 end_skip;
2687 cpl_frameset_delete(pair_on);
2688 cpl_imagelist_delete(ons);
2689 cpl_free(selection);
2690 return cpl_error_get_code();
2691}
2692
2693/*--------------------------------------------------------------------------*/
2701/*--------------------------------------------------------------------------*/
2702static cpl_error_code
2703xsh_detmon_lg_lamp_stab(const cpl_frameset * lamps,
2704 const cpl_frameset * darks,
2705 cpl_boolean opt_nir,
2706 int whichext)
2707{
2708
2709 /*
2710 * NOTE:
2711 * Most of this code is copied (and modified) from
2712 * isaac_img_detlin_load(), in isaac_img_detlin.c v.1.25
2713 */
2714
2715 int nb_lamps;
2716 int nb_darks;
2717
2718 cpl_vector * selection = NULL;
2719 cpl_propertylist * plist;
2720 double dit_lamp, dit_dark;
2721 int dit_stab;
2722 cpl_imagelist * lamps_data = NULL;
2723 cpl_imagelist * darks_data = NULL;
2724 double * stab_levels = NULL;
2725 int i, j;
2726 double * ditvals = NULL;
2727 int last_stab = 0; /* Avoid false uninit warning */
2728
2729 /* Check that there are as many lamp as darks */
2730 cpl_ensure_code((nb_lamps = cpl_frameset_get_size(lamps)) >= 3,
2731 CPL_ERROR_ILLEGAL_INPUT);
2732/*
2733 cpl_ensure_code(cpl_frameset_get_size(darks) == nb_lamps,
2734 CPL_ERROR_ILLEGAL_INPUT);
2735*/
2736 /* Check out that they have consistent integration times */
2737 cpl_msg_info(__func__, "Checking DIT consistency");
2738 selection = cpl_vector_new(nb_lamps);
2739 ditvals = cpl_malloc(nb_lamps * sizeof(double));
2740 dit_stab = 0;
2741 for (i = 0; i < nb_lamps; i++) {
2742 const cpl_frame * c_lamp;
2743 const cpl_frame * c_dark;
2744 /* Check if ok */
2745 skip_if (cpl_error_get_code());
2746
2747 /* DIT from LAMP */
2748 c_lamp = cpl_frameset_get_position_const(lamps, i);
2749 plist = cpl_propertylist_load(cpl_frame_get_filename(c_lamp), 0);
2750 if(opt_nir)
2751 dit_lamp = (double)irplib_pfits_get_dit(plist);
2752 else
2753 dit_lamp = (double)irplib_pfits_get_dit_opt(plist);
2754 cpl_propertylist_delete(plist);
2755 skip_if (cpl_error_get_code());
2756
2757 /* DIT from DARK */
2758 c_dark = cpl_frameset_get_position_const(darks, i);
2759 plist = cpl_propertylist_load(cpl_frame_get_filename(c_dark), 0);
2760 if(opt_nir)
2761 dit_dark = (double)irplib_pfits_get_dit(plist);
2762 else
2763 dit_dark = (double)irplib_pfits_get_dit_opt(plist);
2764 cpl_propertylist_delete(plist);
2765 skip_if (cpl_error_get_code());
2766
2767 /* Check consistency */
2768 if (fabs(dit_dark-dit_lamp) > 1e-3) {
2769 cpl_msg_error(__func__, "DIT not consistent between LAMP and DARK, skip lamp stability computation");
2770 /* FIXME: Should an error code be set here? */
2771
2772 skip_if(1);
2773 }
2774 ditvals[i] = dit_lamp;
2775 /* Set selection */
2776 if (i==0) {
2777 cpl_vector_set(selection, i, -1.0);
2778 dit_stab ++;
2779 last_stab = 0;
2780 } else {
2781 /*
2782 * The second condition is to make sure that frames taken into
2783 * account for lamp stability are not consecutive.
2784 */
2785 if (fabs(dit_lamp - ditvals[0]) < 1e-5 && i - last_stab > 3) {
2786 cpl_vector_set(selection, i, -1.0);
2787 dit_stab ++;
2788 last_stab = i;
2789 } else {
2790 cpl_vector_set(selection, i, 1.0);
2791 }
2792 }
2793 }
2794
2795 /* Check if there are enough DITs for stability check */
2796 if (dit_stab < 2) {
2797 cpl_msg_info(__func__, "Not enough frames for stability check");
2798 } else {
2799
2800 /* Load the data and compute lamp-dark */
2801 cpl_msg_info(__func__, "Compute the differences lamp - dark");
2802
2803
2804 lamps_data = xsh_detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2805 whichext,
2810 -1, -1);
2811
2812 darks_data = xsh_detmon_load_frameset_window(lamps, CPL_TYPE_FLOAT, 0,
2813 whichext,
2818 -1, -1);
2819
2820 nb_darks=cpl_imagelist_get_size(darks_data);
2821 if(nb_darks==nb_lamps) {
2822 skip_if(cpl_imagelist_subtract(lamps_data,darks_data));
2823 } else {
2824 cpl_image* master_dark=cpl_imagelist_collapse_median_create(darks_data);
2825 cpl_imagelist_subtract_image(lamps_data,master_dark);
2826 cpl_image_delete(master_dark);
2827 }
2828 /* Check the lamp stability */
2829 cpl_msg_info(__func__, "Check the lamp stability");
2830 stab_levels = cpl_malloc(dit_stab * sizeof(double));
2831 j = 0;
2832 for (i=0; i<nb_lamps; i++) {
2833 if (cpl_vector_get(selection, i) < 0) {
2834 stab_levels[j] =
2835 cpl_image_get_mean(cpl_imagelist_get(lamps_data, i));
2836 j++;
2837 }
2838 }
2839
2840 /* Compute the lamp stability */
2841 for (i=1; i<dit_stab; i++) {
2842 if ((fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0]) >
2843 xsh_detmon_lg_config.lamp_stability)
2844 xsh_detmon_lg_config.lamp_stability =
2845 fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0];
2846 }
2847
2848
2849 /* Check the lamp stability */
2850 if (xsh_detmon_lg_config.lamp_stability > 0.01) {
2851 cpl_msg_warning(__func__,
2852 "Lamp stability level %g difference too high - proceed anyway",xsh_detmon_lg_config.lamp_stability);
2853 }
2854 }
2855 end_skip;
2856
2857
2858 cpl_free(ditvals);
2859 cpl_vector_delete(selection);
2860 cpl_imagelist_delete(lamps_data);
2861 cpl_imagelist_delete(darks_data);
2862 cpl_free(stab_levels);
2863
2864 return cpl_error_get_code();
2865}
2866
2867/*--------------------------------------------------------------------------*/
2890/*--------------------------------------------------------------------------*/
2891static cpl_error_code
2892xsh_detmon_lg_reduce_dit(const cpl_frameset * set_on,
2893 int* index_on, double* exptime_on,
2894 const int dit_nb,
2895 int * dit_nskip,
2896 const cpl_frameset * set_off,
2897 int * index_off, double* exptime_off,
2898 int* next_on, int* next_off,
2899 cpl_table * linear_table,
2900 cpl_table * gain_table,
2901 cpl_imagelist * linearity_inputs,
2902 cpl_propertylist * qclist,
2903 cpl_boolean opt_nir,
2904 cpl_imagelist * autocorr_images,
2905 cpl_imagelist * diff_flats,
2906 cpl_imagelist * opt_offs,
2907 int whichext,
2908 int* rows_linear_affected,
2909 int* rows_gain_affected)
2910{
2911 cpl_frameset * pair_on = NULL;
2912 cpl_frameset * pair_off = NULL;
2913 cpl_imagelist * ons = NULL;
2914 cpl_imagelist * offs = NULL;
2915 cpl_boolean follow = CPL_TRUE;
2916 unsigned mode = xsh_detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
2917 double c_dit;
2918 int c_ndit;
2919
2920 double current_dit = 0;
2921
2922 const char * filename;
2923
2924 cpl_propertylist * plist = NULL;
2925 cpl_propertylist* pDETlist = NULL;
2926
2927 mode = xsh_detmon_lg_config.collapse ?
2930 mode = xsh_detmon_lg_config.pix2pix ?
2932 mode = opt_nir ?
2935
2936
2937 /* ON pair extraction */
2938 skip_if(xsh_detmon_pair_extract_next(set_on, index_on, next_on, exptime_on, &pair_on, xsh_detmon_lg_config.tolerance));
2939 current_dit = exptime_on[*next_on - 1];
2940
2941 /* Load the ON images */
2942 ons = xsh_detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
2943 skip_if(ons == NULL);
2944 cpl_msg_debug(cpl_func, " Loaded ON images: %" CPL_SIZE_FORMAT
2945 ", exptime[%f]",cpl_imagelist_get_size(ons), current_dit );
2946 if(cpl_imagelist_get_size(ons) != 2)
2947 {
2948 cpl_msg_error(cpl_func, "cannot take ON pair, number of images[%"
2949 CPL_SIZE_FORMAT "]", cpl_imagelist_get_size(ons));
2950 skip_if(TRUE);
2951 }
2952 if(xsh_detmon_lg_config.filter > 0)
2953 {
2954 double med1 =
2955 cpl_image_get_median_window(cpl_imagelist_get(ons, 0),
2960 double med2 =
2961 cpl_image_get_median_window(cpl_imagelist_get(ons, 1),
2966 if ( med1 > (double)xsh_detmon_lg_config.filter ||
2967 med2 > (double)xsh_detmon_lg_config.filter)
2968 {
2969 follow = CPL_FALSE;
2970 cpl_table_select_row(gain_table, dit_nb);
2971 cpl_table_select_row(linear_table, dit_nb);
2972 (*dit_nskip)++;
2973 cpl_msg_warning(cpl_func, "Frames of EXPTIME nb %d "
2974 "will not be taken into account for computation "
2975 "as they are above --filter threshold", dit_nb);
2976 }
2977 }
2978
2979 if (follow || xsh_detmon_lg_config.filter < 0)
2980 {
2981
2982 /*
2983 * If the --collapse option is not activated by the user, the OFF
2984 * sub-frameset is also supposed to be organized into pairs and,
2985 * therefore, processed as the ON sub-frameset.
2986 */
2987 if(!xsh_detmon_lg_config.collapse)
2988 {
2989 /* TODO: We removed this check as with NACO data, that has an odd
2990 * number of input OFF frames it would stop with error
2991 * despite the recipe would reduce the data properly.
2992 * On the other side, on some data without such a check one may get
2993 * failures on another place.
2994 * we need to document such cases and understand how to better deal
2995 * in a robust way the case of odd input off frames
2996 *
2997 if (cpl_frameset_get_size(set_off) % 2 != 0) {
2998 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
2999 "If collapse is FALSE the OFF frameset"
3000 " must be organized in pairs.");
3001 skip_if(1);
3002 }
3003 */
3004 if (!strcmp(xsh_detmon_lg_config.method, "MED") ||
3005 cpl_frameset_get_size(set_on) == cpl_frameset_get_size(set_off))
3006 {
3007 skip_if(xsh_detmon_pair_extract_next(set_off, index_off, next_off, exptime_off, &pair_off, xsh_detmon_lg_config.tolerance));
3008 }
3009 else
3010 {
3011 skip_if(xsh_detmon_single_extract_next(set_off, index_off, next_off, exptime_off, &pair_off));
3012 }
3013 /* Load the OFF images */
3014 cpl_msg_debug(cpl_func, " Load the OFF images, ext[%d], exptime[%f]", whichext, exptime_off[*next_off - 1]);
3015 offs = xsh_detmon_lg_config.load_fset_wrp(pair_off, CPL_TYPE_FLOAT, whichext);
3016
3017 skip_if(offs == NULL);
3018 skip_if(cpl_error_get_code());
3019 }
3020 else {
3021 offs = (cpl_imagelist *) opt_offs;
3022 }
3023
3024 /* Rescaling */
3025 if(xsh_detmon_lg_config.rescale)
3026 {
3027 skip_if(xsh_detmon_lg_rescale(ons));
3028 if (!xsh_detmon_lg_config.collapse &&
3029 !strcmp(xsh_detmon_lg_config.method, "MED"))
3030 skip_if(xsh_detmon_lg_rescale(offs));
3031 }
3032 /* DIT or EXPTIME value extraction */
3033
3034 filename =
3035 cpl_frame_get_filename(cpl_frameset_get_position_const(pair_on, 0));
3036 skip_if ((plist = cpl_propertylist_load(filename, 0)) == NULL);
3037 /* Add columns to the tables DETi WINi UITi*/
3038 if (plist)
3039 {
3040 pDETlist = cpl_propertylist_new();
3041 cpl_propertylist_copy_property_regexp(pDETlist, plist, "DET[0-9]* WIN[0-9]* UIT[0-9]*",0);
3042 if (dit_nb == 0)
3043 {
3044 irplib_table_create_column(gain_table, pDETlist);
3045 irplib_table_create_column(linear_table, pDETlist);
3046 }
3047 }
3048 if(opt_nir == NIR) {
3049 c_dit = irplib_pfits_get_dit(plist);
3050 c_ndit = irplib_pfits_get_ndit(plist);
3051 } else {
3052 c_dit = irplib_pfits_get_exptime(plist);
3053 c_ndit=1;
3054 }
3055
3056 /*
3057 * --GAIN part for each DIT value--
3058 * The following call to xsh_detmon_gain_table_fill_row() fills
3059 * in the row nb i
3060 * of the GAIN table (output) and of the FIT table (by-product to be
3061 * used later for the polynomial computation of the GAIN)
3062 */
3063
3064 cpl_msg_info(cpl_func, "Computing GAIN for EXPTIME value nb %d",
3065 dit_nb + 1);
3066
3067 /* In case PTC is applied, this is allowed */
3068 if(cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE && dit_nb == 0)
3069 {
3070 cpl_table_erase_column(gain_table, "MEAN_OFF1");
3071 cpl_table_erase_column(gain_table, "MEAN_OFF2");
3072 cpl_table_erase_column(gain_table, "SIG_OFF_DIF");
3073 cpl_table_erase_column(gain_table, "GAIN");
3074 cpl_table_erase_column(gain_table, "GAIN_CORR");
3075 cpl_table_new_column(gain_table, "MEAN_OFF", CPL_TYPE_DOUBLE);
3076 }
3077
3078
3079 skip_if(xsh_detmon_gain_table_fill_row(gain_table,
3080 c_dit,c_ndit,
3081 autocorr_images,
3082 diff_flats, ons, offs,
3091 xsh_detmon_lg_config.saturation_limit,
3092 xsh_detmon_lg_config.gain_threshold,
3093 dit_nb, mode, rows_gain_affected));
3094
3095
3096 skip_if(xsh_detmon_check_saturation_on_pair(autocorr_images,
3097 diff_flats,ons,offs,
3104 xsh_detmon_lg_config.saturation_limit,
3105 dit_nb, mode, rows_linear_affected));
3106
3107
3108 if (*rows_gain_affected)
3109 {
3110 /* fill DETi WINi OPTi columns - see DFS06921*/
3111 skip_if(irplib_fill_table_DETWINUIT(gain_table, pDETlist, dit_nb));
3112 /* Linearity reduction */
3113 cpl_msg_info(cpl_func, "Linearity reduction for nb %d",
3114 dit_nb + 1);
3115 }
3116 if (*rows_linear_affected) {
3117 skip_if(xsh_detmon_lin_table_fill_row(linear_table, c_dit,
3118 linearity_inputs, ons, offs,
3123 dit_nb, *dit_nskip, mode));
3124 /* fill DETi WINi OPTi columns - see DFS06921*/
3125 skip_if(irplib_fill_table_DETWINUIT(linear_table, pDETlist, dit_nb));
3126 }
3127
3128
3129 /* as we know only at this point if a frame is
3130 saturated or not, and we would like to compute the
3131 contamination only on the last non saturated frame,
3132 we need de facto to compute saturation on any non saturated
3133 frame, by overwriting the QC parameter. In the end it will
3134 remain only the last value corresponding to a non saturated
3135 frame */
3136
3137 if(opt_nir == OPT &&
3138 *rows_linear_affected != 0 ) {
3139 xsh_detmon_opt_contamination(ons, offs, mode, qclist);
3140 }
3141
3142 }
3143
3144 end_skip;
3145
3146 cpl_frameset_delete(pair_on);
3147 cpl_imagelist_delete(ons);
3148
3149 if(!xsh_detmon_lg_config.collapse ) {
3150 cpl_imagelist_delete(offs);
3151 }
3152
3153 if(!xsh_detmon_lg_config.collapse) {
3154 cpl_frameset_delete(pair_off);
3155 }
3156
3157 cpl_propertylist_delete(plist);
3158 cpl_propertylist_delete(pDETlist);
3159 return cpl_error_get_code();
3160}
3161
3162/*---------------------------------------------------------------------------*/
3168/*---------------------------------------------------------------------------*/
3169static cpl_error_code
3171 cpl_boolean opt_nir)
3172{
3173 cpl_error_code error;
3174 double mean_med_dit;
3175 double *dits;
3176
3177 cpl_ensure_code(table != NULL, CPL_ERROR_NULL_INPUT);
3178
3179 mean_med_dit = cpl_table_get_column_mean(table, "MED_DIT");
3180 if (opt_nir == OPT)
3181 dits = cpl_table_get_data_double(table, "EXPTIME");
3182 else
3183 dits = cpl_table_get_data_double(table, "DIT");
3184
3185 error = cpl_table_copy_data_double(table, "ADL", dits);
3186 cpl_ensure_code(!error, error);
3187 error = cpl_table_multiply_scalar(table, "ADL", mean_med_dit);
3188 cpl_ensure_code(!error, error);
3189
3190 return cpl_error_get_code();
3191}
3192
3193/*---------------------------------------------------------------------------*/
3201/*---------------------------------------------------------------------------*/
3202static cpl_error_code
3203xsh_detmon_lg_reduce_init(cpl_table * gain_table,
3204 cpl_table * linear_table,
3205 cpl_imagelist ** linearity_inputs,
3206 const cpl_boolean opt_nir)
3207{
3208 skip_if(xsh_detmon_gain_table_create(gain_table, opt_nir));
3209 skip_if(xsh_detmon_lin_table_create(linear_table, opt_nir));
3210
3211 if(xsh_detmon_lg_config.pix2pix) {
3212 *linearity_inputs = cpl_imagelist_new();
3213 skip_if(*linearity_inputs == NULL);
3214 }
3215
3216 end_skip;
3217
3218 return cpl_error_get_code();
3219}
3220
3221/*--------------------------------------------------------------------------*/
3227/*--------------------------------------------------------------------------*/
3228static double
3229irplib_pfits_get_dit(const cpl_propertylist * plist)
3230{
3231 return irplib_pfits_get_prop_double(plist, "ESO DET DIT");
3232}
3233
3234/*--------------------------------------------------------------------------*/
3240/*--------------------------------------------------------------------------*/
3241static double
3242irplib_pfits_get_dit_opt(const cpl_propertylist * plist)
3243{
3244 return irplib_pfits_get_prop_double(plist, "ESO DET WIN1 UIT1");
3245}
3246
3247
3248/*---------------------------------------------------------------------------*/
3253static cpl_propertylist*
3254xsh_detmon_load_pro_keys(const char* NAME_O)
3255{
3256 cpl_propertylist* pro_keys=NULL;
3257 pro_keys=cpl_propertylist_load_regexp(NAME_O,0,"^(ESO PRO)",0);
3258 return pro_keys;
3259}
3260
3261
3262static double irplib_pfits_get_prop_double(const cpl_propertylist * plist,
3263 const char* prop_name)
3264{
3265 double dit;
3266 dit = cpl_propertylist_get_double(plist, prop_name);
3267 if(cpl_error_get_code() != CPL_ERROR_NONE)
3268 {
3269 cpl_msg_error(cpl_func, "Cannot read property '%s', err[%s]",
3270 prop_name, cpl_error_get_where());
3271 }
3272 return dit;
3273}
3274
3275static cpl_error_code
3276xsh_detmon_gain_compute_qc(double kappa, int nclip, const int pos,
3277 const cpl_imagelist* offs, unsigned mode,
3278 double double_adu, double avg_on1, double avg_on2,
3279 double avg_off1, double avg_off2, double sigma,
3280 double sig_off_dif, double gain, int c_ndit,
3281 double gain_corr, double autocorr, cpl_image* on_dif,
3282 cpl_table* gain_table)
3283{
3284
3285 /* here xsh_detmon actually computes gain QC parameter */
3286 double avg_on_dif, sig_on_dif;
3287 xsh_ksigma_clip(on_dif, 1, 1, cpl_image_get_size_x(on_dif),
3288 cpl_image_get_size_y(on_dif), kappa, nclip, 1e-5,
3289 &avg_on_dif, &sig_on_dif);
3290 skip_if(
3291 cpl_table_set_double(gain_table, "SIG_ON_DIF", pos,
3292 sig_on_dif));
3293 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE) {
3294 double_adu = (avg_on1 + avg_on2) - 2 * avg_off1;
3295 }
3296 else {
3297 double_adu = (avg_on1 + avg_on2) - (avg_off1 + avg_off2);
3298
3299 sigma = (sig_on_dif * sig_on_dif) - (sig_off_dif * sig_off_dif);
3300
3301 /* sigma_corr = autocorr * sigma; */
3302
3303 gain = double_adu / (c_ndit * sigma);
3304
3305 gain_corr = gain / (autocorr);
3306
3307 skip_if(cpl_table_set_double(gain_table, "GAIN", pos, gain));
3308 skip_if(
3309 cpl_table_set_double(gain_table, "GAIN_CORR", pos,
3310 gain_corr));
3311 }
3312 /* cpl_msg_info(cpl_func,"gain=%g gain_corr=%g autocorr=%g",gain,gain_corr,autocorr); */
3313 skip_if(cpl_table_set_double(gain_table, "AUTOCORR", pos, autocorr));
3314 skip_if(cpl_table_set_double(gain_table, "ADU", pos, double_adu / 2));
3315 /* FIXME: Remove the following 3 columns after testing period */
3316 skip_if(
3317 cpl_table_set_double(gain_table, "Y_FIT", pos,
3318 c_ndit * sig_on_dif * sig_on_dif));
3319 skip_if(
3320 cpl_table_set_double(gain_table, "Y_FIT_CORR", pos,
3321 c_ndit * sig_on_dif * sig_on_dif));
3322 skip_if(cpl_table_set_double(gain_table, "X_FIT", pos, double_adu));
3323 skip_if(
3324 cpl_table_set_double(gain_table, "X_FIT_CORR", pos,
3325 double_adu / autocorr));
3326
3327 end_skip;
3328
3329 return cpl_error_get_code();
3330}
3331
3332double
3333xsh_detmon_gain_prepare_autocorr(unsigned mode, const int pos, double autocorr,
3334 int m, int n, cpl_imagelist* diff_flats,
3335 cpl_image* on_dif, cpl_imagelist* autocorr_images)
3336{
3338 if (diff_flats) {
3339 cpl_image * diff = cpl_image_duplicate(on_dif);
3340 skip_if(cpl_imagelist_set(diff_flats, diff, pos));
3341 }
3342 if (autocorr_images) {
3343 cpl_image * corr = NULL;
3344 autocorr = xsh_detmon_autocorr_factor(on_dif, &corr, m, n);
3345 if (corr) {
3346 skip_if(cpl_imagelist_set(autocorr_images, corr, pos));
3347 }
3348 else {
3349 xsh_detmon_lg_add_empty_image(autocorr_images, pos);
3350 }
3351 }
3352 else {
3353 autocorr = xsh_detmon_autocorr_factor(on_dif, NULL, m, n);
3354 }
3355 autocorr = isnan(autocorr) ? 1.0 : autocorr;
3356 }
3357 else {
3358 autocorr = 1.0;
3359 }
3360 end_skip;
3361
3362 return autocorr;
3363}
3364
3365double
3366xsh_detmon_gain_prepare_table(const cpl_imagelist* offs, unsigned mode, int llx,
3367 int lly, int urx, int ury, double kappa, int nclip,
3368 double avg_off1, double std, const int pos,
3369 cpl_table* gain_table, double* avg_off2,
3370 double* sig_off_dif)
3371{
3372 /* prepare gain table to compute gain QC param */
3373 /* TODO: AMO sees that the condition (mode & IRPLIB_GAIN_NO_COLLAPSE)
3374 * is repeated in 2 if entries==> probably one should rewrite the if
3375 * construct
3376 */
3377 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE) {
3378
3379 skip_if(
3380 xsh_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3381 llx, lly, urx, ury, kappa, nclip, 1e-5,
3382 &avg_off1, &std));
3383 skip_if(cpl_table_set_double(gain_table, "MEAN_OFF", pos, avg_off1));
3384
3385 }
3386 else if ((mode & IRPLIB_GAIN_NO_COLLAPSE)
3387 || (pos == 0 && mode & IRPLIB_GAIN_COLLAPSE)) {
3388 cpl_image * off_dif = NULL;
3389 double avg_off_dif;
3390 skip_if(
3391 xsh_ksigma_clip(cpl_imagelist_get_const(offs, 0),
3392 llx, lly, urx, ury, kappa, nclip, 1e-5,
3393 &avg_off1, &std));
3394 skip_if(cpl_table_set_double(gain_table, "MEAN_OFF1", pos, avg_off1));
3395 skip_if(
3396 xsh_ksigma_clip(cpl_imagelist_get_const(offs, 1),
3397 llx, lly, urx, ury, kappa, nclip, 1e-5,
3398 avg_off2, &std));
3399 skip_if(cpl_table_set_double(gain_table, "MEAN_OFF2", pos, *avg_off2));
3401 cpl_imagelist_get_const(offs, 0),
3402 cpl_imagelist_get_const(offs, 1), llx, lly, urx, ury);
3403 skip_if(off_dif == NULL);
3404 xsh_ksigma_clip(off_dif, 1, 1, cpl_image_get_size_x(off_dif),
3405 cpl_image_get_size_y(off_dif), kappa, nclip, 1e-5,
3406 &avg_off_dif, sig_off_dif);
3407 cpl_image_delete(off_dif);
3408 skip_if(
3409 cpl_table_set_double(gain_table, "SIG_OFF_DIF", pos,
3410 *sig_off_dif));
3411 }
3412 else if (pos > 0 && (mode & IRPLIB_GAIN_COLLAPSE)) {
3413
3414 int status;
3415 avg_off1 = cpl_table_get_double(gain_table, "MEAN_OFF1", 0, &status);
3416 skip_if(cpl_table_set_double(gain_table, "MEAN_OFF1", pos, avg_off1));
3417 *avg_off2 = cpl_table_get_double(gain_table, "MEAN_OFF2", 0, &status);
3418 skip_if(cpl_table_set_double(gain_table, "MEAN_OFF2", pos, *avg_off2));
3419 *sig_off_dif = cpl_table_get_double(gain_table, "SIG_OFF_DIF", 0,
3420 &status);
3421 skip_if(
3422 cpl_table_set_double(gain_table, "SIG_OFF_DIF", pos,
3423 *sig_off_dif));
3424 }
3425
3426 end_skip;
3427
3428 return avg_off1;
3429}
3430
3431/*---------------------------------------------------------------------------*/
3466/*---------------------------------------------------------------------------*/
3467static cpl_error_code
3468xsh_detmon_gain_table_fill_row(cpl_table * gain_table,
3469 double c_dit,int c_ndit,
3470 cpl_imagelist * autocorr_images,
3471 cpl_imagelist * diff_flats,
3472 const cpl_imagelist * ons,
3473 const cpl_imagelist * offs,
3474 double kappa, int nclip,
3475 int llx, int lly, int urx, int ury,
3476 int m, int n,
3477 double saturation_limit,
3478 double gain_threshold,
3479 const int pos, unsigned mode, int* rows_gain_affected)
3480{
3481 const cpl_image *image;
3482 cpl_image *on_dif = NULL;
3483 double std = 0;
3484 double avg_on1, avg_on2;
3485 double avg_off1=0, avg_off2;
3486 double double_adu=0, autocorr=0, gain=0, gain_corr=0;
3487 double sigma=0;
3488
3489 cpl_table_set(gain_table, "FLAG", pos, 1);
3490 if (mode & IRPLIB_GAIN_NIR)
3491 {
3492 cpl_table_set(gain_table, "DIT", pos, c_dit);
3493 cpl_table_set(gain_table, "NDIT", pos, c_ndit);
3494 } else if (mode & IRPLIB_GAIN_OPT)
3495 {
3496 cpl_table_set(gain_table, "EXPTIME", pos, c_dit);
3497 } else
3498 {
3499 cpl_msg_error(cpl_func, "Mandatory mode (OPT or NIR) not provided");
3500 skip_if(1);
3501 }
3502 if(*rows_gain_affected == 0)
3503 {
3504 cpl_msg_info(cpl_func, "skip the frame #%d", pos + 1);
3505 cpl_table_set(gain_table, "FLAG", pos, 0);
3507 {
3508 autocorr = -1;
3509 if (diff_flats)
3510 {
3511 xsh_detmon_lg_add_empty_image(diff_flats, pos);
3512 }
3513 if (autocorr_images)
3514 {
3515 xsh_detmon_lg_add_empty_image(autocorr_images, pos);
3516 }
3517 }
3518 return cpl_error_get_code();
3519 }
3520 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3521 skip_if(xsh_ksigma_clip(image, llx, lly, urx, ury, kappa,
3522 nclip, 1e-5, &avg_on1, &std));
3523 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3524 skip_if(xsh_ksigma_clip(image, llx, lly, urx, ury, kappa,
3525 nclip, 1e-5, &avg_on2, &std));
3526
3527 if (
3528 (avg_on1 > gain_threshold) ||
3529 (avg_on2 > gain_threshold)
3530 )
3531 {
3532 /* If frames has intensity above threshold write out warning and adjust
3533 * imagelists
3534 */
3535 if ( (avg_on1 > gain_threshold) || (avg_on2 > gain_threshold) )
3536 {
3537 cpl_msg_warning(cpl_func, "Average level is above the limit set by the gain_theshold parameter, "
3538 "the frames would not be taken into calculation");
3539
3540 cpl_msg_warning(cpl_func, "Average levels [%f ; %f], limit [%f]",
3541 avg_on1, avg_on2, gain_threshold);
3542 }
3543
3544 cpl_msg_info(cpl_func, "skip the frame #%d", pos + 1);
3545 cpl_table_set(gain_table, "FLAG", pos, 0);
3547 {
3548 autocorr = -1;
3549 if (diff_flats)
3550 {
3551 xsh_detmon_lg_add_empty_image(diff_flats, pos);
3552 }
3553 if (autocorr_images)
3554 {
3555 xsh_detmon_lg_add_empty_image(autocorr_images, pos);
3556 }
3557 }
3558 *rows_gain_affected = 0;
3559 }
3560 else
3561 {
3562 /* we can compute gain: first computes relevant quantities to cover all
3563 * cases, then compute QC parameter.
3564 */
3565 double sig_off_dif;
3566 *rows_gain_affected = 1;
3567 skip_if(cpl_table_set_double(gain_table, "MEAN_ON1", pos, avg_on1));
3568 skip_if(cpl_table_set_double(gain_table, "MEAN_ON2", pos, avg_on2));
3569
3570 on_dif =
3571 xsh_detmon_subtract_create_window(cpl_imagelist_get_const(ons, 0),
3572 cpl_imagelist_get_const(ons, 1),
3573 llx, lly, urx, ury);
3574 skip_if(on_dif == NULL);
3575
3577 diff_flats, on_dif, autocorr_images);
3578
3579 avg_off1 = xsh_detmon_gain_prepare_table(offs, mode, llx, lly, urx, ury,
3580 kappa, nclip, avg_off1, std, pos, gain_table, &avg_off2,
3581 &sig_off_dif);
3582
3583 xsh_detmon_gain_compute_qc(kappa, nclip, pos, offs, mode, double_adu,
3584 avg_on1, avg_on2, avg_off1, avg_off2, sigma,
3585 sig_off_dif, gain, c_ndit, gain_corr, autocorr, on_dif,
3586 gain_table);
3587 }
3588 end_skip;
3589
3590 cpl_image_delete(on_dif);
3591
3592 return cpl_error_get_code();
3593}
3594
3595
3596
3597/*---------------------------------------------------------------------------*/
3619/*---------------------------------------------------------------------------*/
3620static cpl_error_code
3621xsh_detmon_check_saturation_on_pair(cpl_imagelist * autocorr_images,
3622 cpl_imagelist * diff_flats,
3623 const cpl_imagelist * ons,
3624 const cpl_imagelist * offs,
3625 double kappa, int nclip,
3626 int llx, int lly, int urx, int ury,
3627 double saturation_limit,
3628 const int pos, unsigned mode, int* rows_linear_affected)
3629{
3630 const cpl_image *image;
3631 double std = 0;
3632 double avg_on1, avg_on2;
3633
3634
3635 if(*rows_linear_affected == 0)
3636 {
3637 cpl_msg_info(cpl_func, "For linearity skip the frame #%d", pos + 1);
3639 {
3640 if (diff_flats)
3641 {
3642 xsh_detmon_lg_add_empty_image(diff_flats, pos);
3643 }
3644 if (autocorr_images)
3645 {
3646 xsh_detmon_lg_add_empty_image(autocorr_images, pos);
3647 }
3648 }
3649 return cpl_error_get_code();
3650 }
3651 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
3652 skip_if(xsh_ksigma_clip(image, llx, lly, urx, ury, kappa,
3653 nclip, 1e-5, &avg_on1, &std));
3654 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
3655 skip_if(xsh_ksigma_clip(image, llx, lly, urx, ury, kappa,
3656 nclip, 1e-5, &avg_on2, &std));
3657
3658 if (
3659 (avg_on1 > saturation_limit) ||
3660 (avg_on2 > saturation_limit)
3661 )
3662 {
3663 /* If frames has intensity above threshold write out warning and adjust
3664 * imagelists
3665 */
3666 if ( (avg_on1 > saturation_limit) || (avg_on2 > saturation_limit) )
3667 {
3668 cpl_msg_warning(cpl_func, "Average level is above the limit set by the saturation_limit parameter, "
3669 "the frames would not be taken into calculation");
3670
3671 cpl_msg_warning(cpl_func, "Average levels [%f ; %f], limit [%f]",
3672 avg_on1, avg_on2, saturation_limit);
3673 }
3674
3675 cpl_msg_info(cpl_func, "skip the frame #%d", pos + 1);
3676 *rows_linear_affected = 0;
3677 } else{
3678
3679 }
3680
3681 end_skip;
3682
3683 return cpl_error_get_code();
3684}
3685
3686
3687
3688
3689/*--------------------------------------------------------------------------*/
3696/*--------------------------------------------------------------------------*/
3697
3698static cpl_image *
3699xsh_detmon_bpixs(const cpl_imagelist * coeffs,
3700 cpl_boolean bpmbin,
3701 const double kappa,
3702 int *nbpixs)
3703{
3704
3705
3706 const cpl_image *first= cpl_imagelist_get_const(coeffs, 0);
3707
3708
3709
3710
3711
3712
3713 cpl_mask *mask = cpl_mask_new(cpl_image_get_size_x(first),
3714 cpl_image_get_size_y(first));
3715
3716 cpl_image *bpm = NULL; /* Avoid false uninit warning */
3717
3718
3719 int size = cpl_imagelist_get_size(coeffs);
3720
3721 if(!bpmbin) {
3722 bpm = cpl_image_new(cpl_image_get_size_x(first),
3723 cpl_image_get_size_y(first),
3724 CPL_TYPE_INT);
3725 }
3726
3727
3728 for(int i = 0; i < size; i++) {
3729 const cpl_image * cur_coeff = cpl_imagelist_get_const(coeffs, i);
3730
3731 cpl_stats* stats = cpl_stats_new_from_image(cur_coeff,
3732 CPL_STATS_MEAN | CPL_STATS_STDEV);
3733 double cur_mean = cpl_stats_get_mean(stats);
3734 double cur_stdev = cpl_stats_get_stdev(stats);
3735
3736 double lo_cut = cur_mean - kappa * cur_stdev;
3737 double hi_cut = cur_mean + kappa * cur_stdev;
3738
3739 cpl_mask* cur_mask = cpl_mask_threshold_image_create(cur_coeff, lo_cut, hi_cut);
3740 cpl_mask_not(cur_mask);
3741
3742 if(!bpmbin) {
3743 cpl_image* cur_image = cpl_image_new_from_mask(cur_mask);
3744 double p = pow(2, i);
3745 cpl_image_power(cur_image, p);
3746 cpl_image_add(bpm, cur_image);
3747 cpl_image_delete(cur_image);
3748 }
3749
3750 cpl_mask_or(mask, cur_mask);
3751
3752 cpl_mask_delete(cur_mask);
3753 cpl_stats_delete(stats);
3754 }
3755
3756 if(bpmbin) {
3757 bpm = cpl_image_new_from_mask(mask);
3758 }
3759
3760 *nbpixs += cpl_mask_count(mask);
3761
3762 cpl_mask_delete(mask);
3763
3764 return bpm;
3765}
3766
3767
3768/*--------------------------------------------------------------------------*/
3775/*--------------------------------------------------------------------------*/
3776/* Not used so we temporary comment it out
3777static cpl_image *
3778xsh_detmon_bpixs2(cpl_vector* x,const cpl_imagelist* y,
3779 const cpl_imagelist * coeffs,cpl_table* gain_table,
3780 const int order, const double kappa,cpl_boolean bpmbin,
3781 int *nbpixs)
3782{
3783
3784
3785 int size_x=0;
3786 int size_y=0;
3787 int size_c=0;
3788
3789
3790 int i=0;
3791 int j=0;
3792 cpl_size k=0;
3793 int z=0;
3794 int pix=0;
3795 int sx=0;
3796 int sy=0;
3797
3798 double* px=NULL;
3799 const float* pdata=NULL;
3800 const float* pcoeffs=NULL;
3801 double pfit=0.;
3802 double* pgain=NULL;
3803 cpl_binary* pmask=NULL;
3804 double gain=0;
3805 const cpl_image* img_data=NULL;
3806
3807 const cpl_image* img_coeffs=NULL;
3808 cpl_image* bpm=NULL;
3809 cpl_mask* mask=NULL;
3810
3811 cpl_polynomial* pol=NULL;
3812
3813 size_x = cpl_vector_get_size(x);
3814 size_y = cpl_imagelist_get_size(y);
3815 size_c = cpl_imagelist_get_size(coeffs);
3816 img_data = cpl_imagelist_get_const(coeffs, 0);
3817 sx = cpl_image_get_size_x(img_data);
3818 sy = cpl_image_get_size_y(img_data);
3819 mask = cpl_mask_new(sx,sy);
3820
3821 cpl_ensure(size_x == size_y, CPL_ERROR_NULL_INPUT, NULL);
3822
3823 cpl_ensure(size_c == (order+1), CPL_ERROR_NULL_INPUT, NULL);
3824
3825 px = cpl_vector_get_data(x);
3826 pmask=cpl_mask_get_data(mask);
3827 pgain=cpl_table_get_data_double(gain_table,"GAIN");
3828 pol=cpl_polynomial_new(1);
3829 for (z = 0; z < size_x; z++) {
3830
3831 img_data = cpl_imagelist_get_const(y, z);
3832 pdata = cpl_image_get_data_float_const(img_data);
3833 gain=pgain[z];
3834
3835 for (j = 0; j < sy; j++) {
3836
3837 for (i = 0; i < sx; i++) {
3838
3839 pix = j * sx + i;
3840
3841 for (k = size_c-1; k >= 0; k--) {
3842
3843 img_coeffs = cpl_imagelist_get_const(coeffs, k);
3844 pcoeffs = cpl_image_get_data_float_const(img_coeffs);
3845 cpl_polynomial_set_coeff(pol, &k, pcoeffs[pix]);
3846
3847 }
3848
3849 pfit = cpl_polynomial_eval_1d(pol,px[z],NULL);
3850 if (pdata[pix] > 0) {
3851 if (fabs(pdata[pix] - pfit) > kappa * sqrt(gain*pdata[pix])) {
3852 pmask[pix] = CPL_BINARY_1;
3853 } // check if point to be flagged
3854 } // check if pos intensity
3855 } // i loop
3856 } // j loop
3857
3858 //cpl_image_delete(img_data);
3859
3860 } // z loop
3861 cpl_polynomial_delete(pol);
3862 if (bpmbin) {
3863 bpm = cpl_image_new_from_mask(mask);
3864 }
3865
3866 *nbpixs += cpl_mask_count(mask);
3867
3868 cpl_mask_delete(mask);
3869
3870 return bpm;
3871}
3872
3873*/
3874/*---------------------------------------------------------------------------*/
3886/*---------------------------------------------------------------------------*/
3887
3888static double
3889xsh_detmon_autocorr_factor(const cpl_image * image,
3890 cpl_image ** autocorr_image, int m, int n)
3891{
3892 cpl_image * mycorr_image = NULL;
3893 double autocorr = 0;
3894 cpl_error_code err = CPL_ERROR_NONE;
3895
3896 mycorr_image = xsh_detmon_image_correlate(image, image, m, n);
3897 err=cpl_error_get_code();
3898 if (err == CPL_ERROR_UNSUPPORTED_MODE)
3899 {
3900 cpl_msg_warning(cpl_func, "FFTW is not supported by CPL, autocorrelation "
3901 "would be computed using internal implementation");
3902 cpl_error_reset();
3903 if (mycorr_image)
3904 cpl_image_delete(mycorr_image);
3905 mycorr_image = xsh_detmon_autocorrelate(image, m, n);
3906 }
3907 if(mycorr_image == NULL) {
3908 return -1;
3909 }
3910
3911 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), -1);
3912
3913 autocorr = cpl_image_get_flux(mycorr_image);
3914
3915 if (autocorr_image) *autocorr_image = mycorr_image;
3916 else cpl_image_delete(mycorr_image);
3917
3918 return autocorr;
3919}
3920
3921static cpl_propertylist*
3922xsh_detmon_lg_extract_qclist_4plane(cpl_propertylist* linc_qclist,const int ip)
3923{
3924
3925 cpl_propertylist* sub_set=NULL;
3926 char* qc_key=NULL;
3927
3928 sub_set=cpl_propertylist_new();
3929 qc_key=cpl_sprintf("QC LIN COEF%d",ip);
3930 cpl_propertylist_copy_property_regexp(sub_set,linc_qclist,qc_key,0);
3931
3932 cpl_free(qc_key);
3933 return sub_set;
3934
3935}
3936
3937
3947static cpl_error_code
3949 cpl_propertylist* gaint_qclist,
3950 cpl_propertylist* lint_qclist,
3951 cpl_propertylist* linc_qclist,
3952 cpl_propertylist* bpm_qclist,
3953 int whichext)
3954{
3955
3956 cpl_propertylist * xplist = NULL;
3957
3958 const char * filename =
3959 cpl_frame_get_filename(cpl_frameset_get_position(frameset, 0));
3960
3961 xplist = cpl_propertylist_load_regexp(filename, whichext,
3962 "ESO DET|EXTNAME", 0);
3963 if (xsh_detmon_lg_config.exts >= 0)
3964 {
3965 /* for one extension, copy only extname keyword (if any) - DFS09856 */
3966 cpl_property* propExtname = NULL;
3967 propExtname = cpl_propertylist_get_property(xplist, "EXTNAME");
3968 cpl_error_reset();
3969 if (NULL != propExtname)
3970 {
3971 propExtname = cpl_property_duplicate(propExtname);
3972 }
3973 cpl_propertylist_delete(xplist);
3974 xplist = NULL;
3975 if (NULL != propExtname)
3976 {
3977 xplist = cpl_propertylist_new();
3978 cpl_propertylist_append_property(xplist, propExtname);
3979 cpl_property_delete(propExtname);
3980 }
3981 }
3982 if (NULL != xplist)
3983 {
3984 cpl_propertylist_append(gaint_qclist, xplist);
3985 cpl_propertylist_append(lint_qclist, xplist);
3986 cpl_propertylist_append(linc_qclist, xplist);
3987 cpl_propertylist_append(bpm_qclist, xplist);
3988 cpl_propertylist_delete(xplist);
3989 }
3990
3991 return cpl_error_get_code();
3992}
3993
3994
3995
3996
3997
3998/*---------------------------------------------------------------------------*/
4007/*---------------------------------------------------------------------------*/
4008static cpl_error_code
4010 const char* name_o,
4011 cpl_propertylist* xheader,
4012 unsigned CPL_IO_MODE)
4013{
4014
4015 cpl_propertylist* pro_keys=NULL;
4016
4017 pro_keys=xsh_detmon_load_pro_keys(name_o);
4018 cpl_propertylist_append(xheader,pro_keys);
4019
4020 if(CPL_IO_MODE==CPL_IO_DEFAULT) {
4021 cpl_propertylist * pri_head=cpl_propertylist_load(name_o,0);
4022 cpl_table_save(table, pri_head,xheader,name_o,
4023 CPL_IO_DEFAULT);
4024 cpl_propertylist_delete(pri_head);
4025
4026 } else {
4027 cpl_table_save(table,NULL,xheader,name_o,
4028 CPL_IO_EXTEND);
4029 }
4030 cpl_propertylist_delete(pro_keys);
4031
4032 return cpl_error_get_code();
4033}
4034
4035/*---------------------------------------------------------------------------*/
4043/*---------------------------------------------------------------------------*/
4044static cpl_error_code
4046 const char* name_o,
4047 cpl_propertylist* xheader)
4048{
4049
4050 cpl_propertylist* pro_keys=NULL;
4051 pro_keys=xsh_detmon_load_pro_keys(name_o);
4052 cpl_propertylist_append(xheader,pro_keys);
4053
4054 cpl_image_save(image,name_o, CPL_BPP_IEEE_FLOAT,
4055 xheader,CPL_IO_EXTEND);
4056 cpl_propertylist_delete(pro_keys);
4057
4058
4059 return cpl_error_get_code();
4060}
4061
4062/*---------------------------------------------------------------------------*/
4070/*---------------------------------------------------------------------------*/
4071static cpl_error_code
4073 const char* name_o,
4074 cpl_propertylist* xheader)
4075{
4076
4077 cpl_propertylist* pro_keys=NULL;
4078 pro_keys=xsh_detmon_load_pro_keys(name_o);
4079 cpl_propertylist_append(xheader,pro_keys);
4080
4081 cpl_imagelist_save(imagelist,name_o, CPL_BPP_IEEE_FLOAT,
4082 xheader,CPL_IO_EXTEND);
4083
4084 cpl_propertylist_delete(pro_keys);
4085
4086
4087 return cpl_error_get_code();
4088}
4089
4090/*---------------------------------------------------------------------------*/
4107static cpl_error_code
4108xsh_detmon_lg_save_plane(const cpl_parameterlist * parlist,
4109 cpl_frameset* frameset,
4110 const cpl_frameset * usedframes,
4111 int whichext,
4112 const char* recipe_name,
4113 cpl_propertylist* mypro_coeffscube,
4114 cpl_propertylist* linc_plane_qclist,
4115 const char* package,
4116 const char* NAME_O,
4117 cpl_image* plane)
4118{
4119 if(xsh_detmon_lg_config.exts == 0) {
4120 cpl_propertylist* plist=NULL;
4121 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4122 NULL, NULL,
4123 CPL_BPP_IEEE_FLOAT, recipe_name,
4124 mypro_coeffscube, NULL,
4125 package, NAME_O);
4126 plist=cpl_propertylist_load(NAME_O,0);
4127 cpl_image_save(plane,NAME_O, CPL_BPP_IEEE_FLOAT,
4128 plist,CPL_IO_DEFAULT);
4129 cpl_propertylist_delete(plist);
4130
4131 } else if(xsh_detmon_lg_config.exts > 0) {
4132 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4133 NULL, NULL,
4134 CPL_BPP_IEEE_FLOAT, recipe_name,
4135 mypro_coeffscube, NULL,
4136 package, NAME_O);
4137
4138 xsh_detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4139 } else {
4140 if(whichext == 1)
4141 {
4142 cpl_dfs_save_image(frameset, NULL, parlist,
4143 usedframes,NULL, NULL,
4144 CPL_BPP_IEEE_FLOAT, recipe_name,
4145 mypro_coeffscube, NULL,
4146 package, NAME_O);
4147 xsh_detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4148 } else {
4149
4150 xsh_detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
4151
4152 }
4153
4154 }
4155
4156 return cpl_error_get_code();
4157}
4158
4159
4160
4161/*---------------------------------------------------------------------------*/
4179static cpl_error_code
4180xsh_detmon_lg_save_cube(const cpl_parameterlist * parlist,
4181 cpl_frameset* frameset,
4182 const cpl_frameset * usedframes,
4183 int whichext,
4184 const char* recipe_name,
4185 cpl_propertylist* mypro_coeffscube,
4186 cpl_propertylist* linc_qclist,
4187 const char* package,
4188 const char* NAME_O,
4189 cpl_imagelist* coeffs)
4190{
4191
4192 if(xsh_detmon_lg_config.exts == 0) {
4193 cpl_propertylist_append(mypro_coeffscube, linc_qclist);
4195 (frameset, parlist, usedframes, coeffs,
4196 recipe_name, mypro_coeffscube, package,
4197 NAME_O);
4198 } else if(xsh_detmon_lg_config.exts > 0) {
4199 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4200 NULL, NULL,
4201 CPL_BPP_IEEE_FLOAT, recipe_name,
4202 mypro_coeffscube, NULL,
4203 package, NAME_O);
4204
4205 xsh_detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4206
4207 } else {
4208 if(whichext == 1) {
4209 cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4210 NULL, NULL,
4211 CPL_BPP_IEEE_FLOAT, recipe_name,
4212 mypro_coeffscube, NULL,
4213 package, NAME_O);
4214 if (coeffs)
4215 xsh_detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4216 else
4217 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4218 } else {
4219 if (coeffs)
4220 xsh_detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
4221 else
4222 cpl_propertylist_save(linc_qclist, NAME_O, CPL_IO_EXTEND);
4223 }
4224 }
4225
4226 return cpl_error_get_code();
4227}
4228
4229static char*
4231 int flag_sets,int which_set,
4232 int whichext,
4233 const char* paf_suf,
4234 cpl_propertylist** plist)
4235{
4236 char * paf_name=NULL;
4237
4238 if(xsh_detmon_lg_config.exts >= 0)
4239 {
4240 *plist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4242
4243 if(!flag_sets)
4244 {
4245 paf_name=cpl_sprintf("%s_%s.paf", xsh_detmon_lg_config.pafname,paf_suf);
4246 }
4247 else
4248 {
4249 paf_name=cpl_sprintf("%s_%s_set%02d.paf",
4250 xsh_detmon_lg_config.pafname, paf_suf,which_set);
4251 }
4252 }
4253 else
4254 {
4255 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4256 whichext);
4257
4258
4259 if(!flag_sets)
4260 {
4261 paf_name=cpl_sprintf("%s_%s_ext%02d.paf",
4262 xsh_detmon_lg_config.pafname, paf_suf,whichext);
4263 }
4264 else
4265 {
4266 paf_name=cpl_sprintf("%s_%s_set%02d_ext%02d.paf",
4267 xsh_detmon_lg_config.pafname,paf_suf,
4268 which_set, whichext);
4269 }
4270 }
4271
4272 return paf_name;
4273}
4274
4275
4276static char*
4278 int flag_sets,int which_set,
4279 int whichext,
4280 const char* paf_suf,
4281 cpl_propertylist** plist)
4282{
4283 char* paf_name=NULL;
4284
4285 if(xsh_detmon_lg_config.exts >= 0)
4286 {
4287 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4289
4290 if(!flag_sets)
4291 {
4292 paf_name=cpl_sprintf("%s_%s.paf", xsh_detmon_lg_config.pafname,paf_suf);
4293 } else
4294 {
4295 paf_name=cpl_sprintf("%s_%s_set%02d.paf",
4296 xsh_detmon_lg_config.pafname, paf_suf,which_set);
4297 }
4298 } else
4299 {
4300 *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4301 whichext);
4302 if(!flag_sets)
4303 {
4304 paf_name=cpl_sprintf("%s_%s_ext%02d.paf",
4305 xsh_detmon_lg_config.pafname, paf_suf,whichext);
4306 } else
4307 {
4308 paf_name=cpl_sprintf("%s_%s_set%02d_ext%02d.paf",
4309 xsh_detmon_lg_config.pafname,paf_suf,
4310 which_set, whichext);
4311 }
4312 }
4313 return paf_name;
4314
4315}
4316
4317static cpl_error_code
4318xsh_detmon_lg_save_paf_product(cpl_frame* ref_frame,int flag_sets,
4319 int which_set,int whichext,
4320 const char* pafregexp,
4321 const char* procatg,
4322 const char* pipeline_name,
4323 const char* recipe_name,
4324 const char* paf_suf,
4325 cpl_propertylist* qclist,
4326 const int ext)
4327
4328{
4329 /* Set the file name for the linearity table PAF */
4330 char* paf_name=NULL;
4331 cpl_propertylist* plist=NULL;
4332 cpl_propertylist* paflist = NULL;
4333 cpl_propertylist* mainplist=NULL;
4334
4335 mainplist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),0);
4336 if(ext==0) {
4337 paf_name=xsh_detmon_lg_set_paf_name_and_header(ref_frame,flag_sets,
4338 which_set,whichext,
4339 paf_suf,&plist);
4340 } else {
4341 paf_name=xsh_detmon_lg_set_paf_name_and_header_ext(ref_frame,flag_sets,
4342 which_set,whichext,
4343 paf_suf,&plist);
4344 }
4345
4346
4347 paflist = cpl_propertylist_new();
4348 cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,procatg);
4349
4350 /* Get the keywords for the paf file */
4351 cpl_propertylist_copy_property_regexp(paflist, plist,pafregexp, 0);
4352 cpl_propertylist_copy_property_regexp(paflist, mainplist,pafregexp, 0);
4353 cpl_propertylist_append(paflist,qclist);
4354
4355 /* Save the PAF */
4356 cpl_dfs_save_paf(pipeline_name, recipe_name,paflist,paf_name);
4357
4358 /* free memory */
4359 cpl_propertylist_delete(mainplist);
4360 cpl_propertylist_delete(paflist);
4361 cpl_propertylist_delete(plist);
4362 cpl_free(paf_name);
4363
4364 return cpl_error_get_code();
4365
4366}
4367
4368
4369
4370/*---------------------------------------------------------------------------*/
4401static cpl_error_code
4402xsh_detmon_lg_save(const cpl_parameterlist * parlist,
4403 cpl_frameset * frameset,
4404 const char *recipe_name,
4405 const char *pipeline_name,
4406 const char *pafregexp,
4407 const cpl_propertylist * pro_lintbl,
4408 const cpl_propertylist * pro_gaintbl,
4409 const cpl_propertylist * pro_coeffscube,
4410 const cpl_propertylist * pro_bpm,
4411 const cpl_propertylist * pro_corr,
4412 const cpl_propertylist * pro_diff,
4413 const char *package,
4414 cpl_imagelist * coeffs,
4415 cpl_table * gain_table,
4416 cpl_table * linear_table,
4417 cpl_image * bpms,
4418 cpl_imagelist * autocorr_images,
4419 cpl_imagelist * diff_flats,
4420 cpl_propertylist * gaint_qclist,
4421 cpl_propertylist * lint_qclist,
4422 cpl_propertylist * linc_qclist,
4423 cpl_propertylist * bpm_qclist,
4424 const int flag_sets,
4425 const int which_set,
4426 const cpl_frameset * usedframes,
4427 int whichext)
4428{
4429
4430 cpl_frame *ref_frame;
4431 cpl_propertylist *plist = NULL;
4432 cpl_propertylist *mainplist = NULL;
4433 char* NAME_O=NULL;
4434 char* PREF_O=NULL;
4435 int nb_images;
4436 int i;
4437
4438 cpl_propertylist * xplist = NULL;
4439
4440 cpl_propertylist* linc_plane_qclist=NULL;
4441 cpl_image* plane=NULL;
4442 int ip=0;
4443 char* pcatg_plane=NULL;
4444
4445 cpl_propertylist * mypro_lintbl =
4446 cpl_propertylist_duplicate(pro_lintbl);
4447 cpl_propertylist * mypro_gaintbl =
4448 cpl_propertylist_duplicate(pro_gaintbl);
4449 cpl_propertylist * mypro_coeffscube =
4450 cpl_propertylist_duplicate(pro_coeffscube);
4451 cpl_propertylist * mypro_bpm =
4452 cpl_propertylist_duplicate(pro_bpm);
4453 cpl_propertylist * mypro_corr =
4454 cpl_propertylist_duplicate(pro_corr);
4455 cpl_propertylist * mypro_diff =
4456 cpl_propertylist_duplicate(pro_diff);
4457
4458 const char * procatg_lintbl =
4459 cpl_propertylist_get_string(mypro_lintbl, CPL_DFS_PRO_CATG);
4460
4461 const char * procatg_gaintbl =
4462 cpl_propertylist_get_string(mypro_gaintbl, CPL_DFS_PRO_CATG);
4463
4464 const char * procatg_coeffscube =
4465 cpl_propertylist_get_string(mypro_coeffscube, CPL_DFS_PRO_CATG);
4466 const char * procatg_bpm =
4467 cpl_propertylist_get_string(mypro_bpm, CPL_DFS_PRO_CATG);
4468
4469
4470 /* Extract extension headers if multi-extension */
4471 xsh_detmon_lg_extract_extention_header(frameset,gaint_qclist,lint_qclist,
4472 linc_qclist,bpm_qclist,whichext);
4473
4474 /* This is only used later for PAF and temporarily for COEFFS_CUBE
4475 (see if defined)*/
4476 /* Get FITS header from reference file */
4477 ref_frame = cpl_frameset_get_position(frameset, 0);
4478
4479 skip_if((mainplist =
4480 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
4481 0)) == NULL);
4482
4483 /*******************************/
4484 /* Write the LINEARITY TABLE */
4485 /*******************************/
4486 cpl_msg_info(cpl_func,"Write the LINEARITY TABLE");
4487 /* Set the file name for the table */
4488 if(!flag_sets) {
4489 NAME_O=cpl_sprintf("%s_linearity_table.fits", recipe_name);
4490 } else {
4491 NAME_O=cpl_sprintf("%s_linearity_table_set%02d.fits", recipe_name,
4492 which_set);
4493 }
4494
4495 if (xsh_detmon_lg_config.exts >= 0) {
4496 /* Save the table */
4497 cpl_propertylist_append(mypro_lintbl, lint_qclist);
4498 skip_if(cpl_dfs_save_table(frameset, NULL,parlist, usedframes, NULL,
4499 linear_table,NULL, recipe_name,
4500 mypro_lintbl, NULL, package, NAME_O));
4501
4502 xsh_detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4503 lint_qclist,CPL_IO_DEFAULT);
4504
4505 } else {
4506 if(whichext == 1) {
4507 /* Save the 1. extension table */
4508 skip_if(cpl_dfs_save_table(frameset,NULL, parlist, usedframes, NULL,
4509 linear_table,lint_qclist, recipe_name,
4510 mypro_lintbl,NULL, package, NAME_O));
4511 xsh_detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4512 lint_qclist,CPL_IO_DEFAULT);
4513
4514
4515
4516
4517 } else {
4518
4519 xsh_detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
4520 lint_qclist,CPL_IO_EXTEND);
4521 }
4522 }
4523 irplib_free(&NAME_O);
4524 /**************************/
4525 /* Write the GAIN TABLE */
4526 /**************************/
4527 cpl_msg_info(cpl_func,"Write the GAIN TABLE");
4528 /* Set the file name for the table */
4529 if(!flag_sets) {
4530 NAME_O=cpl_sprintf("%s_gain_table.fits", recipe_name);
4531 } else {
4532 NAME_O=cpl_sprintf("%s_gain_table_set%02d.fits", recipe_name,
4533 which_set);
4534 }
4535
4536 if (xsh_detmon_lg_config.exts >= 0)
4537 {
4538 /* Save the table */
4539
4540 cpl_propertylist_append(mypro_gaintbl, gaint_qclist);
4541 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
4542 gain_table,NULL, recipe_name, mypro_gaintbl,
4543 NULL, package, NAME_O));
4545 gaint_qclist,CPL_IO_DEFAULT);
4546
4547 }
4548 else
4549 {
4550 if(whichext == 1)
4551 {
4552 /* Save the 1. extension table */
4553 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL, gain_table,
4554 gaint_qclist, recipe_name, mypro_gaintbl,
4555 NULL, package, NAME_O));
4557 gaint_qclist,CPL_IO_DEFAULT);
4558
4559 }
4560 else
4561 {
4562
4564 gaint_qclist,CPL_IO_EXTEND);
4565 }
4566 }
4567
4568 if(xsh_detmon_lg_config.pix2pix)
4569 {
4570
4571 /***************************/
4572 /* Write the COEFFS FITS */
4573 /***************************/
4574 cpl_msg_info(cpl_func,"Write the COEFFS FITS");
4575 irplib_free(&NAME_O);
4576 if(!flag_sets)
4577 {
4578 PREF_O=cpl_sprintf("%s_coeffs_cube", recipe_name);
4579 } else
4580 {
4581 PREF_O=cpl_sprintf("%s_coeffs_cube_set%02d",
4582 recipe_name, which_set);
4583 }
4584 if (xsh_detmon_lg_config.split_coeffs == 0) {
4585 NAME_O=cpl_sprintf("%s.fits", PREF_O);
4586 }
4587
4588
4589 /* Save the imagelist */
4590 if(xsh_detmon_lg_config.split_coeffs != 0){
4591
4592
4593 nb_images = cpl_imagelist_get_size(coeffs);
4594 for(ip=0;ip<nb_images;ip++) {
4595 NAME_O=cpl_sprintf("%s_P%d.fits", PREF_O,ip);
4596 pcatg_plane=cpl_sprintf("COEFFS_CUBE_P%d",ip);
4597 cpl_propertylist_delete(mypro_coeffscube);
4598 mypro_coeffscube=cpl_propertylist_duplicate(pro_coeffscube);
4599 cpl_propertylist_set_string(mypro_coeffscube,CPL_DFS_PRO_CATG,
4600 pcatg_plane);
4601 linc_plane_qclist=xsh_detmon_lg_extract_qclist_4plane(linc_qclist,ip);
4602 cpl_propertylist_append(mypro_coeffscube, linc_plane_qclist);
4603 plane=cpl_imagelist_get(coeffs,ip);
4604 xsh_detmon_lg_save_plane(parlist,frameset,usedframes,whichext,
4605 recipe_name,mypro_coeffscube,
4606 linc_plane_qclist,package,NAME_O,plane);
4607
4608 if(NULL!=linc_plane_qclist) {
4609 cpl_propertylist_delete(linc_plane_qclist);
4610 }
4611 irplib_free(&NAME_O);
4612
4613 } /* end for loop over cube planes */
4614 } else {
4615
4616 xsh_detmon_lg_save_cube(parlist,frameset,usedframes,whichext,
4617 recipe_name,mypro_coeffscube,
4618 linc_qclist,package,NAME_O,coeffs);
4619 }
4620
4621 /*******************************/
4622 /* Write the BAD PIXEL MAP */
4623 /*******************************/
4624 cpl_msg_info(cpl_func,"Write the BAD PIXEL MAP");
4625 irplib_free(&NAME_O);
4626 /* Set the file name for the bpm */
4627 if(!flag_sets)
4628 {
4629 NAME_O=cpl_sprintf("%s_bpm.fits", recipe_name);
4630 } else
4631 {
4632 NAME_O=cpl_sprintf("%s_bpm_set%02d.fits", recipe_name, which_set);
4633 }
4634
4635
4636 /* Save the image */
4637 if(xsh_detmon_lg_config.exts == 0) {
4638 cpl_propertylist_append(mypro_bpm, bpm_qclist);
4639 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL, bpms,
4640 CPL_BPP_IEEE_FLOAT, recipe_name,
4641 mypro_bpm, NULL, package,
4642 NAME_O);
4643 }
4644 else if(xsh_detmon_lg_config.exts > 0)
4645 {
4646 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4647 CPL_BPP_IEEE_FLOAT, recipe_name,
4648 mypro_bpm, NULL, package,
4649 NAME_O));
4650 xsh_detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4651
4652 } else
4653 {
4654 if (whichext == 1)
4655 {
4656 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
4657 CPL_BPP_IEEE_FLOAT, recipe_name,
4658 mypro_bpm, NULL, package,
4659 NAME_O));
4660 xsh_detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4661 } else
4662 {
4663 xsh_detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
4664 }
4665 }
4666 } /* End of if(pix2pix) */
4667
4668 if(xsh_detmon_lg_config.intermediate)
4669 {
4670 /******************************/
4671 /* Write the AUTOCORRS FITS */
4672 /******************************/
4673 cpl_msg_info(cpl_func,"Write the AUTOCORRS FITS");
4674 nb_images = cpl_imagelist_get_size(autocorr_images);
4675 cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
4676 for(i = 0; i < nb_images; i++)
4677 {
4678 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_corr);
4679 int inull = 0;
4680 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4681 double ddit = 0;
4682 if(i < cpl_table_get_nrow(linear_table))
4683 {
4684 ddit = cpl_table_get_double(linear_table,
4685 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4686 }
4687 cpl_array_delete(pnames);
4688 /*cpl_propertylist_append_double(pplist, "ESO DET DIT", ddit);*/
4689 /* Set the file name for each image */
4690 irplib_free(&NAME_O);
4691 if(!flag_sets)
4692 {
4693 NAME_O=cpl_sprintf("%s_autocorr_%d.fits", recipe_name, i);
4694 assert(NAME_O != NULL);
4695 } else
4696 {
4697 NAME_O=cpl_sprintf("%s_autocorr_%02d_set%02d.fits",
4698 recipe_name, i, which_set);
4699 assert(NAME_O != NULL);
4700 }
4701 /* Save the image */
4702 if(xsh_detmon_lg_config.exts > 0)
4703 {
4704 cpl_propertylist* pextlist = cpl_propertylist_new();
4705 cpl_propertylist_append_double(pextlist, "ESO DET DIT", ddit);
4706 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4707 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4708 recipe_name, pplist, NULL,
4709 package, NAME_O));
4710
4712 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4713
4714 cpl_propertylist_delete(pextlist);
4715 } else
4716 if(xsh_detmon_lg_config.exts == 0)
4717 {
4718 cpl_propertylist_append_double(pplist, "ESO DET DIT", ddit);
4719 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
4720 cpl_imagelist_get(autocorr_images, i),
4721 CPL_BPP_IEEE_FLOAT,
4722 recipe_name, pplist, NULL, package,
4723 NAME_O);
4724
4725 }
4726 else
4727 {
4728 cpl_propertylist* pextlist = cpl_propertylist_new();
4729 cpl_propertylist_append_double(pextlist, "ESO DET DIT", ddit);
4730 if(whichext == 1)
4731 {
4732 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4733 usedframes, NULL,NULL,
4734 CPL_BPP_IEEE_FLOAT, recipe_name,
4735 pplist, NULL,
4736 package, NAME_O));
4737
4739 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4740
4741 } else
4742 {
4743
4745 cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
4746 }
4747 cpl_propertylist_delete(pextlist);
4748 }
4749 cpl_propertylist_delete (pplist);
4750 }
4751 irplib_free(&NAME_O);
4752
4753
4754 /*
4755 cpl_msg_info(cpl_func, "-----before Write the DIFFS FITS %d", __LINE__);
4756 */
4757 /***************************/
4758 /* Write the DIFFS FITS */
4759 /***************************/
4760 cpl_msg_info(cpl_func,"Write the DIFFS FITS");
4761
4762 for(i = 0; i < nb_images; i++)
4763 {
4764 cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_diff);
4765 int inull = 0;
4766 cpl_array* pnames = cpl_table_get_column_names(linear_table);
4767 double ddit = 0;
4768 if(i < cpl_table_get_nrow(linear_table))
4769 {
4770 ddit = cpl_table_get_double(linear_table,
4771 cpl_array_get_data_string_const(pnames)[0], i, &inull);
4772 }
4773 cpl_array_delete(pnames);
4774 /*cpl_propertylist_append_double(pplist, "ESO DET DIT", ddit);*/
4775 /* Set the file name for each image */
4776 if(!flag_sets)
4777 {
4778 NAME_O=cpl_sprintf("%s_diff_flat_%d.fits", recipe_name, i);
4779 } else
4780 {
4781 NAME_O=cpl_sprintf("%s_diff_flat_%d_set%02d.fits",
4782 recipe_name, i, which_set);
4783 }
4784 /* Save the image */
4785 if(xsh_detmon_lg_config.exts > 0)
4786 {
4787 cpl_propertylist* pextlist = cpl_propertylist_new();
4788 cpl_propertylist_append_double(pextlist, "ESO DET DIT", ddit);
4789 cpl_propertylist_append_double(mypro_diff, "ESO DET DIT", ddit);
4790 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
4791 NULL,NULL,CPL_BPP_IEEE_FLOAT,
4792 recipe_name,
4793 mypro_diff, NULL,package, NAME_O));
4794
4796 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4797
4798 cpl_propertylist_delete(pextlist);
4799 }
4800 else if(xsh_detmon_lg_config.exts == 0)
4801 {
4802 cpl_propertylist_append_double(pplist, "ESO DET DIT", ddit);
4803 cpl_dfs_save_image
4804 (frameset, NULL, parlist, usedframes, NULL,
4805 cpl_imagelist_get(diff_flats, i), CPL_BPP_IEEE_FLOAT,
4806 recipe_name, pplist, NULL, package,
4807 NAME_O);
4808
4809 } else
4810 {
4811 cpl_propertylist* pextlist = cpl_propertylist_new();
4812 cpl_propertylist_append_double(pextlist, "ESO DET DIT", ddit);
4813 if(whichext == 1)
4814 {
4815 cpl_propertylist_append_double(mypro_diff,"ESO DET DIT",ddit);
4816 // cpl_propertylist_erase(mypro_diff, "ESO DET DIT");
4817 skip_if(cpl_dfs_save_image(frameset, NULL, parlist,
4818 usedframes, NULL,NULL,
4819 CPL_BPP_IEEE_FLOAT, recipe_name,
4820 mypro_diff, NULL,package, NAME_O));
4821
4823 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4824
4825 } else
4826 {
4827
4829 cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
4830
4831 }
4832 cpl_propertylist_delete(pextlist);
4833 }
4834 cpl_propertylist_delete(pplist);
4835 irplib_free(&NAME_O);
4836 }
4837 } /* End of if(intermediate) */
4838
4839
4840 /*******************************/
4841 /* Write the PAF file(s) */
4842 /*******************************/
4843 cpl_msg_info(cpl_func,"Write the PAF file(s)");
4844
4845 if(xsh_detmon_lg_config.pafgen) {
4846
4847 xsh_detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4848 pafregexp,procatg_gaintbl,
4849 pipeline_name,recipe_name,
4850 "qc01",gaint_qclist,0);
4851
4852 xsh_detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
4853 pafregexp,procatg_lintbl,
4854 pipeline_name,recipe_name,
4855 "qc02",lint_qclist,0);
4856
4857 if(xsh_detmon_lg_config.pix2pix)
4858 {
4859
4860 xsh_detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4861 whichext,pafregexp,
4862 procatg_coeffscube,
4863 pipeline_name,recipe_name,
4864 "qc03",linc_qclist,1);
4865
4866 xsh_detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
4867 whichext,pafregexp,procatg_bpm,
4868 pipeline_name,recipe_name,
4869 "qc04",bpm_qclist,1);
4870 }
4871 }
4872
4873 end_skip;
4874 cpl_msg_info(cpl_func,"exit");
4875
4876 cpl_propertylist_delete(xplist);
4877 if(plist!=NULL) {
4878 cpl_propertylist_delete(plist);
4879 plist=NULL;
4880 }
4881
4882 irplib_free(&NAME_O);
4883 cpl_free(PREF_O);
4884 cpl_free(pcatg_plane);
4885 cpl_propertylist_delete(mainplist);
4886 cpl_propertylist_delete(mypro_lintbl);
4887 cpl_propertylist_delete(mypro_gaintbl);
4888 cpl_propertylist_delete(mypro_coeffscube);
4889 cpl_propertylist_delete(mypro_bpm);
4890 cpl_propertylist_delete(mypro_corr);
4891 cpl_propertylist_delete(mypro_diff);
4892
4893 return cpl_error_get_code();
4894}
4895
4896
4897/*---------------------------------------------------------------------------*/
4905/*---------------------------------------------------------------------------*/
4906static cpl_error_code
4907xsh_detmon_opt_contamination(const cpl_imagelist * ons,
4908 const cpl_imagelist * offs,
4909 unsigned mode,
4910 cpl_propertylist * qclist)
4911{
4912 struct rect {
4913 size_t llx;
4914 size_t lly;
4915 size_t urx;
4916 size_t ury;
4917 };
4918 struct rect rects[5] = {
4919 (struct rect){ xsh_detmon_lg_config.llx1,
4923 (struct rect){ xsh_detmon_lg_config.llx2,
4927 (struct rect){ xsh_detmon_lg_config.llx3,
4931 (struct rect){ xsh_detmon_lg_config.llx4,
4935 (struct rect){ xsh_detmon_lg_config.llx5,
4939 };
4940
4941 for (size_t i = 0; i < 5; i++) {
4942 cpl_image * dif_avg;
4943 const cpl_image * off2;
4944 double median;
4945 char kname[300];
4946 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
4947 off2 = cpl_imagelist_get_const(offs, 0);
4948 else
4949 off2 = cpl_imagelist_get_const(offs, 1);
4950
4951 dif_avg = xsh_detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
4952 cpl_imagelist_get_const(offs, 0),
4953 cpl_imagelist_get_const(ons, 1),
4954 off2,
4955 rects[i].llx,
4956 rects[i].lly,
4957 rects[i].urx,
4958 rects[i].ury);
4959
4960 median = cpl_image_get_median(dif_avg);
4961 cpl_image_delete(dif_avg);
4962
4963 skip_if(0);
4964 sprintf(kname, "%s%d", DETMON_QC_CONTAM, i + 1);
4965
4966 if(cpl_propertylist_has(qclist,kname)){
4967 skip_if(cpl_propertylist_update_double(qclist,kname,median));
4968 } else {
4969 skip_if(cpl_propertylist_append_double(qclist,kname,median));
4970 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
4971 }
4972 }
4973
4974 end_skip;
4975
4976 return cpl_error_get_code();
4977}
4978
4979/*---------------------------------------------------------------------------*/
4987/*---------------------------------------------------------------------------*/
4988int
4990 const char *tag_on, const char *tag_off)
4991{
4992
4993
4994
4995
4996
4997 /* Check entries */
4998 if(set == NULL)
4999 return -1;
5000
5001 /* Initialize */
5002 int nframes = cpl_frameset_get_size(set);
5003
5004 /* Loop on frames */
5005 for(int i = 0; i < nframes; i++) {
5006 cpl_frame* cur_frame = cpl_frameset_get_position(set, i);
5007 const char* tag = cpl_frame_get_tag(cur_frame);
5008
5009 /* RAW frames */
5010 if(!strcmp(tag, tag_on) || !strcmp(tag, tag_off))
5011 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
5012 /* CALIB frames */
5013
5014 /* else if (!strcmp(tag, IIINSTRUMENT_CALIB_FLAT))
5015 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_CALIB);
5016 */
5017 }
5018 return 0;
5019}
5020
5021
5022/*---------------------------------------------------------------------------*/
5030/*---------------------------------------------------------------------------*/
5031static cpl_error_code
5032xsh_detmon_lg_fits_coeffs_and_bpm2chip(cpl_imagelist ** coeffs_ptr,
5033 cpl_image **bpms_ptr)
5034{
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044 int shift_idx=0;
5045
5046
5047
5048
5049 cpl_image* dummy_bpm = cpl_image_new(xsh_detmon_lg_config.nx,
5051 CPL_TYPE_INT);
5052 cpl_imagelist* dummy_coeffs = cpl_imagelist_new();
5053
5054 int* db_p = cpl_image_get_data_int(dummy_bpm);
5055 int* rb_p = cpl_image_get_data_int(*bpms_ptr);;
5056 float** dcs_p = cpl_malloc(sizeof(float *) * (xsh_detmon_lg_config.order + 1));
5057 float** rcs_p = cpl_malloc(sizeof(float *) * (xsh_detmon_lg_config.order + 1));
5058 int dlength = xsh_detmon_lg_config.nx;
5059
5060 int rlength = xsh_detmon_lg_config.urx - xsh_detmon_lg_config.llx + 1;
5061 for (int i = 0; i <= xsh_detmon_lg_config.order; i++)
5062 {
5063 cpl_image* dummy_coeff = cpl_image_new(xsh_detmon_lg_config.nx,
5065 CPL_TYPE_FLOAT);
5066
5067 cpl_imagelist_set(dummy_coeffs, dummy_coeff, i);
5068 dcs_p[i] = cpl_image_get_data_float(dummy_coeff);
5069 rcs_p[i] = cpl_image_get_data_float(cpl_imagelist_get(*coeffs_ptr, i));
5070 }
5071 /*copy the coefficients from temporary image to the dummy_bpm*/
5072 for (int i = xsh_detmon_lg_config.lly - 1; i < xsh_detmon_lg_config.ury; i++)
5073 {
5074 for (int j = xsh_detmon_lg_config.llx - 1; j < xsh_detmon_lg_config.urx; j++)
5075 {
5076 shift_idx=(i - xsh_detmon_lg_config.lly + 1) * rlength +
5077 j - xsh_detmon_lg_config.llx + 1;
5078 *(db_p + i * dlength + j) = *(rb_p + shift_idx);
5079 for (int k = 0; k <= xsh_detmon_lg_config.order; k++)
5080 {
5081 *(dcs_p[k] + i * dlength + j) =
5082 *(rcs_p[k] + (i - xsh_detmon_lg_config.lly + 1) * rlength +
5083 j - xsh_detmon_lg_config.llx + 1);
5084 }
5085 }
5086 }
5087 cpl_imagelist_delete(*coeffs_ptr);
5088 cpl_image_delete(*bpms_ptr);
5089 *coeffs_ptr = dummy_coeffs;
5090 *bpms_ptr = dummy_bpm;
5091 cpl_free(dcs_p);
5092 cpl_free(rcs_p);
5093
5094 return cpl_error_get_code();
5095}
5096
5097/* Not used so we temporaryly comment it out
5098static cpl_error_code
5099xsh_detmon_lg_qclog_lin_coeff(cpl_imagelist* coeffs_ptr, const int order, cpl_propertylist* linc_qclist)
5100{
5101 cpl_image* image=NULL;
5102 int i=0;
5103 double coeff=0;
5104 double * pcoeffs = cpl_malloc(sizeof(double)*(order + 1));
5105 char* name_o1=NULL;
5106 char* name_o2=NULL;
5107
5108 for(i = 0; i <= order; i++)
5109 {
5110 image = cpl_imagelist_get(coeffs_ptr, i);
5111 coeff = cpl_image_get_median(image);
5112 pcoeffs[i] = coeff;
5113 name_o1 = cpl_sprintf("ESO QC LIN COEF%d", i);
5114 name_o2 = cpl_sprintf("ESO QC LIN COEF%d ERR", i);
5115 assert(name_o1 != NULL);
5116 assert(name_o2 != NULL);
5117 cpl_propertylist_append_double(linc_qclist, name_o1, coeff);
5118 cpl_propertylist_set_comment(linc_qclist,name_o1,DETMON_QC_LIN_COEF_C);
5119 cpl_free(name_o1);
5120 name_o1= NULL;
5121 cpl_propertylist_append_double(linc_qclist, name_o2,cpl_image_get_stdev(image));
5122 cpl_propertylist_set_comment(linc_qclist,name_o2,DETMON_QC_LIN_COEF_ERR_C);
5123 cpl_free(name_o2);
5124 name_o2= NULL;
5125 }
5126 cpl_free(pcoeffs);
5127
5128 return cpl_error_get_code();
5129}
5130*/
5131#ifdef DETMON_USE_DETECTOR_SHOTNOISE_MODEL
5132/*----------------------------------------------------------------------------*/
5153/*----------------------------------------------------------------------------*/
5154cpl_error_code
5155xsh_detmon_detector_shotnoise_model(const cpl_image* ima_data, const double gain,
5156 const double ron, cpl_image ** ima_errs)
5157{
5158 cpl_ensure_code(ima_data, CPL_ERROR_NULL_INPUT);
5159 cpl_ensure_code(ima_errs, CPL_ERROR_NULL_INPUT);
5160 cpl_ensure_code(gain > 0., CPL_ERROR_ILLEGAL_INPUT);
5161 cpl_ensure_code(ron > 0., CPL_ERROR_ILLEGAL_INPUT);
5162
5163 *ima_errs = cpl_image_duplicate(ima_data);
5164 /* set negative values (= zero measurable electrons) to read out noise */
5165 cpl_image_threshold(*ima_errs, 0., INFINITY, ron, ron);
5166
5167 /* err_ADU = sqrt(counts/gain + ron * ron)*/
5168
5169 cpl_image_divide_scalar(*ima_errs, gain);
5170 cpl_image_add_scalar(*ima_errs, ron * ron);
5171 cpl_image_power(*ima_errs, 0.5);
5172
5173 return cpl_error_get_code();
5174}
5175#endif
5176
5177int
5178xsh_detmon_compute_badpixmap(cpl_boolean opt_nir, const int nsets,
5179 const cpl_table* linear_table,
5180 const cpl_imagelist* linearity_inputs, int nbpixs,
5181 cpl_vector* x, cpl_propertylist* gaint_qclist,
5182 cpl_image** bpms_ptr)
5183{
5184 /* Here determines the bad pixel map
5185 * HDRL based version
5186 * AMO: this if is repeated: the following code should be up up
5187 */
5188 if (opt_nir == NIR) {
5189 x = cpl_vector_wrap(nsets,
5190 (double *) cpl_table_get_data_double_const(linear_table,
5191 "DIT"));
5192 }
5193 else {
5194 x = cpl_vector_wrap(nsets,
5195 (double *) cpl_table_get_data_double_const(linear_table,
5196 "EXPTIME"));
5197
5198 }
5199 int sz = cpl_imagelist_get_size(linearity_inputs);
5200 //int sx = cpl_image_get_size_x(cpl_imagelist_get_const(linearity_inputs, 0));
5201 //int sy = cpl_image_get_size_y(cpl_imagelist_get_const(linearity_inputs, 0));
5202 double kappa = xsh_detmon_lg_config.kappa;
5203 int niter = xsh_detmon_lg_config.niter;
5204 int llx = xsh_detmon_lg_config.llx;
5205 int urx = xsh_detmon_lg_config.urx;
5206 int lly = xsh_detmon_lg_config.lly;
5207 int ury = xsh_detmon_lg_config.ury;
5208 hdrl_parameter* p;
5209 //double median;
5210 cpl_image *ima, *err;
5211 // fit-chi-rel method
5212 // errors to be used with fit_chi_rel method
5213 cpl_imagelist* errors = cpl_imagelist_new();
5214 /*
5215 // case1: error proportional to sqrt(EXPTIME)
5216 for(int i=0;i<sz;i++) {
5217 err=cpl_image_new(sx,sy,CPL_TYPE_DOUBLE);
5218 cpl_image_add_scalar(err,1.);
5219 cpl_imagelist_set(errors,err,i);
5220 }
5221 */
5222 /*
5223 // case2:shot noise model to be used with fit_chi_rel method
5224 double gain=1.;
5225 double ron=1.;
5226 for(int i=0;i<sz;i++) {
5227 ima=cpl_imagelist_get(linearity_inputs,i);
5228 hdrldemo_detector_shotnoise_model(ima, gain, ron, &err);
5229 cpl_imagelist_set(errors,err,i);
5230 }
5231 */
5232 // case3: error obtained using mad error approximation
5233 double dmad;
5234 //cpl_msg_info(cpl_func,"sz=%d",sz);
5235 cpl_imagelist* linearity_scaled = cpl_imagelist_new();
5236 double gain = 0;
5237 gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
5238 //cpl_msg_info(cpl_func,"ok1 gain=%g",gain);
5239 /* on simulations gain ,may be < 0: make sure it is > 0 */
5240 //cpl_msg_info(cpl_func,"ok1 gain=%g",gain);
5241 gain = (gain < 0) ? 1 : gain;
5242 double avg = 0;
5243 double rms = 0;
5244 skip_if(rms);
5245 //cpl_msg_info(cpl_func,"sz=%d",sz);
5246 //cpl_msg_info(cpl_func,"llx=%d lly=%d urx=%d ury=%d",llx,lly,urx,ury);
5247 for (int i = 0; i < sz; i++) {
5248 ima = cpl_imagelist_get_const(linearity_inputs, i);
5249 /*
5250 cpl_msg_info(cpl_func,"sx=%d sy=%d",
5251 cpl_image_get_size_x(ima),cpl_image_get_size_y(ima));
5252 */
5253 //cpl_msg_info(cpl_func,"max_x=%d max_y=%d",urx-llx+1,ury-lly+1);
5254 //median=cpl_image_get_median_window(ima,1,1,urx-llx+1,ury-lly+1);
5255 skip_if(
5256 xsh_ksigma_clip(ima, 1, 1, urx - llx + 1,
5257 ury - lly + 1, kappa, niter, 1e-5, &avg,
5258 &rms));
5259
5260 //cpl_msg_info(cpl_func,"avg=%g median=%g",avg,median);
5261 //cpl_msg_info(cpl_func,"thresh=%g", xsh_detmon_lg_config.saturation_limit);
5262 if (avg < xsh_detmon_lg_config.saturation_limit) {
5263
5264 //cpl_msg_info(cpl_func,">>>>i=%d", i);
5265 /*
5266 err=cpl_image_duplicate(ima);
5267 cpl_image_multiply_scalar(err, gain);
5268 cpl_image_power(err,0.5);
5269 */
5270 cpl_image_get_mad(ima, &dmad);
5271 err = cpl_image_duplicate(ima);
5272 cpl_image_multiply_scalar(err, 0);
5273 cpl_image_add_scalar(err, dmad * CPL_MATH_STD_MAD);
5274
5275 //xsh_detmon_detector_shotnoise_model(ima, gain_eff,ron, &err);
5276 /*
5277 cpl_msg_info(cpl_func,"err sx=%d",cpl_image_get_size_x(err));
5278 cpl_msg_info(cpl_func,"err sy=%d",cpl_image_get_size_y(err));
5279 cpl_msg_info(cpl_func,"ima sx=%d",cpl_image_get_size_x(ima));
5280 cpl_msg_info(cpl_func,"ima sy=%d",cpl_image_get_size_y(ima));
5281 cpl_msg_info(cpl_func,"sy=%d",cpl_image_get_size_y(err));
5282 */
5283 cpl_imagelist_set(errors, err, i);
5284 /*
5285 sprintf(dname,"data_%d.fits",i);
5286 sprintf(ename,"errs_%d.fits",i);
5287 cpl_image_save(err, ename, CPL_BPP_IEEE_FLOAT,NULL,CPL_IO_DEFAULT);
5288 cpl_image_save(ima, dname, CPL_BPP_IEEE_FLOAT,NULL,CPL_IO_DEFAULT);
5289 */
5290 skip_if(
5291 cpl_imagelist_set(linearity_scaled,
5292 cpl_image_duplicate(ima), i));
5293 }
5294 }
5295 hdrl_imagelist* hil = hdrl_imagelist_create(linearity_scaled, errors);
5296 /*
5297 cpl_imagelist_save(linearity_scaled,"lin_data.fits", CPL_BPP_IEEE_FLOAT,NULL,CPL_IO_DEFAULT);
5298 cpl_imagelist_save(errors,"lin_errs.fits", CPL_BPP_IEEE_FLOAT,NULL,CPL_IO_DEFAULT);
5299 */
5300 cpl_imagelist_delete(errors);
5301 /* P-val method */
5302 double pval = 0.001;
5303 p = hdrl_bpm_fit_parameter_create_pval(1, pval);
5304 /*
5305 p = hdrl_bpm_fit_parameter_create_rel_coef(1, 1., 1.);
5306 hdrl_parameter_delete(p);
5307 */
5308 /* chi-rel method
5309 int ord=xsh_detmon_lg_config.order;
5310 p = hdrl_bpm_fit_parameter_create_rel_chi(1, kappa, kappa);
5311 */
5312 hdrl_bpm_fit_compute(p, hil, x, bpms_ptr);
5313 //cpl_vector_dump(x,stdout);
5314 /*
5315 // bpm-3D method
5316 cpl_imagelist* linearity_scaled=cpl_imagelist_new();
5317
5318 for(int i=0;i<sz;i++) {
5319 ima=cpl_imagelist_get(linearity_inputs,i);
5320 median=cpl_image_get_median(ima);
5321 if(median < xsh_detmon_lg_config.saturation_limit) {
5322 cpl_image_divide_scalar(ima,median);
5323 cpl_imagelist_set(linearity_scaled,cpl_image_duplicate(ima),i);
5324 }
5325 }
5326 hdrl_imagelist* hil= hdrl_imagelist_create(linearity_scaled,NULL);
5327
5328
5329 // bpm-3D method
5330 hdrl_bpm_3d_method method = HDRL_BPM_3D_THRESHOLD_RELATIVE ;
5331 p=hdrl_bpm_3d_parameter_create(kappa, kappa, method) ;
5332 cpl_imagelist * out_imlist = hdrl_bpm_3d_compute(hil, p);
5333 *bpms_ptr = cpl_imagelist_collapse_create(out_imlist);
5334 cpl_msg_info(cpl_func,"BP map value: min=%g max=%g",
5335 cpl_image_get_min(*bpms_ptr),cpl_image_get_max(*bpms_ptr));
5336 */
5337 nbpixs = cpl_image_get_flux(*bpms_ptr);
5338 /* clean-up memory */
5339 hdrl_imagelist_delete(hil);
5340 cpl_imagelist_delete(linearity_scaled);
5341 cpl_vector_unwrap((cpl_vector*) x);
5342 hdrl_parameter_delete(p);
5343 // 3D method only
5344 //cpl_imagelist_delete(out_imlist);
5345 /* ORIGINAL BP MAP COMPUTATION
5346 *bpms_ptr = xsh_detmon_bpixs(*coeffs_ptr, xsh_detmon_lg_config.bpmbin,
5347 xsh_detmon_lg_config.kappa, &nbpixs);
5348 */
5349 /*
5350 *bpms_ptr = xsh_detmon_bpixs2(x,linearity_inputs,*coeffs_ptr,gain_table,
5351 xsh_detmon_lg_config.order,xsh_detmon_lg_config.bpmbin,xsh_detmon_lg_config.kappa,&nbpixs);
5352 */
5353 /*
5354 cpl_vector_unwrap((cpl_vector*)x);
5355 cpl_vector_unwrap((cpl_vector*)y);
5356 */
5357 //cpl_msg_info(cpl_func,"nbpixs=%d",nbpixs);
5358 skip_if(*bpms_ptr == NULL);
5359
5360 end_skip;
5361 return nbpixs;
5362}
5363
5364/*---------------------------------------------------------------------------*/
5378/*---------------------------------------------------------------------------*/
5379static cpl_error_code
5380xsh_detmon_lg_reduce_all(const cpl_table * linear_table,
5381 cpl_propertylist * gaint_qclist,
5382 cpl_propertylist * lint_qclist,
5383 cpl_propertylist * linc_qclist,
5384 cpl_propertylist * bpm_qclist,
5385 cpl_imagelist ** coeffs_ptr,
5386 cpl_image ** bpms_ptr,
5387 const cpl_imagelist * linearity_inputs,
5388 const cpl_table * gain_table,
5389 int which_ext, cpl_boolean opt_nir)
5390{
5391
5392 int nbpixs = 0;
5393 const int linear_nsets = cpl_table_get_nrow(linear_table);
5394 const int gain_nsets = cpl_table_get_nrow(gain_table);
5395 double autocorr;
5396 cpl_polynomial *poly_linfit = NULL;
5397 cpl_image *fiterror = NULL;
5398 char * name_o1 = NULL;
5399 char * name_o2 = NULL;
5400 double * pcoeffs = NULL;
5401 unsigned mode = xsh_detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
5402 double min_val=0;
5403 double max_val=0;
5404 cpl_vector *x =NULL;
5405 const cpl_vector *y =NULL;
5406
5407
5408 const cpl_image * first = NULL;
5409 int sizex = 0;
5410 int sizey = 0;
5411
5412 int vsize = 0;
5413 cpl_size deg=0;
5414 /* FIXME: This should go before the x and y vectors.
5415 Checking for all the inputs */
5416 cpl_ensure_code(gaint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5417 cpl_ensure_code(lint_qclist != NULL, CPL_ERROR_NULL_INPUT);
5418 cpl_ensure_code(linc_qclist != NULL, CPL_ERROR_NULL_INPUT);
5419 cpl_ensure_code(bpm_qclist != NULL, CPL_ERROR_NULL_INPUT);
5420
5421 pcoeffs = cpl_malloc(sizeof(double)*(xsh_detmon_lg_config.order + 1));
5422
5423 skip_if(cpl_propertylist_append_string(gaint_qclist, DETMON_QC_METHOD,
5424 xsh_detmon_lg_config.method));
5425 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_METHOD,
5427
5428
5429 if (!strcmp(xsh_detmon_lg_config.method, "PTC")) {
5430 /* Computation of GAIN via polynomial fit */
5431 if (xsh_detmon_lg_config.exts >= 0) {
5432 cpl_msg_info(cpl_func,
5433 "Polynomial fitting for the GAIN (constant term method)");
5434 } else {
5435 cpl_msg_info(cpl_func,
5436 "Polynomial fitting for the GAIN (constant term method)"
5437 " for extension nb %d", which_ext);
5438 }
5439 skip_if(xsh_detmon_lg_qc_ptc(gain_table, gaint_qclist, mode, gain_nsets));
5440 } else {
5441 skip_if(xsh_detmon_lg_qc_med(gain_table, gaint_qclist, gain_nsets));
5442 }
5443
5444 /*^FIXME: This shouldn't be written when no applied */
5445 /* Lamp flux */
5446 if(xsh_detmon_lg_config.lamp_ok) {
5447 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_FLUX,
5449 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_FLUX,
5451 }
5452
5453 /*^FIXME: This shouldn't be written when no applied */
5454 if(xsh_detmon_lg_config.autocorr == TRUE) {
5455 autocorr = cpl_table_get_column_median(gain_table, "AUTOCORR");
5456 skip_if(cpl_propertylist_append_double(gaint_qclist, DETMON_QC_AUTOCORR,
5457 autocorr));
5458 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_AUTOCORR,
5460 }
5461 if (xsh_detmon_lg_config.exts >= 0) {
5462 cpl_msg_info(cpl_func, "Polynomial fitting pix-to-pix");
5463 } else {
5464 cpl_msg_info(cpl_func, "Polynomial fitting pix-to-pix"
5465 " for extension nb %d", which_ext);
5466 }
5467
5468 if(!xsh_detmon_lg_config.pix2pix) {
5469 const int order=xsh_detmon_lg_config.order;
5470
5471
5472
5473
5474
5475 double mse = 0;
5476 /* Computation of LINEARITY via polynomial fit */
5477 y = cpl_vector_wrap(linear_nsets,
5478 (double *)cpl_table_get_data_double_const(linear_table,
5479 "MED"));
5480
5481 if (opt_nir == NIR) {
5482 x = cpl_vector_wrap(linear_nsets,
5483 (double *)cpl_table_get_data_double_const(linear_table,
5484 "DIT"));
5485 } else {
5486 x = cpl_vector_wrap(linear_nsets,
5487 (double *)cpl_table_get_data_double_const(linear_table,
5488 "EXPTIME"));
5489 }
5490
5491 if(x == NULL || y == NULL) {
5492 cpl_vector_unwrap((cpl_vector *)x);
5493 cpl_vector_unwrap((cpl_vector *)y);
5494 /*
5495 * As x and y are const vectors, if they would be defined at the
5496 * beginning of the function (required for skip_if - end_skip
5497 * scheme), they couldn't be initialised to NULL (required too).
5498 * Therefore, they are considered apart from the scheme.
5499 */
5500 skip_if(1);
5501 }
5502
5503 cpl_msg_info(cpl_func, "Polynomial fitting for the LINEARITY");
5504 poly_linfit = irplib_polynomial_fit_1d_create(x, y,order,&mse);
5505
5506 if(order == cpl_vector_get_size(x) - 1) {
5507 cpl_msg_warning(cpl_func, "The fitting is not over-determined.");
5508 mse = 0;
5509 }
5510
5511 if(poly_linfit == NULL) {
5512 cpl_vector_unwrap((cpl_vector *)x);
5513 cpl_vector_unwrap((cpl_vector *)y);
5514 /* See comment in previous error checking if() statement */
5515 skip_if(1);
5516 }
5517
5518
5519 min_val=cpl_vector_get_min(y);
5520 max_val=cpl_vector_get_max(y);
5521
5522 cpl_vector_unwrap((cpl_vector *)x);
5523 cpl_vector_unwrap((cpl_vector *)y);
5524
5525 for(deg = 0; deg <= order; deg++) {
5526 const double coeff =
5527 cpl_polynomial_get_coeff(poly_linfit, &deg);
5528 char *name_o =
5529 cpl_sprintf("ESO QC LIN COEF%" CPL_SIZE_FORMAT "", deg);
5530 assert(name_o != NULL);
5531 skip_if(cpl_propertylist_append_double(lint_qclist, name_o, coeff));
5532 skip_if(cpl_propertylist_set_comment(lint_qclist,name_o,
5534
5535 cpl_free(name_o);
5536 pcoeffs[deg] = coeff;
5537 }
5538 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_ERRFIT, mse));
5539 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_ERRFIT,
5541
5542
5543 } else {
5544 const int order=xsh_detmon_lg_config.order;
5545 /* pix2pix == TRUE */
5546 y = cpl_vector_wrap(linear_nsets,
5547 (double *)cpl_table_get_data_double_const(linear_table,
5548 "MED"));
5549
5550 if (opt_nir == NIR)
5551 {
5552 x = cpl_vector_wrap(linear_nsets,
5553 (double *)cpl_table_get_data_double_const(linear_table,
5554 "DIT"));
5555 } else {
5556 x = cpl_vector_wrap(linear_nsets,
5557 (double *)cpl_table_get_data_double_const(linear_table,
5558 "EXPTIME"));
5559
5560 }
5561
5562 first = cpl_imagelist_get_const(linearity_inputs, 0);
5563 sizex = cpl_image_get_size_x(first);
5564 sizey = cpl_image_get_size_y(first);
5565 vsize = cpl_vector_get_size(x);
5566 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
5567 *coeffs_ptr =
5568 cpl_fit_imagelist_polynomial(x, linearity_inputs, 0,order, FALSE,
5569 CPL_TYPE_FLOAT, fiterror);
5570 min_val=cpl_vector_get_min(y);
5571 max_val=cpl_vector_get_max(y);
5572 cpl_vector_unwrap((cpl_vector*)x);
5573 cpl_vector_unwrap((cpl_vector*)y);
5574
5575 irplib_ensure(*coeffs_ptr != NULL, CPL_ERROR_UNSPECIFIED,
5576 "Failed polynomial fit");
5577 //xsh_detmon_lg_qclog_lin_coeff(*coeffs_ptr, order,linc_qclist);
5578
5579 for(deg = 0; deg <= order; deg++)
5580 {
5581 cpl_image *image = cpl_imagelist_get(*coeffs_ptr, deg);
5582 const double coeff = cpl_image_get_median(image);
5583 pcoeffs[deg] = coeff;
5584 name_o1 = cpl_sprintf("ESO QC LIN COEF%d", (int)deg);
5585 name_o2 = cpl_sprintf("ESO QC LIN COEF%d ERR", (int)deg);
5586 assert(name_o1 != NULL);
5587 assert(name_o2 != NULL);
5588 skip_if(cpl_propertylist_append_double(linc_qclist, name_o1, coeff));
5589 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o1,
5591 cpl_free(name_o1);
5592 name_o1= NULL;
5593 skip_if(cpl_propertylist_append_double(linc_qclist, name_o2,
5594 cpl_image_get_stdev(image)));
5595 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o2,
5597 cpl_free(name_o2);
5598 name_o2= NULL;
5599 }
5600
5601
5602 if(order == vsize - 1)
5603 {
5604 cpl_msg_warning(cpl_func, "The fitting is not over-determined.");
5605 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5606 0.0));
5607 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5609 } else
5610 {
5611 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
5612 cpl_image_get_median(fiterror)));
5613 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
5615 }
5616 } /* end case pix2pix == TRUE */
5617
5618 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MIN,
5619 min_val));
5620 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MIN,
5622 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MAX,
5623 max_val));
5624 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MAX,
5626 skip_if(xsh_detmon_lg_lineff(pcoeffs,lint_qclist,xsh_detmon_lg_config.ref_level,
5627 xsh_detmon_lg_config.order));
5628 /* Detection of bad pixels */
5629 if (xsh_detmon_lg_config.exts >= 0)
5630 {
5631 cpl_msg_info(cpl_func, "Bad pixel detection");
5632 } else
5633 {
5634 cpl_msg_info(cpl_func, "Bad pixel detection"
5635 " for extension nb %d", which_ext);
5636 }
5637 if(xsh_detmon_lg_config.pix2pix)
5638 {
5639
5640 /* Determines bad pixel map */
5641 nbpixs = xsh_detmon_compute_badpixmap(opt_nir, linear_nsets, linear_table,
5642 linearity_inputs, nbpixs, x,gaint_qclist, bpms_ptr);
5643 /* we still have to unwrapp x & y that we kept for bpixs2 function */
5644 }
5645
5646
5647 skip_if(cpl_propertylist_append_int(bpm_qclist, DETMON_QC_NUM_BPM, nbpixs));
5648 skip_if(cpl_propertylist_set_comment(bpm_qclist, DETMON_QC_NUM_BPM,
5650 cpl_msg_info(cpl_func,"stability=%g",xsh_detmon_lg_config.lamp_stability);
5651 if(xsh_detmon_lg_config.lamp_stability != 0.0)
5652 {
5653 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_STAB,
5654 xsh_detmon_lg_config.lamp_stability));
5655 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_STAB,
5657 }
5658 /* Fit COEFFS_CUBE and BPM outputs to whole-chip size images (DFS05711) */
5659 if (!xsh_detmon_lg_config.wholechip && xsh_detmon_lg_config.pix2pix)
5660 {
5661 xsh_detmon_lg_fits_coeffs_and_bpm2chip(coeffs_ptr,bpms_ptr);
5662 }
5663 end_skip;
5664
5665 cpl_free(pcoeffs);
5666 cpl_free(name_o1);
5667 cpl_free(name_o2);
5668 cpl_image_delete(fiterror);
5669 cpl_polynomial_delete(poly_linfit);
5670
5671
5672
5673 return cpl_error_get_code();
5674}
5675
5676/*---------------------------------------------------------------------------*/
5684/*---------------------------------------------------------------------------*/
5685static cpl_error_code
5686xsh_detmon_lg_lineff(double * pcoeffs,
5687 cpl_propertylist * qclist,
5688 int ref_level,
5689 int order)
5690{
5691 double lineff = 0;
5692 double root = 0;
5693 double residual, slope;
5694 int i;
5695 cpl_size deg=0;
5696 cpl_polynomial * poly = cpl_polynomial_new(1);
5697
5698
5699 /*
5700 * Construction of the polynomial F_m(F_r) from F_m(t),
5701 * using F_r = a_1 * t.
5702 */
5703 /*
5704 for (deg = 0; deg <= order; deg++) {
5705 cpl_msg_info(cpl_func,"coef[%d]=%g",deg,pcoeffs[deg]);
5706 }
5707 */
5708
5709
5710 pcoeffs[0] -= ref_level;
5711
5712 for (i = 2; i <= order; i++)
5713 {
5714 int j;
5715 for(j = 0; j < i; j++)
5716 {
5717 pcoeffs[i] /= pcoeffs[1];
5718 }
5719 }
5720
5721 pcoeffs[1] = 1;
5722
5723 for (deg = 0; deg <= order; deg++) {
5724 /*cpl_msg_info(cpl_func,"coef[%d]=%g",deg,pcoeffs[deg]);*/
5725 skip_if(cpl_polynomial_set_coeff(poly, &deg, pcoeffs[deg]));
5726 }
5727
5728 /*
5729 * Verification of validity of first guess (0).
5730 * The root to be found will be in the same interval of monotony
5731 * of the first guess; therefore, slope must be greater than 0.
5732 * Slope > 0 and poly(root) = 0 force also residual to be negative.
5733 */
5734 residual = cpl_polynomial_eval_1d(poly, 0.0, &slope);
5735
5736 if (slope <= 0.0 && residual >= 0.0) {
5737 cpl_msg_warning(cpl_func, "Reference level (--ref_level) outside"
5738 " linearity range of the detector. Cannot compute"
5739 " linearity efficiency (QC.LINEFF).");
5740 lineff = -1;
5741 }
5742 else
5743 {
5744 cpl_error_code err = cpl_polynomial_solve_1d(poly, 0.0, &root, 1);
5745 /*
5746 cpl_msg_info(cpl_func,"root=%g ref_level=%d lin_eff=%d",
5747 root,ref_level,ref_level);
5748 */
5749 if (err == CPL_ERROR_NONE)
5750 {
5751
5752 lineff = (root - ref_level) / ref_level;
5753 }
5754 else
5755 {
5756 cpl_error_reset();
5757 cpl_msg_warning(cpl_func,
5758 "Cannot compute linearity efficiency (QC.LINEFF)"
5759 "for the current combination "
5760 " of (--ref-level equal %d) and (--order equal %d) parameters. Try "
5761 "to decrease (--ref-level) value.", ref_level, order);
5762 }
5763 }
5764 cpl_msg_warning(cpl_func, "DETMON_QC_LIN_EFF=%f",lineff );
5765 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF,
5766 lineff));
5767 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF,
5769
5770 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF_FLUX,
5771 ref_level));
5772 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF_FLUX,
5774
5775 end_skip;
5776
5777 cpl_polynomial_delete(poly);
5778
5779 return cpl_error_get_code();
5780}
5781
5782/*---------------------------------------------------------------------------*/
5789/*---------------------------------------------------------------------------*/
5790static cpl_error_code
5791xsh_detmon_lg_qc_ptc(const cpl_table * gain_table,
5792 cpl_propertylist * qclist, unsigned mode, int rows_in_gain)
5793{
5794 double mse = 0;
5795 cpl_polynomial *poly_fit = NULL;
5796 cpl_polynomial *poly_fit2 = NULL;
5797 cpl_size i;
5798 const int nsets = rows_in_gain;
5799
5800 cpl_vector *x = NULL;
5801 cpl_vector *y = NULL;
5802
5803 cpl_errorstate prestate;
5804 double coef = 0;
5805 cpl_ensure_code(gain_table != NULL, CPL_ERROR_NULL_INPUT);
5806 cpl_ensure_code(qclist != NULL, CPL_ERROR_NULL_INPUT);
5807
5808 x = cpl_vector_wrap(nsets, (double *)cpl_table_get_data_double_const(gain_table, "X_FIT"));
5809
5810 y = cpl_vector_wrap(nsets, (double *)cpl_table_get_data_double_const(gain_table, "Y_FIT"));
5811
5812 skip_if(x == NULL || y == NULL);
5814 {
5815 if (x)
5816 {
5817 cpl_vector_unwrap(x);
5818 }
5819 if (y)
5820 {
5821 cpl_vector_unwrap(y);
5822 }
5823 return CPL_ERROR_NONE;
5824 }
5825 /*it is not really a MSE, but chi square of the fit, see cpl_vector_fill_polynomial_fit_residual for details*/
5826 poly_fit = irplib_polynomial_fit_1d_create_chiq(x, y, 1, &mse);
5827 skip_if(poly_fit == NULL);
5828
5829 /* Write the QC params corresponding to the fitting of the GAIN */
5830 i = 1;
5831 prestate = cpl_errorstate_get();
5832 coef = cpl_polynomial_get_coeff(poly_fit, &i);
5833 skip_if (!cpl_errorstate_is_equal(prestate) || coef==0);
5834 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD, coef));
5835 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
5837 if (coef != 0)
5838 {
5839 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,
5840 1 / coef));
5841 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
5843 }
5844 /* MSE is removed - see DFS07358 for details
5845 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE, mse));
5846 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
5847 DETMON_QC_GAIN_MSE_C));
5848 */
5849 i = 0;
5850 /* QC.RON computation is disabled, see DFS05852 for details*/
5851
5852 /* * skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_RON,
5853 cpl_polynomial_get_coeff(poly_fit, &i)));
5854 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_RON,
5855 DETMON_QC_RON_C));
5856 */
5858 const cpl_vector *x2 =
5859 cpl_vector_wrap(nsets, (double *)cpl_table_get_data_double_const(gain_table, "X_FIT_CORR"));
5860 const cpl_vector *y2 =
5861 cpl_vector_wrap(nsets, (double *)cpl_table_get_data_double_const(gain_table, "Y_FIT"));
5862
5863 if(x2 == NULL || y2 == NULL) {
5864 cpl_vector_unwrap((cpl_vector *)x2);
5865 cpl_vector_unwrap((cpl_vector *)y2);
5866 /*
5867 * As x and y are const vectors, if they would be defined at the
5868 * beginning of the function (required for skip_if - end_skip
5869 * scheme), they couldn't be initialised to NULL (required too).
5870 * Therefore, they are considered apart from the scheme.
5871 */
5872 skip_if(1);
5873 }
5874
5875 /* Revise mse, maybe used afterwards */
5876 poly_fit2 = irplib_polynomial_fit_1d_create(x2, y2, 1, &mse);
5877 if(poly_fit2 == NULL) {
5878 cpl_vector_unwrap((cpl_vector *)x2);
5879 cpl_vector_unwrap((cpl_vector *)y2);
5880
5881 cpl_msg_error(cpl_func, "Error during polynomial fit, err[%s]", cpl_error_get_where());
5882 /* See comment in previous error checking if() statement */
5883 skip_if(1);
5884 }
5885 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5886 cpl_vector_unwrap((cpl_vector *)x2);
5887 cpl_vector_unwrap((cpl_vector *)y2);
5888 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5889 /* Write the QC params corresponding to the fitting of the GAIN */
5890 i = 1;
5891 prestate = cpl_errorstate_get();
5892 coef = cpl_polynomial_get_coeff(poly_fit2, &i);
5893 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
5894 skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
5895
5896 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,
5897 coef));
5898 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
5900
5901 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
5902 1 / coef));
5903 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
5905 }
5906
5907 end_skip;
5908
5909 /*cleanup*/
5910 cpl_vector_unwrap(x);
5911 cpl_vector_unwrap(y);
5912 cpl_polynomial_delete(poly_fit);
5913 cpl_polynomial_delete(poly_fit2);
5914
5915 return cpl_error_get_code();
5916}
5917
5924static int xsh_detmon_lg_check_before_gain(const cpl_vector* x, const cpl_vector* y)
5925{
5926 const double TOLERANCE = 1e-37;/*MINDOUBLE is not everywhere defined (Mac);*/
5927 double xmin = cpl_vector_get_min(x);
5928 double xmax = cpl_vector_get_max(x);
5929 double ymin = cpl_vector_get_min(y);
5930 double ymax = cpl_vector_get_max(y);
5931 double ystdev = cpl_vector_get_stdev(y);
5932 double xstdev = cpl_vector_get_stdev(x);
5933 int retval = 1;
5934 if (fabs(xmax-xmin) < TOLERANCE &&
5935 fabs(ymax - ymin) < TOLERANCE &&
5936 xstdev < TOLERANCE &&
5937 ystdev < TOLERANCE)
5938 {
5939 cpl_msg_warning(cpl_func, "An empty frame has been detected, linearity, coeffs, gain, FPN values will not be computed.");
5940 retval = 0;
5941 }
5942 return retval;
5943}
5944/*---------------------------------------------------------------------------*/
5953/*---------------------------------------------------------------------------*/
5954static cpl_error_code
5955xsh_detmon_lg_qc_med(const cpl_table * gain_table,
5956 cpl_propertylist * qclist, int rows_in_gain)
5957{
5958
5959 double gain=0;
5960 cpl_vector *x = NULL;
5961 cpl_vector *y = NULL;
5962 int check_result = 0;
5963
5964 if (rows_in_gain) {/* silence unused var */};
5965
5966 x = cpl_vector_wrap(rows_in_gain, (double *)cpl_table_get_data_double_const(gain_table, "X_FIT"));
5967 y = cpl_vector_wrap(rows_in_gain, (double *)cpl_table_get_data_double_const(gain_table, "Y_FIT"));
5968 check_result = xsh_detmon_lg_check_before_gain(x, y);
5969 if (x)
5970 {
5971 cpl_vector_unwrap(x);
5972 }
5973 if (y)
5974 {
5975 cpl_vector_unwrap(y);
5976 }
5977 if (0 == check_result)
5978 {
5979 return CPL_ERROR_NONE;
5980 }
5981
5982 gain=cpl_table_get_column_median(gain_table, "GAIN");
5983
5984 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,gain));
5985
5986 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
5988
5989 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE,
5990 cpl_table_get_column_stdev
5991 (gain_table, "GAIN")));
5992 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
5994
5995 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD,1./gain));
5996 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
5998
5999
6000 gain=cpl_table_get_column_median(gain_table, "GAIN_CORR");
6001
6002 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
6003 gain));
6004 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
6006
6007
6008 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,1./gain));
6009 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
6011
6012
6013 end_skip;
6014
6015 return cpl_error_get_code();
6016}
6017
6018
6019/*---------------------------------------------------------------------------*/
6028/*---------------------------------------------------------------------------*/
6029static cpl_error_code
6030xsh_detmon_lg_rescale(cpl_imagelist * to_rescale)
6031{
6032 double med1 =
6033 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 0),
6038 double med2 =
6039 cpl_image_get_median_window(cpl_imagelist_get(to_rescale, 1),
6044
6045 skip_if(0);
6046
6047 if(fabs(med1 / med2 - 1) > 0.001) {
6048 if(med1 > med2)
6049 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 0),
6050 med1 / med2));
6051 else
6052 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 1),
6053 med2 / med1));
6054 }
6055
6056 end_skip;
6057
6058 return cpl_error_get_code();
6059}
6060
6061static cpl_error_code
6062xsh_detmon_pair_extract_next(const cpl_frameset * set,
6063 int* iindex,
6064 int* next_element,
6065 double* dit_array,
6066 cpl_frameset ** pair,
6067 double tolerance) /* xsh_detmon_lg_config.tolerance */
6068{
6069 double dit = -100;
6070 double dit_next = -100;
6071 cpl_size* selection;
6072 int nsets_extracted = 0;
6073 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
6074 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
6075 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
6076 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
6077
6078 nsets_extracted = cpl_frameset_get_size(set);
6079 selection = cpl_malloc(sizeof(cpl_size) * nsets_extracted);
6080 memset(&selection[0], 0, sizeof(cpl_size) * nsets_extracted);
6081
6082
6083 dit = dit_array[*next_element ];
6084 /* cpl_msg_info(cpl_func, "%d: dit %f",*next_element, dit ); */
6085 if (*next_element < nsets_extracted - 1)
6086 {
6087 dit_next = dit_array[*next_element + 1 ];
6088 /* cpl_msg_info(cpl_func, "%d: dit %f",*next_element + 1, dit_next ); */
6089 }
6090 /* one element would be returned always */
6091 selection[iindex[*next_element] ] = 1;
6092 if (fabs(dit - dit_next) < tolerance)
6093 {
6094 /* return a second element of the pair */
6095 selection[iindex[*next_element + 1] ] = 1;
6096 (*next_element)++;
6097 }
6098 else
6099 {
6100 cpl_msg_warning(cpl_func, "DIT for the second frame in the pair is above tolerance level - could not be taken, dit1[%f] dit2[%f] next_element: %d . Check input data set and tolerance value", dit, dit_next, *next_element);
6101 }
6102 (*next_element)++;
6103 /* prepare frameset */
6104 cpl_frameset_delete(*pair);
6105 *pair = cpl_frameset_extract(set, selection, 1);
6106
6107
6108 cpl_free(selection);
6109 return cpl_error_get_code();
6110}
6111
6112static cpl_error_code
6113xsh_detmon_single_extract_next(const cpl_frameset * set,
6114 int* iindex,
6115 int* next_element,
6116 double* dit_array,
6117 cpl_frameset ** pair)
6118{
6119 cpl_size* selection;
6120 int nsets_extracted = 0;
6121 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
6122 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
6123 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
6124 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
6125
6126 nsets_extracted = cpl_frameset_get_size(set);
6127 selection = cpl_malloc(sizeof(cpl_size) * nsets_extracted);
6128 memset(&selection[0], 0, sizeof(cpl_size) * nsets_extracted);
6129
6130 /* only one element would be returned */
6131 selection[iindex[*next_element] ] = 1;
6132 (*next_element)++;
6133 /* prepare frameset */
6134 cpl_frameset_delete(*pair);
6135 *pair = cpl_frameset_extract(set, selection, 1);
6136
6137 cpl_free(selection);
6138 return cpl_error_get_code();
6139}
6140
6141
6142/*---------------------------------------------------------------------------*/
6233/*---------------------------------------------------------------------------*/
6234
6235cpl_table *
6236xsh_detmon_gain(const cpl_imagelist * imlist_on,
6237 const cpl_imagelist * imlist_off,
6238 const cpl_vector * exptimes,
6239 const cpl_vector * ndit,
6240 double tolerance,
6241 int llx,
6242 int lly,
6243 int urx,
6244 int ury,
6245 double kappa,
6246 int nclip,
6247 int xshift,
6248 int yshift,
6249 cpl_propertylist * qclist,
6250 unsigned mode,
6251 cpl_imagelist ** diff_imlist,
6252 cpl_imagelist ** autocorr_imlist)
6253{
6254 cpl_table * gain_table = NULL;
6255 cpl_imagelist * difflist = NULL;
6256 cpl_imagelist * autocorrlist = NULL;
6257 cpl_imagelist * c_onlist = NULL;
6258 cpl_imagelist * c_offlist = NULL;
6259 cpl_vector * diffdits = NULL;
6260 cpl_vector * diffndits = NULL;
6261 int rows_in_gain = 0;
6262 int ndiffdits, ndits;
6263 int i, j;
6264 cpl_boolean opt_nir = mode & IRPLIB_GAIN_OPT ? OPT : NIR;
6265 const char * method = mode & IRPLIB_GAIN_PTC ? "PTC" : "MED";
6266
6267 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6268 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6269 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6270 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6271
6272 /* Create table with columns */
6273 gain_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6274 skip_if(xsh_detmon_gain_table_create(gain_table, opt_nir));
6275
6276
6277 /* Search for different EXPTIME values */
6278 skip_if(xsh_detmon_lg_find_dits_ndits(exptimes, ndit,tolerance,&diffdits,
6279 &diffndits));
6280 ndiffdits = cpl_vector_get_size(diffdits);
6281
6282 ndits = cpl_vector_get_size(exptimes);
6283
6284 /* AUTOCORR processing requires both. They will become outputs later. */
6285 if (mode & IRPLIB_GAIN_WITH_AUTOCORR && (diff_imlist || autocorr_imlist)) {
6286 difflist = cpl_imagelist_new();
6287 autocorrlist = cpl_imagelist_new();
6288 }
6289
6290 if (mode & IRPLIB_GAIN_COLLAPSE) {
6292 c_offlist = cpl_imagelist_duplicate(imlist_off);
6293 skip_if(xsh_detmon_lg_rescale(c_offlist));
6294 } else {
6295 c_offlist = (cpl_imagelist *) imlist_off;
6296 }
6297 }
6298
6299 /* Loop over the different DITs found in EXPTIMEs */
6300 for (i = 0; i < ndiffdits; i++) {
6301 int c_nons;
6302 int c_noffs = 0; /* False (uninit) warning */
6303
6304 double c_dit = 0;
6305 int c_ndit = 1;
6306
6307 c_dit=cpl_vector_get(diffdits, i);
6308
6309 if(opt_nir) {
6310 c_ndit=(int)cpl_vector_get(diffndits, i);
6311 }
6312
6313 c_onlist = cpl_imagelist_new();
6314 c_nons = 0;
6315
6317 c_offlist = cpl_imagelist_new();
6318 c_noffs = 0;
6319 }
6320
6321 /* Extraction of images of EXPTIME i */
6322 for(j = 0; j < ndits; j++) {
6323 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6324 /*
6325 * First we get the corresponding image from the ON imlist.
6326 * The option IRPLIB_GAIN_WITH_RESCALE requires to modify
6327 * the input pixel buffer; therefore we must duplicate it.
6328 * On the other hand, if this option is not required, there
6329 * is no need for that duplication. We must only care that
6330 * c_onlist must not be deleted but only unset.
6331 */
6332 cpl_image * im_on;
6334 const cpl_image * im =
6335 cpl_imagelist_get_const(imlist_on, j);
6336 im_on = cpl_image_duplicate(im);
6337 } else {
6338 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6339 }
6340 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6341 c_nons++;
6342
6343 /*
6344 * Same explanation as above but for OFF imlist.
6345 * Only necessary when IRPLIB_GAIN_NO_COLLAPSE required.
6346 */
6348 cpl_image * im_off;
6350 const cpl_image * im =
6351 cpl_imagelist_get_const(imlist_off, j);
6352 im_off = cpl_image_duplicate(im);
6353 } else {
6354 im_off =
6355 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6356 }
6357 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6358 c_noffs++;
6359 }
6360 }
6361 }
6362
6363 /* If NO_COLLAPSE, must be the same number of images! */
6365 skip_if (c_nons != c_noffs);
6366
6367 /* There must be pairs! */
6368 skip_if (c_nons == 0 || c_nons % 2 != 0);
6369
6370 /* Rescaling */
6372 skip_if(xsh_detmon_lg_rescale(c_onlist));
6374 skip_if(xsh_detmon_lg_rescale(c_offlist));
6375 }
6376
6377 /* The following loop is necessary for the case of multiple pairs
6378 of same EXPTIME values */
6379 while(c_nons > 0) {
6380 int rows_affected = 1;
6381 skip_if(xsh_detmon_gain_table_fill_row(gain_table,
6382 c_dit,c_ndit,
6383 autocorrlist,
6384 difflist, c_onlist,
6385 c_offlist, kappa, nclip,
6386 llx, lly, urx, ury,
6387 xshift, yshift,1E10, 1E10, i,
6388 mode, &rows_affected));
6389 if (rows_affected)
6390 {
6391 rows_in_gain++;
6392 }
6394 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6395 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6397 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6398 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6399 }
6400 } else {
6401 cpl_imagelist_unset(c_onlist, 0);
6402 skip_if(0);
6403 cpl_imagelist_unset(c_onlist, 0);
6404 skip_if(0);
6406 cpl_imagelist_unset(c_offlist, 0);
6407 skip_if(0);
6408 cpl_imagelist_unset(c_offlist, 0);
6409 skip_if(0);
6410 }
6411 }
6412 skip_if(0);
6413 c_nons -= 2;
6414 }
6415
6416 cpl_imagelist_delete(c_onlist);
6418 cpl_imagelist_delete(c_offlist);
6419 }
6420 }
6421
6422 skip_if(cpl_propertylist_append_string(qclist, DETMON_QC_METHOD, method));
6423 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_METHOD,
6425
6426 /* Computation of GAIN via polynomial fit */
6427 if (mode & IRPLIB_GAIN_PTC) {
6428 skip_if(xsh_detmon_lg_qc_ptc(gain_table, qclist, mode, rows_in_gain));
6429 } else {
6430 skip_if(xsh_detmon_lg_qc_med(gain_table, qclist, rows_in_gain));
6431 }
6432
6434 double autocorr = cpl_table_get_column_median(gain_table, "AUTOCORR");
6435 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_AUTOCORR,
6436 autocorr));
6437 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_AUTOCORR,
6439 }
6440
6441 if (diff_imlist != NULL) *diff_imlist = difflist;
6442 if (autocorr_imlist != NULL) *autocorr_imlist = autocorrlist;
6443
6444 end_skip;
6445
6446 cpl_vector_delete(diffdits);
6447 cpl_vector_delete(diffndits);
6448
6449 return gain_table;
6450}
6451
6452static cpl_error_code
6453xsh_detmon_gain_table_create(cpl_table * gain_table,
6454 const cpl_boolean opt_nir)
6455{
6456 if (opt_nir == NIR) {
6457 skip_if(cpl_table_new_column(gain_table, "DIT", CPL_TYPE_DOUBLE));
6458 skip_if(cpl_table_new_column(gain_table, "NDIT", CPL_TYPE_INT));
6459 } else { /* OPT */
6460 skip_if(cpl_table_new_column(gain_table, "EXPTIME", CPL_TYPE_DOUBLE));
6461 }
6462 skip_if(cpl_table_new_column(gain_table, "MEAN_ON1", CPL_TYPE_DOUBLE));
6463 skip_if(cpl_table_new_column(gain_table, "MEAN_ON2", CPL_TYPE_DOUBLE));
6464 skip_if(cpl_table_new_column(gain_table, "MEAN_OFF1", CPL_TYPE_DOUBLE));
6465 skip_if(cpl_table_new_column(gain_table, "MEAN_OFF2", CPL_TYPE_DOUBLE));
6466 skip_if(cpl_table_new_column(gain_table, "SIG_ON_DIF", CPL_TYPE_DOUBLE));
6467 skip_if(cpl_table_new_column(gain_table, "SIG_OFF_DIF", CPL_TYPE_DOUBLE));
6468 skip_if(cpl_table_new_column(gain_table, "GAIN", CPL_TYPE_DOUBLE));
6469 skip_if(cpl_table_new_column(gain_table, "AUTOCORR", CPL_TYPE_DOUBLE));
6470 skip_if(cpl_table_new_column(gain_table, "GAIN_CORR", CPL_TYPE_DOUBLE));
6471 skip_if(cpl_table_new_column(gain_table, "ADU", CPL_TYPE_DOUBLE));
6472 skip_if(cpl_table_new_column(gain_table, "X_FIT", CPL_TYPE_DOUBLE));
6473 skip_if(cpl_table_new_column(gain_table, "X_FIT_CORR", CPL_TYPE_DOUBLE));
6474 skip_if(cpl_table_new_column(gain_table, "Y_FIT", CPL_TYPE_DOUBLE));
6475 skip_if(cpl_table_new_column(gain_table, "Y_FIT_CORR", CPL_TYPE_DOUBLE));
6476 skip_if(cpl_table_new_column(gain_table, "FLAG", CPL_TYPE_INT));
6477
6478 end_skip;
6479
6480 return cpl_error_get_code();
6481}
6482
6483static cpl_error_code
6484xsh_detmon_lin_table_create(cpl_table * lin_table,
6485 const cpl_boolean opt_nir)
6486{
6487 if (opt_nir == NIR) {
6488 skip_if(cpl_table_new_column(lin_table, "DIT", CPL_TYPE_DOUBLE));
6489 } else { /* OPT */
6490 skip_if(cpl_table_new_column(lin_table, "EXPTIME", CPL_TYPE_DOUBLE));
6491 }
6492 skip_if(cpl_table_new_column(lin_table, "MED", CPL_TYPE_DOUBLE));
6493 skip_if(cpl_table_new_column(lin_table, "MEAN", CPL_TYPE_DOUBLE));
6494 skip_if(cpl_table_new_column(lin_table, "MED_DIT", CPL_TYPE_DOUBLE));
6495 skip_if(cpl_table_new_column(lin_table, "MEAN_DIT", CPL_TYPE_DOUBLE));
6496 skip_if(cpl_table_new_column(lin_table, "ADL", CPL_TYPE_DOUBLE));
6497 end_skip;
6498
6499 return cpl_error_get_code();
6500}
6501
6502static cpl_vector *
6503xsh_detmon_lg_find_dits(const cpl_vector * exptimes,
6504 double tolerance)
6505{
6506 cpl_vector * dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6507 int ndits = 0;
6508
6509 int i, j;
6510
6511 /* First different EXPTIME */
6512 cpl_vector_set(dits, 0, cpl_vector_get(exptimes, 0));
6513 ndits = 1;
6514
6515 /* Search for all different EXPTIMEs */
6516 for(i = 1; i < cpl_vector_get_size(exptimes); i++) {
6517 int ndiffs = 0;
6518 for (j = 0; j < ndits; j++) {
6519 if (fabs(cpl_vector_get(exptimes, i) -
6520 cpl_vector_get(dits, j)) > tolerance)
6521 ndiffs++;
6522 }
6523 if(ndiffs == ndits) {
6524 cpl_vector_set(dits, ndits, cpl_vector_get(exptimes, i));
6525 ndits++;
6526 }
6527 }
6528
6529 cpl_vector_set_size(dits, ndits);
6530
6531 return dits;
6532}
6533
6534
6535
6536
6537static cpl_error_code
6538xsh_detmon_lg_find_dits_ndits(const cpl_vector * exptimes,
6539 const cpl_vector * vec_ndits,
6540 double tolerance,
6541 cpl_vector** diff_dits,
6542 cpl_vector** diff_ndits)
6543{
6544 int ndits = 0;
6545
6546 int i, j;
6547 int size=0;
6548
6549
6550 * diff_dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
6551 * diff_ndits = cpl_vector_new(cpl_vector_get_size(*diff_dits));
6552
6553 /* First different EXPTIME */
6554 cpl_vector_set(*diff_dits, 0, cpl_vector_get(exptimes, 0));
6555 cpl_vector_set(*diff_ndits, 0, cpl_vector_get(vec_ndits, 0));
6556
6557 ndits = 1;
6558 size=cpl_vector_get_size(exptimes);
6559 /* Search for all different EXPTIMEs */
6560 for(i = 1; i < size; i++) {
6561 int ndiffs = 0;
6562 for (j = 0; j < ndits; j++) {
6563 if (fabs(cpl_vector_get(exptimes, i) -
6564 cpl_vector_get(*diff_dits,j)) > tolerance)
6565 ndiffs++;
6566 }
6567 if(ndiffs == ndits) {
6568 cpl_vector_set(*diff_dits, ndits, cpl_vector_get(exptimes, i));
6569 cpl_vector_set(*diff_ndits, ndits, cpl_vector_get(vec_ndits, i));
6570 ndits++;
6571 }
6572 }
6573
6574 cpl_vector_set_size(*diff_dits, ndits);
6575 cpl_vector_set_size(*diff_ndits, ndits);
6576
6577
6578 return cpl_error_get_code();
6579}
6580
6581
6582/*---------------------------------------------------------------------------*/
6665/*---------------------------------------------------------------------------*/
6666
6667cpl_table *
6668xsh_detmon_lin(const cpl_imagelist * imlist_on,
6669 const cpl_imagelist * imlist_off,
6670 const cpl_vector * exptimes,
6671 double tolerance,
6672 int llx,
6673 int lly,
6674 int urx,
6675 int ury,
6676 int order,
6677 int ref_level,
6678 double kappa,
6679 cpl_boolean bpmbin,
6680 cpl_propertylist * qclist,
6681 unsigned mode,
6682 cpl_imagelist ** coeffs_cube,
6683 cpl_image ** bpm)
6684{
6685 cpl_table * lin_table = NULL;
6686 cpl_imagelist * c_onlist = NULL;
6687 cpl_imagelist * c_offlist = NULL;
6688 cpl_vector * diffdits = NULL;
6689 cpl_imagelist * lin_inputs = NULL;
6690 cpl_polynomial * poly_linfit = NULL;
6691 cpl_image * fiterror = NULL;
6692 cpl_vector * vcoeffs = NULL;
6693 double * pcoeffs = NULL;
6694 int ndiffdits, ndits;
6695 int i, j;
6696 cpl_boolean opt_nir = mode & IRPLIB_LIN_OPT ? OPT : NIR;
6697 const cpl_vector *x = NULL;
6698 const cpl_vector *y = NULL;
6699
6700 const cpl_image * first = NULL;
6701 int sizex = 0;
6702 int sizey = 0;
6703
6704 cpl_size deg;
6705 double vsize = 0;
6706
6707
6708 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
6709 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
6710 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
6711 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
6712 cpl_ensure(order > 0 , CPL_ERROR_ILLEGAL_INPUT, NULL);
6713
6714 vcoeffs = cpl_vector_new(order + 1);
6715 pcoeffs = cpl_vector_get_data(vcoeffs);
6716
6717 /* This mode requires optional outputs */
6718 if (mode & IRPLIB_LIN_PIX2PIX) {
6719 cpl_ensure(coeffs_cube != NULL, CPL_ERROR_NULL_INPUT, NULL);
6720 cpl_ensure(bpm != NULL, CPL_ERROR_NULL_INPUT, NULL);
6721 lin_inputs = cpl_imagelist_new();
6722 }
6723
6724 /* Create table with columns */
6725 lin_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
6726 skip_if(xsh_detmon_lin_table_create(lin_table, opt_nir));
6727
6728 /* Search for different EXPTIME values */
6729 /* Search for different EXPTIME values */
6730 diffdits = xsh_detmon_lg_find_dits(exptimes, tolerance);
6731 ndiffdits = cpl_vector_get_size(diffdits);
6732
6733 ndits = cpl_vector_get_size(exptimes);
6734
6735
6736
6737
6738
6739
6740 /* TO BE IMPLEMENTED SIMILARLY TO UPPER LEVEL FUNCTION (search for nskip)
6741 if(filter > 0) {
6742 double med1 =
6743 cpl_image_get_median_window(cpl_imagelist_get(imlist_on, 0),
6744 llx,lly,urx,ury);
6745 double med2 =
6746 cpl_image_get_median_window(cpl_imagelist_get(imlist_on, 1),
6747 llx,lly,urx,ury);
6748 if ( med1 > (double)filter ||
6749 med2 > (double)filter) {
6750 follow = CPL_FALSE;
6751 cpl_table_select_row(lin_table, dit_nb);
6752 dit_nskip++;
6753 cpl_msg_warning(cpl_func, "Frames of EXPTIME nb %d "
6754 "will not be taken into account for computation "
6755 "as they are above --filter threshold", dit_nb);
6756 }
6757 }
6758 */
6759
6760
6761
6762
6763 if (mode & IRPLIB_LIN_COLLAPSE) {
6764 /*
6765 * The master bias is required only for
6766 * linearity computation in the OPT domain
6767 */
6768 cpl_image * collapse = cpl_imagelist_collapse_create(imlist_off);
6769 skip_if(collapse == NULL);
6770
6771 c_offlist = cpl_imagelist_new();
6772 skip_if(cpl_imagelist_set(c_offlist, collapse, 0));
6773 }
6774
6775 /* Loop over the different DITs found in EXPTIMEs */
6776 for (i = 0; i < ndiffdits; i++) {
6777 int c_nons;
6778 int c_noffs = 0; /* False (uninit) warning */
6779
6780 double c_dit = cpl_vector_get(diffdits, i);
6781
6782 c_onlist = cpl_imagelist_new();
6783 c_nons = 0;
6784
6786 c_offlist = cpl_imagelist_new();
6787 c_noffs = 0;
6788 }
6789
6790 for(j = 0; j < ndits; j++) {
6791 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
6792 /*
6793 * First we get the corresponding image from the ON imlist.
6794 * The option IRPLIB_GAIN_WITH_RESCALE requires to modify
6795 * the input pixel buffer; therefore we must duplicate it.
6796 * On the other hand, if this option is not required, there
6797 * is no need for that duplication. We must only care that
6798 * c_onlist must not be deleted but only unset.
6799 */
6800 cpl_image * im_on;
6802 const cpl_image * im =
6803 cpl_imagelist_get_const(imlist_on, j);
6804 im_on = cpl_image_duplicate(im);
6805 } else {
6806 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
6807 }
6808 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
6809 c_nons++;
6810
6811 /*
6812 * Same explanation as above but for OFF imlist.
6813 * Only necessary when IRPLIB_GAIN_NO_COLLAPSE required.
6814 */
6816 cpl_image * im_off;
6818 const cpl_image * im =
6819 cpl_imagelist_get_const(imlist_off, j);
6820 im_off = cpl_image_duplicate(im);
6821 } else {
6822 im_off =
6823 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
6824 }
6825 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
6826 c_noffs++;
6827 }
6828 }
6829 }
6830
6831 /* If NO_COLLAPSE, must be the same number of images! */
6833 skip_if (c_nons != c_noffs);
6834
6835 /* There must be pairs! */
6836 skip_if (c_nons == 0 || c_nons % 2 != 0);
6837
6838 /* Rescaling */
6840 skip_if(xsh_detmon_lg_rescale(c_onlist));
6842 skip_if(xsh_detmon_lg_rescale(c_offlist));
6843 }
6844
6845 /* The following loop is necessary for the case of multiple pairs
6846 of same EXPTIME values */
6847 while(c_nons > 0) {
6848
6849 skip_if(xsh_detmon_lin_table_fill_row(lin_table, c_dit,
6850 lin_inputs,
6851 c_onlist, c_offlist,
6852 llx, lly, urx, ury,
6853 i, 0, mode));
6854
6856 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6857 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
6859 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6860 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
6861 }
6862 } else {
6863 cpl_imagelist_unset(c_onlist, 0);
6864 skip_if(0);
6865 cpl_imagelist_unset(c_onlist, 0);
6866 skip_if(0);
6868 cpl_imagelist_unset(c_offlist, 0);
6869 skip_if(0);
6870 cpl_imagelist_unset(c_offlist, 0);
6871 skip_if(0);
6872 }
6873 }
6874 skip_if(0);
6875 c_nons -= 2;
6876 }
6877
6878 cpl_imagelist_delete(c_onlist);
6880 cpl_imagelist_delete(c_offlist);
6881 }
6882 }
6883
6884 skip_if(xsh_detmon_add_adl_column(lin_table, opt_nir));
6885
6886 if(!(mode & IRPLIB_LIN_PIX2PIX)) {
6887 double mse = 0;
6888 /* Computation of LINEARITY via polynomial fit */
6889 y = cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6890 (double *)cpl_table_get_data_double_const(lin_table,
6891 "MED"));
6892 if (opt_nir == NIR) {
6893 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6894 (double *)cpl_table_get_data_double_const(lin_table, "DIT"));
6895 } else {
6896 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6897 (double *)cpl_table_get_data_double_const(lin_table, "EXPTIME"));
6898 }
6899 if(x == NULL || y == NULL) {
6900 cpl_vector_unwrap((cpl_vector *)x);
6901 cpl_vector_unwrap((cpl_vector *)y);
6902 /*
6903 * As x and y are const vectors, if they would be defined at the
6904 * beginning of the function (required for skip_if - end_skip
6905 * scheme), they couldn't be initialised to NULL (required too).
6906 * Therefore, they are considered apart from the scheme.
6907 */
6908 skip_if(1);
6909 }
6910
6911 cpl_msg_info(cpl_func, "Polynomial fitting for the LINEARITY");
6912 poly_linfit = irplib_polynomial_fit_1d_create_chiq(x, y, order, &mse);
6913
6914 if(order == cpl_vector_get_size(x) - 1) {
6915 cpl_msg_warning(cpl_func, "The fitting is not over-determined.");
6916 mse = 0;
6917 }
6918
6919 if(poly_linfit == NULL) {
6920 cpl_vector_unwrap((cpl_vector *)x);
6921 cpl_vector_unwrap((cpl_vector *)y);
6922 /* See comment in previous error checking if() statement */
6923 skip_if(1);
6924 }
6925
6926 cpl_vector_unwrap((cpl_vector *)x);
6927 cpl_vector_unwrap((cpl_vector *)y);
6928
6929 for(deg = 0; deg <= order; deg++) {
6930 const double coeff =
6931 cpl_polynomial_get_coeff(poly_linfit, &deg);
6932 char *name_o =
6933 cpl_sprintf("ESO QC LIN COEF%" CPL_SIZE_FORMAT "", deg);
6934 assert(name_o != NULL);
6935 skip_if(cpl_propertylist_append_double(qclist, name_o, coeff));
6936 skip_if(cpl_propertylist_set_comment(qclist,name_o,
6938 cpl_free(name_o);
6939 pcoeffs[deg] = coeff;
6940 }
6941 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT, mse));
6942 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
6944
6945
6946 } else {
6947 if (opt_nir == NIR) {
6948 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6949 (double *)cpl_table_get_data_double_const(lin_table,
6950 "DIT"));
6951 } else {
6952 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
6953 (double *)cpl_table_get_data_double_const(lin_table,
6954 "EXPTIME"));
6955 }
6956
6957
6958 first = cpl_imagelist_get_const(lin_inputs, 0);
6959 sizex = cpl_image_get_size_x(first);
6960 sizey = cpl_image_get_size_y(first);
6961
6962 vsize = cpl_vector_get_size(x);
6963
6964 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
6965
6966 *coeffs_cube =
6967 cpl_fit_imagelist_polynomial(x, lin_inputs, 0,
6968 order, FALSE, CPL_TYPE_FLOAT,
6969 fiterror);
6970
6971 cpl_vector_unwrap((cpl_vector*)x);
6972 irplib_ensure(*coeffs_cube != NULL, CPL_ERROR_UNSPECIFIED,
6973 "Failed polynomial fit");
6974
6975 for(i = 0; i <= order; i++) {
6976 cpl_image *image = cpl_imagelist_get(*coeffs_cube, i);
6977 const double coeff = cpl_image_get_median(image);
6978 char * name_o1 = cpl_sprintf("ESO QC LIN COEF%d", i);
6979 char * name_o2 = cpl_sprintf("ESO QC LIN COEF%d ERR", i);
6980 pcoeffs[i] = coeff;
6981 assert(name_o1 != NULL);
6982 assert(name_o2 != NULL);
6983 skip_if(cpl_propertylist_append_double(qclist, name_o1, coeff));
6984 skip_if(cpl_propertylist_set_comment(qclist,name_o1,
6986 cpl_free(name_o1);
6987 name_o1= NULL;
6988 skip_if(cpl_propertylist_append_double(qclist, name_o2,
6989 cpl_image_get_stdev(image)));
6990 skip_if(cpl_propertylist_set_comment(qclist,name_o2,
6992 cpl_free(name_o2);
6993 name_o2= NULL;
6994 }
6995
6996 if(order == vsize - 1) {
6997 cpl_msg_warning(cpl_func, "The fitting is not over-determined.");
6998 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
6999 0.0));
7000 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7002
7003
7004 } else {
7005 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
7006 cpl_image_get_median(fiterror)));
7007 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
7009
7010 }
7011 }
7012
7013 skip_if(xsh_detmon_lg_lineff(pcoeffs, qclist, ref_level, order));
7014
7015 if(mode & IRPLIB_LIN_PIX2PIX) {
7016 int nbpixs;
7017 *bpm = xsh_detmon_bpixs(*coeffs_cube, bpmbin, kappa, &nbpixs);
7018 skip_if(*bpm == NULL);
7019 skip_if(cpl_propertylist_append_int(qclist, DETMON_QC_NUM_BPM,
7020 nbpixs));
7021 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_NUM_BPM,
7023 }
7024
7025 end_skip;
7026
7027 cpl_vector_delete(diffdits);
7028 cpl_polynomial_delete(poly_linfit);
7029 cpl_imagelist_delete(lin_inputs);
7030 cpl_vector_delete(vcoeffs);
7031 cpl_image_delete(fiterror);
7032
7033 return lin_table;
7034
7035}
7036
7037/*--------------------------------------------------------------------------*/
7061/*--------------------------------------------------------------------------*/
7062static cpl_error_code
7063xsh_detmon_lin_table_fill_row(cpl_table * lin_table, double c_dit,
7064 cpl_imagelist * linearity_inputs,
7065 const cpl_imagelist * ons,
7066 const cpl_imagelist * offs,
7067 int llx,
7068 int lly,
7069 int urx,
7070 int ury,
7071 const int pos,
7072 const int nskip,
7073 unsigned mode)
7074{
7075 cpl_image * extracted=NULL;
7076
7077 cpl_ensure_code(lin_table != NULL, CPL_ERROR_NULL_INPUT);
7078 cpl_ensure_code(ons != NULL, CPL_ERROR_NULL_INPUT);
7079 cpl_ensure_code(offs != NULL, CPL_ERROR_NULL_INPUT);
7080
7081 if (mode & IRPLIB_LIN_PIX2PIX) {
7082 cpl_msg_debug(cpl_func,"checking linearity inputs");
7083 cpl_ensure_code(linearity_inputs != NULL, CPL_ERROR_NULL_INPUT);
7084 }
7085
7086
7087 if (mode & IRPLIB_LIN_NIR) {
7088 cpl_table_set(lin_table, "DIT", pos, c_dit);
7089 } else if (mode & IRPLIB_LIN_OPT) { /*OPT */
7090 cpl_table_set(lin_table, "EXPTIME", pos, c_dit);
7091 } else {
7092 cpl_msg_error(cpl_func, "Mandatory mode not given");
7093 }
7094
7095 {
7096 const cpl_image * off2;
7097 if (cpl_imagelist_get_size(offs) == 1 || mode & IRPLIB_LIN_COLLAPSE)
7098 off2 = cpl_imagelist_get_const(offs, 0);
7099 else
7100 off2 = cpl_imagelist_get_const(offs, 1);
7101
7102 extracted = xsh_detmon_subtracted_avg(cpl_imagelist_get_const(ons, 0),
7103 cpl_imagelist_get_const(offs, 0),
7104 cpl_imagelist_get_const(ons, 1),
7105 off2,
7106 llx, lly, urx, ury);
7107 cpl_ensure_code(extracted != NULL, cpl_error_get_code());
7108 }
7109
7110 {
7111 double median = cpl_image_get_median(extracted);
7112 double mean= cpl_image_get_mean(extracted);
7113 cpl_table_set(lin_table, "MED", pos, median);
7114 cpl_table_set(lin_table, "MEAN", pos, mean);
7115
7116 cpl_table_set(lin_table, "MED_DIT", pos, median / c_dit);
7117 cpl_table_set(lin_table, "MEAN_DIT", pos, mean / c_dit);
7118 }
7119
7120 /* Insert to the imagelist used to fit the polynomial */
7121 if(mode & IRPLIB_LIN_PIX2PIX) {
7122 cpl_error_code error = cpl_imagelist_set(linearity_inputs, extracted,
7123 pos-nskip);
7124 cpl_ensure_code(!error, error);
7125 } else {
7126 cpl_image_delete(extracted);
7127 }
7128
7129 return cpl_error_get_code();
7130}
7131
7132static double irplib_calculate_total_noise_smooth(const cpl_image* pimage,
7133 int pattern_x, int pattern_y)
7134{
7135 cpl_image * p_tmp_image = 0;
7136 cpl_image * psmooth_image = 0;
7137 double ret_noise;
7138 cpl_mask * mask = cpl_mask_new(pattern_x, pattern_y);
7139 cpl_mask_not(mask);
7140 p_tmp_image = cpl_image_duplicate(pimage);
7141 cpl_image_filter_mask(p_tmp_image,pimage, mask,CPL_FILTER_MEDIAN ,CPL_BORDER_FILTER);
7142 cpl_image_divide_scalar(p_tmp_image, cpl_image_get_median(pimage));
7143 psmooth_image = cpl_image_divide_create(pimage,p_tmp_image);
7144 ret_noise = irplib_calculate_total_noise(psmooth_image);
7145 cpl_mask_delete(mask);
7146 cpl_image_delete(psmooth_image);
7147 cpl_image_delete(p_tmp_image);
7148 return ret_noise;
7149}
7150
7151static double irplib_calculate_total_noise(const cpl_image* pimage)
7152{
7153 double total_noise = -1;
7154 unsigned long max_bin_size = 1E5;
7155 const double hstart = cpl_image_get_min(pimage);
7156 const double hrange = cpl_image_get_max(pimage) - hstart;
7157 const unsigned long nbins = max_bin_size;
7158 cpl_error_code err = CPL_ERROR_NONE;
7159 /* apply histogram method */
7160 irplib_hist * phist = 0;
7161 phist = irplib_hist_new();
7162 /* 2 extra-bins for possible out-of-range values */
7163
7164 irplib_hist_init(phist, nbins, hstart, hrange);
7165 err = irplib_hist_fill(phist, pimage);
7166 if (err == CPL_ERROR_NONE)
7167 {
7168 unsigned int i = 0;
7169 double x0 = 0;
7170 double area = 0;
7171 double offset = 0;
7172
7173 /* prepare vector */
7174 unsigned long n_bins = irplib_hist_get_nbins(phist);
7175 double start = irplib_hist_get_start(phist);
7176 double bin_size = irplib_hist_get_bin_size(phist);
7177 cpl_vector* pdata_vector = cpl_vector_new(n_bins);
7178 cpl_vector* ppos_vector = cpl_vector_new(n_bins);
7179 cpl_table* ptable = cpl_table_new(n_bins);
7180 cpl_table_new_column(ptable, "bin", CPL_TYPE_DOUBLE);
7181 cpl_table_new_column(ptable, "value", CPL_TYPE_DOUBLE);
7182 for(i = 0; i < n_bins; i++)
7183 {
7184 unsigned int value = irplib_hist_get_value(phist, i);
7185 double dvalue = (double)(value);
7186 cpl_vector_set(pdata_vector, i, dvalue);
7187 cpl_vector_set(ppos_vector, i, start + i * bin_size);
7188
7189 cpl_table_set(ptable, "bin", i, start + i * bin_size);
7190 cpl_table_set(ptable, "value", i, dvalue);
7191 }
7192 err = cpl_vector_fit_gaussian(ppos_vector, NULL, pdata_vector, NULL, CPL_FIT_ALL, &x0, &total_noise, &area, &offset, NULL, NULL, NULL );
7193 if (err == CPL_ERROR_NONE)
7194 {
7195 cpl_msg_info(cpl_func, "FPN Calculation: histogram x0[%f] total_noise[%f] area[%f] offset[%f]", x0, total_noise, area, offset);
7196 }
7197 else
7198 {
7199 cpl_msg_warning(cpl_func, "FPN could not be computed due failed Gaussian Fit, err msg [%s]", cpl_error_get_message());
7200 cpl_error_reset();
7201 }
7202 cpl_table_delete(ptable);
7203 cpl_vector_delete(ppos_vector);
7204 cpl_vector_delete(pdata_vector);
7205 }
7206 else
7207 {
7208 cpl_msg_warning(cpl_func, "FPN could not be computed due failed histogram computation, err msg [%s]", cpl_error_get_message());
7209 cpl_error_reset();
7210 }
7211 irplib_hist_delete(phist);
7212
7213 return total_noise;
7214}
7215
7216static double irplib_compute_err(double gain, double ron, double FA)
7217{
7218 double int_gain = (gain * gain - 1) / 12;
7219 if (int_gain < 0)
7220 {
7221 int_gain = 0;
7222 }
7223 return sqrt(ron * ron + FA / gain + int_gain);
7224}
7225
7226static double irplib_fpn_lg(const cpl_image* f1, int* range, double gain ,
7227 FPN_METHOD fpn_method, int smooth_size, double* mse)
7228{
7229 cpl_image* im_diff = 0;
7230 const cpl_image* im_f1 = f1;
7231 cpl_image* im_inrange1 = 0;
7232 double FA = 0;
7233 double s_tot = 0; /* absolute total noise */
7234 double s_fpn = 0; /* fixed pattern noise */
7235 double sr_fpn = 0; /* relative structural noise */
7236 /*che cinput*/
7237 if (gain<=0) {
7238 /* put dummy values Negative to indicate a problem occurred
7239 (FPN should be always positive) */
7240 cpl_msg_warning(cpl_func,"gain[%f]<0", gain);
7241 cpl_msg_warning(cpl_func,"We set dummy values for FPN");
7242 s_fpn=-999.;
7243 sr_fpn=-999;
7244 return sr_fpn;
7245 }
7246 if (range)
7247 {
7248 im_inrange1 = cpl_image_extract(f1, range[0], range[1], range[2], range[3]);
7249 im_f1 = im_inrange1;
7250 }
7251 FA = cpl_image_get_median(im_f1);
7252
7253 /* apply histogram method */
7254 /* Is this irplib function giving the right result?? */
7255 switch (fpn_method)
7256 {
7257 case FPN_SMOOTH:
7258 cpl_msg_info(cpl_func,"SMOOTH method is used for FPN, pattern size[%d x %d] pixels",smooth_size,smooth_size );
7259 s_tot = irplib_calculate_total_noise_smooth(im_f1,smooth_size,smooth_size);
7260 break;
7261 case FPN_HISTOGRAM:
7262 cpl_msg_info(cpl_func,"HISTOGRAM method is used for FPN");
7263 s_tot = irplib_calculate_total_noise(im_f1);
7264 break;
7265 default:
7266 s_tot = -1;
7267 sr_fpn = -1;
7268 cpl_msg_warning(cpl_func,"fpn_method is not defined");
7269 break;
7270 }
7271 if (s_tot > 0)
7272 {
7273 if (FA<0)
7274 {
7275 /* put dummy values Negative to indicate a problem occurred
7276 (FPN should be always positive) */
7277 cpl_msg_warning(cpl_func,"Median flux on sum of flats<0");
7278 cpl_msg_warning(cpl_func,"We set dummy values for FPN");
7279 s_fpn=-999.;
7280 sr_fpn=-999;
7281 }
7282
7283 if ((s_tot * s_tot - FA / gain) > 0)
7284 {
7285 s_fpn = sqrt(s_tot * s_tot - FA / gain);
7286 sr_fpn = s_fpn / FA;
7287 *mse = (irplib_compute_err(gain, 0, FA)) * gain / FA;
7288 } else {
7289 /* put dummy values Negative to indicate a problem occurred
7290 (FPN should be always positive) */
7291 cpl_msg_warning(cpl_func,"s_tot * s_tot < FA / gain");
7292 cpl_msg_warning(cpl_func,"We set dummy values for FPN");
7293 s_fpn=-999.;
7294 sr_fpn=-999;
7295 *mse = -1;
7296 }
7297 /*
7298 cpl_msg_debug(cpl_func, "FPN Calculation: FA[%f] s_tot[%f] photon_noise[%f] s_fpn[%f] sr_fpn[%f] mse[%f]", FA, s_tot, photon_noise, s_fpn, sr_fpn, *mse);
7299 */
7300 }
7301 cpl_image_delete(im_diff);
7302 if (range)
7303 {
7304 cpl_image_delete(im_inrange1);
7305 }
7306 return sr_fpn;
7307}
7308
7309
7310static cpl_imagelist * irplib_load_fset_wrp(const cpl_frameset * pframeset,
7311 cpl_type type , int whichext)
7312{
7313 /* FIXME: load image into window size from beginning to
7314 * save all the extracts */
7315 return xsh_detmon_load_frameset_window(pframeset, type, 0, whichext,
7322}
7323
7324static cpl_imagelist * irplib_load_fset_wrp_ext(const cpl_frameset * pframeset,
7325 cpl_type type , int whichext)
7326{
7327 int i = whichext; /* fake code to avoid compiler warning */
7328 cpl_imagelist* offs = cpl_imagelist_new();
7329 xsh_detmon_lg_config.load_fset(pframeset, type, offs);
7330 i++;
7331 return offs;
7332}
7333
7334static cpl_error_code irplib_table_create_column(cpl_table* ptable,
7335 cpl_propertylist* plist)
7336{
7337 if (ptable && plist)
7338 {
7339 int size = cpl_propertylist_get_size(plist);
7340 int i = 0;
7341 for (i = 0; i < size; i++)
7342 {
7343 cpl_property* pprop = cpl_propertylist_get(plist,i);
7344 if (pprop)
7345 {
7346 const char* pname = cpl_property_get_name(pprop);
7347 if (pname)
7348 {
7349 cpl_table_new_column(ptable, pname, cpl_property_get_type(pprop));
7350 if (cpl_error_get_code() != CPL_ERROR_NONE)
7351 {
7352 cpl_msg_warning(cpl_func, "cannot create new column[%s], err[%s]", pname, cpl_error_get_message());
7353 break; /* leave the cycle */
7354 }
7355 }
7356 }
7357 }
7358 }
7359 return cpl_error_get_code();
7360}
7361
7362static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable,
7363 cpl_propertylist* plist, int row)
7364{
7365 cpl_error_code err = CPL_ERROR_NONE;
7366 if (ptable && plist)
7367 {
7368 int size = cpl_propertylist_get_size(plist);
7369 int i = 0;
7370 for (i = 0; i < size; i++)
7371 {
7372 cpl_property* pprop = cpl_propertylist_get(plist,i);
7373 if (pprop)
7374 {
7375 const char* pname = cpl_property_get_name(pprop);
7376 double value = cpl_property_get_double(pprop);
7377 if (pname)
7378 {
7379 cpl_table_set_double(ptable, pname, row, value);
7380 if (cpl_error_get_code() != CPL_ERROR_NONE)
7381 {
7382 cpl_msg_warning(cpl_func, "cannot write value to the table, column[%s] value[%f], err[%s]", pname, value, cpl_error_get_message());
7383 cpl_error_reset();
7384 break; /* leave the cycle */
7385 }
7386 }
7387 }
7388 }
7389 }
7390 return err;
7391}
7392
7393cpl_error_code xsh_detmon_check_order(const double *exptime, int sz,
7394 double tolerance, int order)
7395{
7396 int nsets = 0;
7397 int i = 0;
7398 /* 1. Determine number of groups */
7399 /* cpl_msg_warning(cpl_func, "xsh_detmon_check_order sz[%i]", sz);*/
7400 do
7401 {
7402 /* cpl_msg_warning(cpl_func, "xsh_detmon_check_order i[%i] exptime[%g]", i, exptime[i]); */
7403 nsets++;
7404 do
7405 {
7406 i++;
7407 if(i == sz - 1)
7408 {
7409 break;
7410 }
7411 } while(fabs(exptime[i-1] - exptime[i]) < tolerance);
7412 } while(i < sz - 1);
7413 /* the very last adjustment for the last group */
7414 if ( !( fabs(exptime[i-1] - exptime[i]) < tolerance ) ) nsets++;
7415 if(nsets <= order)
7416 {
7417 cpl_error_set_message(cpl_func,CPL_ERROR_INCOMPATIBLE_INPUT,
7418 "Not enough frames for the polynomial"
7419 " fitting. nsets = %d <= %d order",
7420 nsets,order);
7421 }
7422 return cpl_error_get_code();
7423}
7424
7425static cpl_error_code
7427 cpl_frameset * frameset,
7428 const cpl_parameterlist * parlist,
7429 const cpl_frameset *usedframes,
7430 const cpl_imagelist *coeffs,
7431 const char *recipe_name,
7432 const cpl_propertylist *mypro_coeffscube,
7433 const char * package,
7434 const char * name_o)
7435{
7436 return(cpl_dfs_save_imagelist
7437 (frameset, NULL, parlist, usedframes, NULL,coeffs, CPL_BPP_IEEE_FLOAT,
7438 recipe_name, mypro_coeffscube, NULL, package,
7439 name_o));
7440}
7441
7442static void xsh_detmon_lg_add_empty_image(cpl_imagelist* imlist, int pos)
7443{
7444 const cpl_image* first = cpl_imagelist_get(imlist, 0);
7445 if (first)
7446 {
7447 int x = cpl_image_get_size_x(first);
7448 int y = cpl_image_get_size_y(first);
7449 cpl_type type = cpl_image_get_type(first);
7450 cpl_image * blank = cpl_image_new(x, y, type);
7451 cpl_imagelist_set(imlist, blank, pos);
7452 }
7453}
7454
7455
7456cpl_error_code
7457xsh_detmon_lg_set_tag(cpl_frameset* set, const char** tag_on, const char** tag_off)
7458{
7459 int ntag_old=0;
7460 int ntag_new=0;
7461
7462 ntag_old=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_OLD);
7463 ntag_new=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_NEW);
7464 if(ntag_old) {
7465 *tag_on=DETMON_LG_ON_RAW_OLD;
7466 *tag_off=DETMON_LG_OFF_RAW_OLD;
7467 } else if (ntag_new) {
7468 *tag_on=DETMON_LG_ON_RAW_NEW;
7469 *tag_off=DETMON_LG_OFF_RAW_NEW;
7470 } else {
7471 cpl_msg_error(cpl_func,"Provide %s and %s (or %s and %s) input frames",
7474 }
7475
7476
7477 return cpl_error_get_code();
7478}
static double exptime
static char mode[32]
static double sigma
int size
int * y
int * x
unsigned int first
Definition: irplib_error.c:88
irplib_error errors[MAX_ERRORS]
Definition: irplib_error.c:86
double xsh_detmon_retrieve_par_double(const char *parn, const char *pipeline_name, const char *recipe_name, const cpl_parameterlist *parlist)
Definition: xsh_detmon.c:241
cpl_boolean opt_nir
Definition: xsh_detmon.c:100
cpl_error_code xsh_detmon_fill_parlist(cpl_parameterlist *parlist, const char *recipe_name, const char *pipeline_name, int npars,...)
Definition: xsh_detmon.c:132
int xsh_detmon_retrieve_par_int(const char *parn, const char *pipeline_name, const char *recipe_name, const cpl_parameterlist *parlist)
Definition: xsh_detmon.c:211
double irplib_pfits_get_exptime(const cpl_propertylist *plist)
Definition: xsh_detmon.c:271
static cpl_error_code TYPE_ADD() xsh_ksigma_clip(const CPL_TYPE *pi, cpl_binary *pm, int llx, int lly, int urx, int ury, int nx, double var_sum, int npixs, double kappa, int nclip, double tolerance, double *mean, double *stdev)
static cpl_error_code xsh_detmon_lg_save_image_with_pro_keys(cpl_image *image, const char *name_o, cpl_propertylist *xheader)
Save cube product.
int nx
double xsh_detmon_gain_prepare_table(const cpl_imagelist *offs, unsigned mode, int llx, int lly, int urx, int ury, double kappa, int nclip, double avg_off1, double std, const int pos, cpl_table *gain_table, double *avg_off2, double *sig_off_dif)
double kappa
Definition: xsh_detmon_lg.c:81
static cpl_error_code xsh_detmon_lg_find_dits_ndits(const cpl_vector *exptimes, const cpl_vector *vec_ndits, double tolerance, cpl_vector **diff_dits, cpl_vector **diff_ndits)
cpl_error_code xsh_detmon_lg_fill_parlist(cpl_parameterlist *parlist, const char *recipe_name, const char *pipeline_name, const char *method, int order, double kappa, int niter, int llx, int lly, int urx, int ury, int ref_level, const char *intermediate, const char *autocorr, const char *collapse, const char *rescale, const char *pix2pix, const char *bpmbin, int filter, int m, int n, double tolerance, const char *pafgen, const char *pafname, int llx1, int lly1, int urx1, int ury1, int llx2, int lly2, int urx2, int ury2, int llx3, int lly3, int urx3, int ury3, int llx4, int lly4, int urx4, int ury4, int llx5, int lly5, int urx5, int ury5, int exts, cpl_boolean opt_nir)
Generic parlist filling for Lin/Gain recipe.
const char * pafname
int ref_level
Definition: xsh_detmon_lg.c:89
static double irplib_calculate_total_noise(const cpl_image *pimage)
static cpl_error_code xsh_detmon_add_adl_column(cpl_table *, cpl_boolean)
Compute ADL column of Linearity Table.
static cpl_error_code xsh_detmon_lg_qc_med(const cpl_table *, cpl_propertylist *, int)
MED method final computation. The median and stdev of the column "GAIN", and the median of the column...
static cpl_image * xsh_detmon_bpixs(const cpl_imagelist *, cpl_boolean, const double, int *)
Produce bad pixel map according to coefficients' cube.
int llx1
Definition: xsh_detmon_lg.c:93
double xsh_detmon_gain_prepare_autocorr(unsigned mode, const int pos, double autocorr, int m, int n, cpl_imagelist *diff_flats, cpl_image *on_dif, cpl_imagelist *autocorr_images)
int threshold_max
Definition: xsh_detmon_lg.c:84
int urx5
static double irplib_pfits_get_prop_double(const cpl_propertylist *plist, const char *prop_name)
static cpl_error_code xsh_detmon_pair_extract_next(const cpl_frameset *set, int *index, int *next_element, double *dit_array, cpl_frameset **pair, double tolerance)
static cpl_error_code xsh_detmon_lg_core(cpl_frameset *cur_fset_on, cpl_frameset *cur_fset_off, int *index_on, int *index_off, double *exptime_on, double *exptime_off, int whichext, int whichset, const char *recipe_name, const char *pipeline_name, const char *pafregexp, const cpl_propertylist *pro_lintbl, const cpl_propertylist *pro_gaintbl, const cpl_propertylist *pro_coeffscube, const cpl_propertylist *pro_bpm, const cpl_propertylist *pro_corr, const cpl_propertylist *pro_diff, const char *package, int(*load_fset)(const cpl_frameset *, cpl_type, cpl_imagelist *), int nsets, cpl_boolean opt_nir, cpl_frameset *frameset, const cpl_parameterlist *parlist, cpl_frameset *cur_fset)
Core: Reduction and saving (encapsulated to avoid repetition)
int niter
Definition: xsh_detmon_lg.c:82
static cpl_error_code xsh_detmon_lg_reduce_init(cpl_table *, cpl_table *, cpl_imagelist **, const cpl_boolean)
Create columns of product tables and init linearity_inputs.
static cpl_error_code xsh_detmon_lg_lineff(double *, cpl_propertylist *, int, int)
Linearity effective correction (LIN.EFF) computation.
cpl_boolean bpmbin
int(* load_fset)(const cpl_frameset *, cpl_type, cpl_imagelist *)
static cpl_error_code xsh_detmon_lg_save_plane(const cpl_parameterlist *parlist, cpl_frameset *frameset, const cpl_frameset *usedframes, int whichext, const char *recipe_name, cpl_propertylist *mypro_coeffscube, cpl_propertylist *linc_plane_qclist, const char *package, const char *NAME_O, cpl_image *plane)
Save cube product.
static void xsh_detmon_lg_add_empty_image(cpl_imagelist *imlist, int pos)
cpl_image * xsh_detmon_autocorrelate(const cpl_image *input2, const int m, const int n)
cpl_boolean autocorr
double lamp_stability
cpl_boolean pafgen
int lly
Definition: xsh_detmon_lg.c:86
int lly5
int xsh_detmon_compute_badpixmap(cpl_boolean opt_nir, const int nsets, const cpl_table *linear_table, const cpl_imagelist *linearity_inputs, int nbpixs, cpl_vector *x, cpl_propertylist *gaint_qclist, cpl_image **bpms_ptr)
cpl_error_code xsh_detmon_lg_fill_parlist_nir_default_mr(cpl_parameterlist *parlist, const char *recipe_name, const char *pipeline_name)
static char * xsh_detmon_lg_set_paf_name_and_header(cpl_frame *ref_frame, int flag_sets, int which_set, int whichext, const char *paf_suf, cpl_propertylist **plist)
int xsh_detmon_lg_dfs_set_groups(cpl_frameset *, const char *, const char *)
DFS related function.
static double xsh_detmon_autocorr_factor(const cpl_image *, cpl_image **, int, int)
Produce bad pixel map by comparing to coefficients' cube fits to actual intensity values.
static cpl_error_code xsh_detmon_fpn_compute(const cpl_frameset *set_on, int *index_on, int last_linear_best, cpl_propertylist *lint_qclist, int llx, int lly, int urx, int ury, double gain, int whichext, FPN_METHOD fpn_method, int smooth_size)
int lly3
static cpl_error_code xsh_detmon_lg_check_defaults(const cpl_image *)
Check and set default values with depend on the inputs.
static cpl_error_code xsh_detmon_lg_reduce_dit(const cpl_frameset *set_on, int *index_on, double *exptime_on, const int dit_nb, int *dit_nskip, const cpl_frameset *set_off, int *index_off, double *exptime_off, int *next_on, int *next_off, cpl_table *linear_table, cpl_table *gain_table, cpl_imagelist *linearity_inputs, cpl_propertylist *qclist, cpl_boolean opt_nir, cpl_imagelist *autocorr_images, cpl_imagelist *diff_flats, cpl_imagelist *opt_offs, int whichext, int *rows_linear_affected, int *rows_gain_affected)
Reduction step to be applied together to frames of same DIT.
static cpl_error_code xsh_detmon_lg_rescale(cpl_imagelist *)
Rescale of images (one to another level)
static cpl_error_code xsh_detmon_opt_contamination(const cpl_imagelist *, const cpl_imagelist *, unsigned mode, cpl_propertylist *)
Contamination computation (OPT only)
static cpl_error_code xsh_detmon_lin_table_create(cpl_table *, const cpl_boolean)
int exts
cpl_error_code xsh_detmon_lg_set_tag(cpl_frameset *set, const char **tag_on, const char **tag_off)
static cpl_error_code xsh_detmon_lg_save_imagelist_with_pro_keys(cpl_imagelist *imagelist, const char *name_o, cpl_propertylist *xheader)
Save cube product.
static cpl_error_code xsh_detmon_lg_reduce(const cpl_frameset *, const cpl_frameset *, int *index_on, int *index_off, double *exptime_on, double *exptime_off, int *next_index_on, int *next_index_off, cpl_imagelist **, cpl_table *, cpl_table *, cpl_image **, cpl_imagelist *, cpl_imagelist *, cpl_propertylist *, cpl_propertylist *, cpl_propertylist *, cpl_propertylist *, int(*load_fset)(const cpl_frameset *, cpl_type, cpl_imagelist *), const cpl_boolean, int)
Apply linearity and gain reduction algorithms.
cpl_boolean lamp_ok
cpl_boolean rescale
int ury2
static double irplib_compute_err(double gain, double ron, double photon_noise)
int threshold
Definition: xsh_detmon_lg.c:90
int llx2
Definition: xsh_detmon_lg.c:97
static cpl_error_code xsh_detmon_lg_save_cube(const cpl_parameterlist *parlist, cpl_frameset *frameset, const cpl_frameset *usedframes, int whichext, const char *recipe_name, cpl_propertylist *mypro_coeffscube, cpl_propertylist *linc_qclist, const char *package, const char *NAME_O, cpl_imagelist *coeffs)
Save cube product.
static cpl_error_code xsh_detmon_lg_reduce_set(int i, cpl_frameset *frameset, int nsets, const char *tag_on, const char *tag_off, const char *recipe_name, const char *pipeline_name, const char *pafregexp, const cpl_propertylist *pro_lintbl, const cpl_propertylist *pro_gaintbl, const cpl_propertylist *pro_coeffscube, const cpl_propertylist *pro_bpm, const cpl_propertylist *pro_corr, const cpl_propertylist *pro_diff, const char *package, int(*load_fset)(const cpl_frameset *, cpl_type, cpl_imagelist *), const cpl_boolean opt_nir, const cpl_parameterlist *parlist, cpl_size *selection)
static cpl_error_code xsh_detmon_lg_reduce_all(const cpl_table *, cpl_propertylist *, cpl_propertylist *, cpl_propertylist *, cpl_propertylist *, cpl_imagelist **, cpl_image **, const cpl_imagelist *, const cpl_table *, int, cpl_boolean)
Final reduction step (after DIT-per-DIT reduction): fit linearity data and determine corresponding QC...
static int irplib_pfits_get_ndit(const cpl_propertylist *plist)
find out the character string associated to the DIT keyword in a propertylist
int ury5
static cpl_error_code xsh_detmon_lg_qc_ptc(const cpl_table *, cpl_propertylist *, unsigned, int)
PTC (Photon Transfer Curve) method final computation.
static int xsh_detmon_lg_check_before_gain(const cpl_vector *x, const cpl_vector *y)
int llx
Definition: xsh_detmon_lg.c:85
int m
Definition: xsh_detmon_lg.c:91
cpl_table * xsh_detmon_lin(const cpl_imagelist *imlist_on, const cpl_imagelist *imlist_off, const cpl_vector *exptimes, double tolerance, int llx, int lly, int urx, int ury, int order, int ref_level, double kappa, cpl_boolean bpmbin, cpl_propertylist *qclist, unsigned mode, cpl_imagelist **coeffs_cube, cpl_image **bpm)
Linearity computation.
static cpl_error_code xsh_detmon_gain_table_create(cpl_table *, const cpl_boolean)
int n
Definition: xsh_detmon_lg.c:92
static cpl_error_code xsh_detmon_lg_extract_extention_header(cpl_frameset *frameset, cpl_propertylist *gaint_qclist, cpl_propertylist *lint_qclist, cpl_propertylist *linc_qclist, cpl_propertylist *bpm_qclist, int whichext)
Extract extension headers if multi-extension.
static cpl_error_code xsh_detmon_lin_table_fill_row(cpl_table *, double, cpl_imagelist *, const cpl_imagelist *, const cpl_imagelist *, int, int, int, int, const int, const int, unsigned)
Fill i-th row in Linearity Table: DIT or EXPTIME, MEAN, MED, MEAN_DIT, MED_DIT.
double gain_threshold
cpl_boolean intermediate
static cpl_error_code irplib_table_create_column(cpl_table *ptable, cpl_propertylist *plist)
static cpl_error_code xsh_detmon_check_saturation_on_pair(cpl_imagelist *autocorr_images, cpl_imagelist *diff_flats, const cpl_imagelist *ons, const cpl_imagelist *offs, double kappa, int nclip, int llx, int lly, int urx, int ury, double saturation_limit, const int pos, unsigned mode, int *rows_linear_affected)
Operate on input ON and OFF images related to gain Computes all quantities needed to determine the ga...
const char * method
Definition: xsh_detmon_lg.c:78
cpl_error_code xsh_detmon_lg_fill_parlist_opt_default(cpl_parameterlist *parlist, const char *recipe_name, const char *pipeline_name)
Parlist filling with OPT required parameters and its default values.
int urx
Definition: xsh_detmon_lg.c:87
static cpl_error_code xsh_detmon_table_fill_invalid(cpl_table *ptable, double code)
double tolerance
static char * xsh_detmon_lg_set_paf_name_and_header_ext(cpl_frame *ref_frame, int flag_sets, int which_set, int whichext, const char *paf_suf, cpl_propertylist **plist)
int ury
Definition: xsh_detmon_lg.c:88
static cpl_error_code xsh_detmon_lg_lamp_stab(const cpl_frameset *, const cpl_frameset *, cpl_boolean, int)
Compute lamp stability.
int ny
int urx2
Definition: xsh_detmon_lg.c:99
cpl_table * xsh_detmon_gain(const cpl_imagelist *imlist_on, const cpl_imagelist *imlist_off, const cpl_vector *exptimes, const cpl_vector *ndit, double tolerance, int llx, int lly, int urx, int ury, double kappa, int nclip, int xshift, int yshift, cpl_propertylist *qclist, unsigned mode, cpl_imagelist **diff_imlist, cpl_imagelist **autocorr_imlist)
Gain computation.
static cpl_error_code xsh_detmon_gain_compute_qc(double kappa, int nclip, const int pos, const cpl_imagelist *offs, unsigned mode, double double_adu, double avg_on1, double avg_on2, double avg_off1, double avg_off2, double sigma, double sig_off_dif, double gain, int c_ndit, double gain_corr, double autocorr, cpl_image *on_dif, cpl_table *gain_table)
static cpl_error_code xsh_detmon_lg_retrieve_parlist(const char *, const char *, const cpl_parameterlist *, cpl_boolean)
Parlist extraction and copy to global struct variable.
static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table *ptable, cpl_propertylist *plist, int row)
static cpl_error_code xsh_detmon_lg_save_paf_product(cpl_frame *ref_frame, int flag_sets, int which_set, int whichext, const char *pafregexp, const char *procatg, const char *pipeline_name, const char *recipe_name, const char *paf_suf, cpl_propertylist *qclist, const int ext)
int lly4
int nb_extensions
static struct @2 xsh_detmon_lg_config
static cpl_propertylist * xsh_detmon_lg_extract_qclist_4plane(cpl_propertylist *linc_qclist, const int ip)
cpl_error_code xsh_detmon_lg_fill_parlist_nir_default(cpl_parameterlist *parlist, const char *recipe_name, const char *pipeline_name)
Parlist filling with NIR required parameters and its default values.
double saturation_limit
static cpl_imagelist * irplib_load_fset_wrp_ext(const cpl_frameset *, cpl_type, int)
int llx4
static cpl_propertylist * xsh_detmon_load_pro_keys(const char *NAME_O)
Load pro keys.
int ury3
static void irplib_free(char **pointer)
cpl_boolean split_coeffs
static cpl_error_code xsh_detmon_lg_fits_coeffs_and_bpm2chip(cpl_imagelist **coeffs_ptr, cpl_image **bpms_ptr)
Fits COEFFS_CUBE and BPM outputs to whole-chip size images (DFS05711)
enum _FPN_METHOD FPN_METHOD
Definition: xsh_detmon_lg.c:75
int urx1
Definition: xsh_detmon_lg.c:95
int lly2
Definition: xsh_detmon_lg.c:98
static cpl_error_code xsh_detmon_gain_table_fill_row(cpl_table *gain_table, double c_dit, int c_ndit, cpl_imagelist *autocorr_images, cpl_imagelist *diff_flats, const cpl_imagelist *ons, const cpl_imagelist *offs, double kappa, int nclip, int llx, int lly, int urx, int ury, int m, int n, double saturation_limit, double gain_threshold, const int pos, unsigned mode, int *rows_affected)
Operate on input ON and OFF images related to gain Computes all quantities needed to determine the ga...
int llx3
int order
Definition: xsh_detmon_lg.c:80
cpl_error_code hdrldemo_detector_shotnoise_model(const cpl_image *ima_data, const double gain, const double ron, cpl_image **ima_errs)
compute photon count error in [ADU]
static double irplib_pfits_get_dit(const cpl_propertylist *)
Find out the character string associated to the DIT keyword (NIR)
int ury4
static cpl_error_code xsh_detmon_lg_save_table_with_pro_keys(cpl_table *table, const char *name_o, cpl_propertylist *xheader, unsigned CPL_IO_MODE)
Save cube product.
int lly1
Definition: xsh_detmon_lg.c:94
cpl_boolean collapse
static cpl_vector * xsh_detmon_lg_find_dits(const cpl_vector *, double)
static cpl_error_code xsh_detmon_lg_save(const cpl_parameterlist *, cpl_frameset *, const char *, const char *, const char *, const cpl_propertylist *, const cpl_propertylist *, const cpl_propertylist *, const cpl_propertylist *, const cpl_propertylist *, const cpl_propertylist *, const char *, cpl_imagelist *, cpl_table *, cpl_table *, cpl_image *, cpl_imagelist *, cpl_imagelist *, cpl_propertylist *, cpl_propertylist *, cpl_propertylist *, cpl_propertylist *, const int, const int, const cpl_frameset *, int)
Save all products.
static double irplib_fpn_lg(const cpl_image *f1, int *range, double gain, FPN_METHOD fpn_method, int, double *mse)
cpl_boolean wholechip
FPN_METHOD fpn_method
cpl_error_code xsh_detmon_lg_fill_parlist_opt_default_mr(cpl_parameterlist *parlist, const char *recipe_name, const char *pipeline_name)
cpl_error_code xsh_detmon_lg_fill_parlist_default_mr(cpl_parameterlist *parlist, const char *recipe_name, const char *pipeline_name)
int urx3
cpl_error_code xsh_detmon_check_order(const double *exptime, int sz, double tolerance, int order)
int ury1
Definition: xsh_detmon_lg.c:96
static double irplib_pfits_get_dit_opt(const cpl_propertylist *)
Find out the character string associated to the DIT keyword (OPT)
int urx4
cpl_error_code xsh_detmon_lg(cpl_frameset *frameset, const cpl_parameterlist *parlist, const char *tag_on, const char *tag_off, const char *recipe_name, const char *pipeline_name, const char *pafregexp, const cpl_propertylist *pro_lintbl, const cpl_propertylist *pro_gaintbl, const cpl_propertylist *pro_coeffscube, const cpl_propertylist *pro_bpm, const cpl_propertylist *pro_corr, const cpl_propertylist *pro_diff, const char *package, int(*compare)(const cpl_frame *, const cpl_frame *), int(*load_fset)(const cpl_frameset *, cpl_type, cpl_imagelist *), const cpl_boolean opt_nir)
_FPN_METHOD
Definition: xsh_detmon_lg.c:70
@ FPN_SMOOTH
Definition: xsh_detmon_lg.c:73
@ FPN_HISTOGRAM
Definition: xsh_detmon_lg.c:72
@ FPN_UNKNOWN
Definition: xsh_detmon_lg.c:71
int fpn_smooth
int filter
double cr
int llx5
cpl_boolean pix2pix
static double irplib_calculate_total_noise_smooth(const cpl_image *pimage, int pattern_x, int pattern_y)
static cpl_error_code xsh_detmon_lg_split_onoff(const cpl_frameset *, cpl_frameset *, cpl_frameset *, const char *, const char *)
Split the input frameset into two sub-framesets (ON and OFF)
static cpl_error_code xsh_detmon_lg_dfs_save_imagelist(cpl_frameset *frameset, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_imagelist *coeffs, const char *recipe_name, const cpl_propertylist *mypro_coeffscube, const char *package, const char *name_o)
int threshold_min
Definition: xsh_detmon_lg.c:83
cpl_image * xsh_detmon_image_correlate(const cpl_image *image1, const cpl_image *image2, const int m, const int n)
static cpl_imagelist * irplib_load_fset_wrp(const cpl_frameset *, cpl_type, int whichext)
static cpl_error_code xsh_detmon_single_extract_next(const cpl_frameset *set, int *index, int *next_element, double *dit_array, cpl_frameset **pair)
#define DETMON_QC_COUNTS_MAX
Definition: xsh_detmon_lg.h:54
#define DETMON_QC_COUNTS_MIN
Definition: xsh_detmon_lg.h:51
#define DETMON_QC_COUNTS_MIN_C
Definition: xsh_detmon_lg.h:52
#define IRPLIB_GAIN_WITH_RESCALE
#define IRPLIB_GAIN_NO_COLLAPSE
#define DETMON_QC_AUTOCORR
Definition: xsh_detmon_lg.h:72
#define DETMON_QC_CONTAM
#define DETMON_QC_GAIN_MSE
Definition: xsh_detmon_lg.h:66
#define DETMON_QC_FPN
#define DETMON_QC_LAMP_FLUX
Definition: xsh_detmon_lg.h:78
#define DETMON_QC_GAIN_MSE_C
Definition: xsh_detmon_lg.h:67
#define DETMON_QC_ERRFIT_C
#define DETMON_QC_CONAD_CORR_C
Definition: xsh_detmon_lg.h:61
#define DETMON_QC_GAIN_C
Definition: xsh_detmon_lg.h:64
#define IRPLIB_LIN_NO_COLLAPSE
#define DETMON_QC_GAIN_CORR
Definition: xsh_detmon_lg.h:75
#define DETMON_QC_CONAD
Definition: xsh_detmon_lg.h:57
#define DETMON_QC_AUTOCORR_C
Definition: xsh_detmon_lg.h:73
#define DETMON_QC_LIN_EFF
Definition: xsh_detmon_lg.h:91
#define IRPLIB_LIN_NIR
#define DETMON_QC_LIN_EFF_FLUX_C
Definition: xsh_detmon_lg.h:95
#define DETMON_QC_ERRFIT_MSE_C
#define DETMON_QC_CONAD_CORR
Definition: xsh_detmon_lg.h:60
#define DETMON_QC_CONAD_C
Definition: xsh_detmon_lg.h:58
#define IRPLIB_GAIN_NIR
#define IRPLIB_GAIN_COLLAPSE
#define IRPLIB_GAIN_OPT
#define DETMON_QC_LIN_EFF_FLUX
Definition: xsh_detmon_lg.h:94
#define IRPLIB_LIN_PIX2PIX
#define DETMON_QC_ERRFIT
#define DETMON_LG_OFF_RAW_OLD
Definition: xsh_detmon_lg.h:43
#define DETMON_QC_LAMP_STAB_C
Definition: xsh_detmon_lg.h:86
#define IRPLIB_GAIN_PTC
#define DETMON_QC_LAMP_FLUX_C
Definition: xsh_detmon_lg.h:79
#define IRPLIB_LIN_OPT
#define DETMON_QC_METHOD_C
Definition: xsh_detmon_lg.h:89
#define DETMON_QC_GAIN_CORR_C
Definition: xsh_detmon_lg.h:76
#define DETMON_QC_LIN_COEF_ERR_C
#define DETMON_QC_LAMP_STAB
Definition: xsh_detmon_lg.h:85
#define IRPLIB_LIN_WITH_RESCALE
#define DETMON_LG_OFF_RAW_NEW
Definition: xsh_detmon_lg.h:45
#define DETMON_QC_LIN_COEF_C
Definition: xsh_detmon_lg.h:98
#define DETMON_QC_CONTAM_C
#define IRPLIB_LIN_COLLAPSE
#define IRPLIB_GAIN_WITH_AUTOCORR
#define DETMON_QC_LIN_EFF_C
Definition: xsh_detmon_lg.h:92
#define DETMON_LG_ON_RAW_NEW
Definition: xsh_detmon_lg.h:44
#define DETMON_LG_ON_RAW_OLD
Definition: xsh_detmon_lg.h:42
#define DETMON_QC_METHOD
Definition: xsh_detmon_lg.h:88
#define DETMON_QC_GAIN
Definition: xsh_detmon_lg.h:63
#define DETMON_QC_NUM_BPM_C
Definition: xsh_detmon_lg.h:82
#define DETMON_QC_NUM_BPM
Definition: xsh_detmon_lg.h:81
#define DETMON_QC_COUNTS_MAX_C
Definition: xsh_detmon_lg.h:55
cpl_image * xsh_detmon_subtracted_avg(const cpl_image *on1, const cpl_image *off1, const cpl_image *on2, const cpl_image *off2, cpl_size llx, cpl_size lly, cpl_size urx, cpl_size ury)
return absolute average of subtracted images
cpl_image * xsh_detmon_subtract_create_window(const cpl_image *a, const cpl_image *b, cpl_size llx, cpl_size lly, cpl_size urx, cpl_size ury)
subtract window two images creating new image of window size
cpl_imagelist * xsh_detmon_load_frameset_window(const cpl_frameset *fset, cpl_type type, cpl_size pnum, cpl_size xtnum, cpl_size llx, cpl_size lly, cpl_size urx, cpl_size ury, cpl_size nx, cpl_size ny)
load data in frameset into an imagelist
#define OPT
Definition: xsh_lingain.c:106
#define NIR
Definition: xsh_lingain.c:105