IIINSTRUMENT Pipeline Reference Manual 1.3.13
detmon/detmon_darkron.c
1/* $Id: detmon.c,v 1.11 2013-07-19 12:00:24 jtaylor Exp $
2 *
3 * This file is part of the irplib package
4 * Copyright (C) 2002, 2003 European Southern Observatory
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * $Author: jtaylor $
23 * $Date: 2013-07-19 12:00:24 $
24 * $Revision: 1.11 $
25 * $Name: not supported by cvs2svn $
26 */
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31
32/*---------------------------------------------------------------------------
33 Includes
34 ---------------------------------------------------------------------------*/
35
36#include "detmon_darkron.h"
37
38#include "detmon_ronbias.h"
39#include "detmon.h"
40
41#include "irplib_ksigma_clip.h"
42#include "irplib_hist.h"
43#include "irplib_utils.h"
44
45#include <math.h>
46#include <string.h>
47#include <assert.h>
48#include <float.h>
49
51/*--------------------------------------------------------------------------*/
52
53/*
54 * @defgroup detmon Detector monitoring functions
55 */
56
57/*--------------------------------------------------------------------------*/
58
59/*---------------------------------------------------------------------------
60 Defines
61 ---------------------------------------------------------------------------*/
62
63/* Computes the square of an euclidean distance bet. 2 points */
64#define pdist(x1,y1,x2,y2) (((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)))
65
66#define cpl_drand() ((double)rand()/(double)RAND_MAX)
67
68enum pixeltypes
69{
70 HOT = 0,
71 DEAD = 1,
72 NOISY = 2
73};
74
75enum stackingtypes
76{
77 MINMAX = 0,
78 MEAN = 1,
79 MEDIAN = 2,
80 KSIGMA = 3
81};
82
83enum readouts
84{
85 HORIZONTAL = 1,
86 VERTICAL = 2
87};
88
89
90
91static struct
92{
93 const char * ron_method;
94 const char * dsnu_method;
95 int exts;
96 int nb_extensions;
97 cpl_boolean opt_nir;
98} detmon_dark_config;
99
100#define NIR TRUE
101#define OPT FALSE
102
103/*---------------------------------------------------------------------------
104 Private function prototypes
105 ---------------------------------------------------------------------------*/
106
107/* The following function is duplicated from cpl_det */
108int
109detmon_dark_dfs_set_groups(cpl_frameset *,
110 const char *);
111
112cpl_error_code
113detmon_dark_dsnu(cpl_frameset *,
114 cpl_imagelist *,
115 cpl_table *,
116 cpl_image *,
117 int pos);
118
119
120static cpl_error_code
121detmon_dark_save(const cpl_parameterlist *,
122 cpl_frameset *,
123 const char *,
124 const char *,
125 const char *,
126 const char *,
127 const char *,
128 const char *,
129 cpl_imagelist **,
130 cpl_table **,
131 cpl_imagelist **,
132 cpl_propertylist **,
133 const int,
134 const int,
135 const cpl_frameset *);
136
137
138
139static cpl_error_code
140detmon_retrieve_dark_params(const char *,
141 const char *,
142 const cpl_parameterlist *);
143
144cpl_error_code
145detmon_dark_qc(cpl_propertylist *,
146 cpl_image *);
147
148
149
150/* RONBIAS FILLING PARLIST */
151
152
153/*---------------------------------------------------------------------------*/
154
155/*
156 * @brief Fill input parameters with default values
157 * @param parlist parameters list
158 * @param recipe_name recipe name
159 * @param pipeline_name pipeline name
160
161 * @return CPL_ERROR_NONE on success.
162 */
163
164/*---------------------------------------------------------------------------*/
165
166 cpl_error_code
167detmon_darkron_fill_parlist_default(cpl_parameterlist * parlist,
168 const char *recipe_name,
169 const char *pipeline_name)
170{
171 const cpl_error_code error =
172 detmon_ronbias_fill_parlist(parlist, recipe_name, pipeline_name,
173 "ALL", /* --method */
174 "NORM",/* --pmethod */
175 1, /* --preoverscan_degree */
176 -1, /* --random_nsamples */
177 -1, /* --random_sizex */
178 -1, /* --random_sizey */
179 0, /* --criteria */
180 -1, /* --ref_llx */
181 -1, /* --ref_lly */
182 -1, /* --ref_urx */
183 -1, /* --ref_ury */
184 "MEAN",/* --stacking_method */
185 3, /* --stacking_ks_low */
186 3, /* --stacking_ks_high */
187 5, /* --stacking_ks_iter */
188 0, /* --master_shift_x */
189 0, /* --master_shift_y */
190 -1, /* --ron_llx */
191 -1, /* --ron_lly */
192 -1, /* --ron_urx */
193 -1, /* --ron_ury */
194 0, /* --exts */
195 NIR);
196 cpl_ensure_code(!error, error);
197
198 return cpl_error_get_code();
199}
200
201
202/*--------------------------------------------------------------------------*/
203
204/*
205 * @brief Comparison function to identify different settings
206 * @param frame1 First frame
207 * @param frame2 Second frame
208 * @return 0 if different, 1 if equal, -1 in error case
209 */
210
211/*--------------------------------------------------------------------------*/
212
213int
214detmon_compare_dits(const cpl_frame * frame1, const cpl_frame * frame2)
215{
216 int comparison;
217 cpl_propertylist *plist1;
218 cpl_propertylist *plist2;
219 double dval1, dval2;
220
221 /* Test entries */
222 if(frame1 == NULL || frame2 == NULL)
223 return -1;
224
225 /* Get property lists */
226 if((plist1 = cpl_propertylist_load(cpl_frame_get_filename(frame1),
227 0)) == NULL) {
228 cpl_msg_error(cpl_func, "getting header from reference frame");
229 return -1;
230 }
231 if((plist2 = cpl_propertylist_load(cpl_frame_get_filename(frame2),
232 0)) == NULL) {
233 cpl_msg_error(cpl_func, "getting header from reference frame");
234 cpl_propertylist_delete(plist1);
235 return -1;
236 }
237
238 /* Test status */
239 if(cpl_error_get_code()) {
240 cpl_propertylist_delete(plist1);
241 cpl_propertylist_delete(plist2);
242 return -1;
243 }
244
245 /* Compare exposure time */
246 comparison = 1;
247 dval1 = irplib_pfits_get_exptime(plist1);
248 dval2 = irplib_pfits_get_exptime(plist2);
249 if(cpl_error_get_code()) {
250 cpl_msg_error(cpl_func, "cannot get exposure time");
251 cpl_propertylist_delete(plist1);
252 cpl_propertylist_delete(plist2);
253 return -1;
254 }
255 if(fabs(dval1 - dval2) > 1e-3)
256 comparison = 0;
257
258 /* Free and return */
259 cpl_propertylist_delete(plist1);
260 cpl_propertylist_delete(plist2);
261 return comparison;
262}
263
264/* End of duplicated code */
265
266
267/*---------------------------------------------------------------------------*/
268/*
269 * @brief dark recipe
270 * @param frameset input frameset
271 * @param parlist input parameter list
272 * @param tag input recipe frame tag
273 * @param recipe_name input recipe name
274 * @param pipeline_name input pipeline name
275 * @param procatg_master input procatg of master product
276 * @param procatg_dsnu input procatg dsnu product
277 * @param procatg_tbl input procatg table
278 * @param package input package name
279 * @param compare function to make comparisons
280 * @return CPL_ERROR_NONE on success.
281 */
282/*---------------------------------------------------------------------------*/
283
284
285cpl_error_code
286detmon_dark(cpl_frameset * frameset,
287 const cpl_parameterlist * parlist,
288 const char * tag,
289 const char * recipe_name,
290 const char * pipeline_name,
291 const char * procatg_master,
292 const char * procatg_dsnu,
293 const char * procatg_tbl,
294 const char * package,
295 int (*compare)(const cpl_frame *,
296 const cpl_frame *))
297{
298 cpl_size nsets;
299 cpl_size *selection = NULL;
300 int i;
301 cpl_error_code error;
302
303 if(detmon_dark_dfs_set_groups(frameset, tag)) {
304 cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames");
305 }
306
307 /*
308 * This function reads all inputs parameters from parlist
309 * and stores them in a global variable detmon_ronbias_config.
310 * Similar to detmon_lg_retrieve_parlist(). See detmon.c
311 */
312 error = detmon_retrieve_dark_params(pipeline_name,
313 recipe_name, parlist);
314 cpl_ensure_code(!error, error);
315
316 /* Labelise all input frames */
317 if(compare == NULL)
318 nsets = 1;
319 else {
320 cpl_msg_info(cpl_func, "Identify the different settings");
321 selection = cpl_frameset_labelise(frameset, compare, &nsets);
322 if(selection == NULL)
323 cpl_msg_error(cpl_func, "Cannot labelise input frames");
324 }
325
326 detmon_dark_config.nb_extensions = 1;
327 if(detmon_dark_config.exts < 0) {
328 const cpl_frame *cur_frame =
329 cpl_frameset_get_position_const(frameset, 0);
330 /* Get the nb of extensions */
331 detmon_dark_config.nb_extensions =
332 cpl_frame_get_nextensions(cur_frame);
333 }
334
335 /* Extract settings and reduce each of them */
336 for(i = 0; i < nsets; i++) {
337 cpl_size *select_dits = NULL;
338 cpl_frameset *cur_fset =
339 nsets == 1 ? cpl_frameset_duplicate(frameset) :
340 cpl_frameset_extract(frameset, selection, i);
341
342 cpl_size ndits = 0;
343 int j, k;
344 cpl_table ** dsnu_table = NULL;
345 cpl_imagelist ** dsnu = NULL;
346
347 cpl_propertylist ** qclist =
348 (cpl_propertylist **)
349 cpl_malloc(detmon_dark_config.nb_extensions *
350 sizeof(cpl_propertylist *));
351
352
353 cpl_imagelist ** masters =
354 (cpl_imagelist **)
355 cpl_malloc(detmon_dark_config.nb_extensions *
356 sizeof(cpl_imagelist *));
357
358 /* Initialise memory for products */
359 if(detmon_dark_config.opt_nir == OPT) {
360 dsnu_table =
361 (cpl_table **) cpl_malloc(detmon_dark_config.nb_extensions *
362 sizeof(cpl_table *));
363 dsnu =
364 (cpl_imagelist **)
365 cpl_malloc(detmon_dark_config.nb_extensions *
366 sizeof(cpl_imagelist *));
367 }
368
369 select_dits = cpl_frameset_labelise(cur_fset,
370 detmon_compare_dits,
371 &ndits);
372
373 if(detmon_dark_config.exts >= 0) {
374 *masters = cpl_imagelist_new();
375 if(detmon_dark_config.opt_nir == OPT) {
376 *dsnu = cpl_imagelist_new();
377 *dsnu_table = cpl_table_new(ndits);
378 }
379 *qclist = cpl_propertylist_new();
380 cpl_table_new_column(*dsnu_table, "DIT", CPL_TYPE_DOUBLE);
381 cpl_table_new_column(*dsnu_table, "STDEV", CPL_TYPE_DOUBLE);
382 } else {
383 for ( j = 0; j < detmon_dark_config.nb_extensions; j ++) {
384 masters[j] = cpl_imagelist_new();
385 if(detmon_dark_config.opt_nir == OPT) {
386 dsnu[j] = cpl_imagelist_new();
387 dsnu_table[j] = cpl_table_new(ndits);
388 }
389 qclist[j] = cpl_propertylist_new();
390 cpl_table_new_column(dsnu_table[j], "DIT", CPL_TYPE_DOUBLE);
391 cpl_table_new_column(dsnu_table[j], "STDEV", CPL_TYPE_DOUBLE);
392 }
393 }
394
395 for(j = 0; j < ndits; j++) {
396 cpl_frameset * cur_fdit = cpl_frameset_extract(cur_fset,
397 select_dits, j);
398 cpl_imagelist ** raws =
399 (cpl_imagelist **)
400 cpl_malloc(detmon_dark_config.nb_extensions *
401 sizeof(cpl_imagelist *));
402
403 if(detmon_dark_config.exts >= 0) {
404 cpl_image * collapsed;
405 *raws =
406 cpl_imagelist_load_frameset(cur_fdit, CPL_TYPE_FLOAT, 1,
407 detmon_dark_config.exts);
408 collapsed = cpl_imagelist_collapse_create(*raws);
409 cpl_imagelist_set(*masters, collapsed, j);
410 if(detmon_dark_config.opt_nir == OPT) {
411 detmon_dark_dsnu(cur_fdit, *dsnu, *dsnu_table,
412 collapsed, j);
413 }
414 detmon_dark_qc(*qclist, collapsed);
415 } else {
416 cpl_imagelist *raws_all_exts =
417 cpl_imagelist_load_frameset(cur_fdit, CPL_TYPE_FLOAT, 1,
418 -1);
419 for(k = 0; k < detmon_dark_config.nb_extensions; k++) {
420 int nframes = cpl_frameset_get_size(cur_fdit);
421 int h;
422 cpl_image * collapsed;
423 for(h = 0; h < nframes; h++) {
424 cpl_image *image =
425 cpl_imagelist_unset(raws_all_exts,
426 (detmon_dark_config.
427 nb_extensions - 1 - k) * h);
428 cpl_imagelist_set(raws[k], image, h);
429 }
430 collapsed = cpl_imagelist_collapse_create(raws[k]);
431 cpl_imagelist_set(masters[k],collapsed, j);
432 if(detmon_dark_config.opt_nir == OPT) {
433 detmon_dark_dsnu(cur_fdit, dsnu[k],
434 dsnu_table[j], collapsed, j);
435 }
436 detmon_dark_qc(qclist[k], collapsed);
437 }
438 }
439
440 cpl_frameset_delete(cur_fdit);
441 for(k = 0; k < detmon_dark_config.nb_extensions; k++) {
442 cpl_imagelist_delete(raws[k]);
443 }
444 cpl_free(raws);
445 } /* end of loop (for) around different DIT values */
446
447 cpl_frameset_delete(cur_fset);
448
449 detmon_dark_save(parlist, frameset, recipe_name, pipeline_name,
450 procatg_master, procatg_tbl, procatg_dsnu,
451 package, masters, dsnu_table, dsnu, qclist,
452 0, 0, frameset);
453
454 if(detmon_dark_config.opt_nir == OPT) {
455 for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
456 cpl_table_delete(dsnu_table[j]);
457 cpl_imagelist_delete(dsnu[j]);
458 }
459 cpl_free(dsnu_table);
460 cpl_free(dsnu);
461 }
462
463 for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
464 cpl_propertylist_delete(qclist[j]);
465 cpl_imagelist_delete(masters[j]);
466 }
467 cpl_free(qclist);
468 cpl_free(masters);
469 cpl_free(select_dits);
470
471 } /* end of loop (for) around different setting */
472
473 cpl_free(selection);
474
475 return cpl_error_get_code();
476}
477
478
479/*---------------------------------------------------------------------------*/
480
481/*
482 * @brief Classifies input frames
483 * @param set Input frameset
484 * @param tag Input frame tag
485
486 * @return 0 on success, else -1
487 */
488
489/*---------------------------------------------------------------------------*/
490int
491detmon_dark_dfs_set_groups(cpl_frameset * set, const char *tag)
492{
493
494
495
496 /* Check entries */
497 if(set == NULL)
498 return -1;
499
500 /* Initialize */
501 int nframes = cpl_frameset_get_size(set);
502
503 /* Loop on frames */
504 for(int i = 0; i < nframes; i++) {
505 cpl_frame* cur_frame = cpl_frameset_get_position(set, i);
506 const char* cur_tag = cpl_frame_get_tag(cur_frame);
507
508 /* RAW frames */
509 if(!strcmp(cur_tag, tag))
510 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
511 /* CALIB frames */
512
513 /* else if (!strcmp(tag, IIINSTRUMENT_CALIB_FLAT))
514 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_CALIB) ;
515 */
516 }
517 return 0;
518}
519
520/*---------------------------------------------------------------------------*/
521
522/*
523 * @brief Retrieve input parameters
524 * @param pipeline_name Input pipeline name
525 * @param recipe_name Input recipe name
526 * @param parlist Input parameter list
527 * @return CPL_ERROR_NONE on success.
528 */
529
530/*---------------------------------------------------------------------------*/
531static cpl_error_code
532detmon_retrieve_dark_params(const char *pipeline_name,
533 const char *recipe_name,
534 const cpl_parameterlist * parlist)
535{
536 char *par_name;
537 const cpl_parameter *par;
538
539 /* --ron.method */
540 par_name = cpl_sprintf("%s.%s.ron.method", pipeline_name, recipe_name);
541 assert(par_name != NULL);
542 par = cpl_parameterlist_find_const(parlist, par_name);
543 detmon_dark_config.ron_method = cpl_parameter_get_string(par);
544 cpl_free(par_name);
545
546 /* --dsnu.method */
547 par_name = cpl_sprintf("%s.%s.dsnu.method", pipeline_name, recipe_name);
548 assert(par_name != NULL);
549 par = cpl_parameterlist_find_const(parlist, par_name);
550 detmon_dark_config.dsnu_method = cpl_parameter_get_string(par);
551 cpl_free(par_name);
552
553 /* --opt_nir */
554 par_name = cpl_sprintf("%s.%s.opt_nir", pipeline_name, recipe_name);
555 assert(par_name != NULL);
556 par = cpl_parameterlist_find_const(parlist, par_name);
557 detmon_dark_config.opt_nir = cpl_parameter_get_bool(par);
558 cpl_free(par_name);
559
560 /* --exts */
561 detmon_dark_config.exts =
562 detmon_retrieve_par_int("exts", pipeline_name, recipe_name,
563 parlist);
564
565 if(cpl_error_get_code()) {
566 cpl_msg_error(cpl_func, "Failed to retrieve the input parameters");
567 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
568 }
569
570
571 return CPL_ERROR_NONE;
572}
573
574
575/*---------------------------------------------------------------------------*/
576/*
577 * @brief Fill dark param structure with default values
578 * @param parlist input parameter list
579 * @param recipe_name recipe name
580 * @param pipeline_name pipeline name
581 * @param ron_method method to compute RON
582 * @param dsnu_metthod method to compute DSNU
583 * @param opt_nir opt/nir swich parameter
584 * @param exts extensions
585 *
586 * @return CPL_ERROR_NONE on success.
587 */
588/*---------------------------------------------------------------------------*/
589 cpl_error_code
590detmon_fill_dark_params(cpl_parameterlist * parlist,
591 const char *recipe_name,
592 const char *pipeline_name,
593 const char * ron_method,
594 const char * dsnu_method,
595 const char * opt_nir,
596 int exts)
597{
598 detmon_fill_parlist(parlist, recipe_name, pipeline_name, 4,
599
600 "ron.method",
601 "Method used to compute RON. Currently no "
602 "change is possible, RMS computed",
603 "CPL_TYPE_STRING", ron_method,
604
605 "dsnu.method",
606 "Method used to compute DSNU map. Currently no "
607 "change is possible. Method used STDEV",
608 "CPL_TYPE_STRING", dsnu_method,
609
610 "opt_nir",
611 "Boolean, OPT (FALSE) or NIR(TRUE)",
612 "CPL_TYPE_BOOL", opt_nir,
613
614 "exts",
615 "Activate the multi-exts option. Default 0"
616 "(primary unit), -1 (all exts)",
617 "CPL_TYPE_INT", exts);
618
619 return cpl_error_get_code();
620}
621
622/*---------------------------------------------------------------------------*/
623/*
624 * @brief Fill dark param structure with default values
625 * @param parlist input parameter list
626 * @param recipe_name recipe name
627 * @param pipeline_name pipeline name
628 *
629 * @return CPL_ERROR_NONE on success.
630 */
631/*---------------------------------------------------------------------------*/
632int
633detmon_fill_dark_params_default(cpl_parameterlist * parlist,
634 const char *recipe_name,
635 const char *pipeline_name)
636{
637 detmon_fill_dark_params(parlist, recipe_name, pipeline_name,
638 "SIMPLE", /* --ron.method */
639 "STDEV", /* --dsnu.method */
640 "CPL_FALSE", /* OPT*/
641 0); /* --exts */
642 return cpl_error_get_code();
643}
644
645/*---------------------------------------------------------------------------*/
646
647/*
648 * @brief Computes DSNU
649 * @param cur_fdit Input frameset
650 * @param dsnu Input imagelist
651 * @param dsnu_table input dsnu table
652 * @param collapsed input collapsed image
653 * @param pos frame position in table
654 * @return CPL_ERROR_NONE on success.
655 */
656
657/*---------------------------------------------------------------------------*/
658cpl_error_code
659detmon_dark_dsnu(cpl_frameset * cur_fdit,
660 cpl_imagelist * dsnu,
661 cpl_table * dsnu_table,
662 cpl_image * collapsed,
663 int pos)
664{
665 cpl_frame * first = cpl_frameset_get_position(cur_fdit, 0);
666 cpl_propertylist * plist =
667 cpl_propertylist_load(cpl_frame_get_filename(first), 0);
668 double dit = irplib_pfits_get_exptime(plist);
669 double mean = cpl_image_get_mean(collapsed);
670
671 cpl_image * dsnu_map =
672 cpl_image_subtract_scalar_create(collapsed, mean);
673 double stdev;
674 cpl_image_divide_scalar(dsnu_map, mean);
675 stdev = cpl_image_get_stdev(dsnu_map);
676
677 cpl_imagelist_set(dsnu, dsnu_map, pos);
678
679 cpl_table_set(dsnu_table, "DIT", pos, dit);
680 cpl_table_set(dsnu_table, "STDEV", pos, stdev);
681
682 cpl_propertylist_delete(plist);
683
684 return cpl_error_get_code();
685
686}
687
688/*---------------------------------------------------------------------------*/
689
690/*
691 * @brief Save dark recipe products
692 * @param parlist input parameter list
693 * @param frameset input frameset
694 * @param recipe_name input recipe name
695 * @param pipeline_name input pipeline name
696 * @param procatg_master input procatg of master product
697 * @param procatg_tbl input procatg table
698 * @param procatg_dsnu input procatg dsnu product
699 * @param package input package name
700 * @param masters list of masters products
701 * @param dsnu_table dsnu table product
702 * @param dsnu list of dsnu images products
703 * @param qclist qc parameters
704 * @param flag_sets switch
705 * @param which_set specifier
706 * @param usedframes used frames
707 * @return CPL_ERROR_NONE on success.
708 */
709
710/*---------------------------------------------------------------------------*/
711static cpl_error_code
712detmon_dark_save(const cpl_parameterlist * parlist,
713 cpl_frameset * frameset,
714 const char *recipe_name,
715 const char *pipeline_name,
716 const char *procatg_master,
717 const char *procatg_tbl,
718 const char *procatg_dsnu,
719 const char *package,
720 cpl_imagelist ** masters,
721 cpl_table ** dsnu_table,
722 cpl_imagelist ** dsnu,
723 cpl_propertylist ** qclist,
724 const int flag_sets,
725 const int which_set,
726 const cpl_frameset * usedframes)
727{
728
729 cpl_frame *ref_frame;
730 cpl_propertylist *plist;
731 char *name_o = NULL; /* Avoid (false) uninit warning */
732 int i, j;
733 cpl_propertylist *paflist;
734 cpl_error_code error;
735 int nb_images;
736
737 /***************************/
738 /* Write the MASTER FITS */
739 /***************************/
740
741 nb_images = cpl_imagelist_get_size(masters[0]);
742 cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
743
744
745 for(i = 0; i < nb_images; i++) {
746 /* Set the file name for each image */
747 if(!flag_sets) {
748 name_o =
749 cpl_sprintf("%s_master_dit_%d.fits", recipe_name, i+1);
750 assert(name_o != NULL);
751 } else {
752 name_o =
753 cpl_sprintf("%s_master_dit_%d_set%02d.fits",
754 recipe_name, i, which_set);
755 assert(name_o != NULL);
756 }
757
758
759 /* Save the image */
760 if(detmon_dark_config.exts >= 0) {
761 cpl_propertylist * pro_master = cpl_propertylist_new();
762
763 cpl_propertylist_append_string(pro_master,
764 CPL_DFS_PRO_CATG, procatg_master);
765
766 cpl_propertylist_append(pro_master, qclist[0]);
767
768 if(cpl_dfs_save_image
769 (frameset, NULL, parlist, usedframes, NULL,
770 cpl_imagelist_get(*masters, i), CPL_BPP_IEEE_FLOAT,
771 recipe_name, pro_master, NULL, package,
772 name_o)) {
773 cpl_msg_error(cpl_func, "Cannot save the product: %s",
774 name_o);
775 cpl_free(name_o);
776 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
777
778 }
779
780 cpl_propertylist_delete(pro_master);
781 } else {
782 cpl_propertylist * pro_master = cpl_propertylist_new();
783
784 cpl_propertylist_append_string(pro_master,
785 CPL_DFS_PRO_CATG, procatg_master);
786
787 cpl_propertylist_append(pro_master, qclist[0]);
788
789 if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
790 NULL, CPL_BPP_IEEE_FLOAT, recipe_name,
791 pro_master, NULL,
792 package, name_o)) {
793 cpl_msg_error(cpl_func, "Cannot save the product: %s",
794 name_o);
795 cpl_free(name_o);
796 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
797 }
798
799 cpl_propertylist_delete(pro_master);
800 for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
801 error =
802 cpl_image_save(cpl_imagelist_get(masters[j], i),
803 name_o, CPL_BPP_IEEE_FLOAT, qclist[j],
804 CPL_IO_EXTEND);
805 cpl_ensure_code(!error, error);
806 }
807 }
808 cpl_free(name_o);
809 }
810
811 if (detmon_dark_config.opt_nir == OPT) {
812 cpl_propertylist * pro_tbl = cpl_propertylist_new();
813
814 cpl_propertylist_append_string(pro_tbl,
815 CPL_DFS_PRO_CATG, procatg_tbl);
816
817 cpl_propertylist_append(pro_tbl, qclist[0]);
818 /*******************************/
819 /* Write the LINEARITY TABLE */
820 /*******************************/
821
822 /* Set the file name for the table */
823 if(!flag_sets) {
824 name_o = cpl_sprintf("%s_dsnu_table.fits", recipe_name);
825 assert(name_o != NULL);
826 } else {
827 name_o =
828 cpl_sprintf("%s_dsnu_table_set%02d.fits", recipe_name,
829 which_set);
830 assert(name_o != NULL);
831 }
832 /* Save the table */
833 if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
834 dsnu_table[0], NULL, recipe_name, pro_tbl, NULL,
835 package, name_o)) {
836 cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
837 cpl_free(name_o);
838 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
839 }
840
841 cpl_propertylist_delete(pro_tbl);
842
843 if(detmon_dark_config.exts < 0) {
844
845 for(i = 1; i < detmon_dark_config.nb_extensions; i++) {
846 error =
847 cpl_table_save(dsnu_table[i], NULL, qclist[i], name_o,
848 CPL_IO_EXTEND);
849 cpl_ensure_code(!error, error);
850 }
851 }
852
853 /* Free */
854 cpl_free(name_o);
855
856 /***************************/
857 /* Write the DSNU_MAP FITS */
858 /***************************/
859
860 for(i = 0; i < nb_images; i++) {
861 /* Set the file name for each image */
862 if(!flag_sets) {
863 name_o =
864 cpl_sprintf("%s_dsnu_map_dit_%d.fits", recipe_name, i+1);
865 assert(name_o != NULL);
866 } else {
867 name_o =
868 cpl_sprintf("%s_dsnu_map_dit_%d_set%02d.fits",
869 recipe_name, i, which_set);
870 assert(name_o != NULL);
871 }
872
873
874 /* Save the image */
875 if(detmon_dark_config.exts >= 0) {
876 cpl_propertylist * pro_dsnu = cpl_propertylist_new();
877
878 cpl_propertylist_append_string(pro_dsnu,
879 CPL_DFS_PRO_CATG, procatg_dsnu);
880
881 cpl_propertylist_append(pro_dsnu, qclist[0]);
882
883 if(cpl_dfs_save_image
884 (frameset, NULL, parlist, usedframes, NULL,
885 cpl_imagelist_get(*dsnu, i), CPL_BPP_IEEE_FLOAT,
886 recipe_name, pro_dsnu, NULL, package,
887 name_o)) {
888 cpl_msg_error(cpl_func, "Cannot save the product: %s",
889 name_o);
890 cpl_free(name_o);
891 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
892
893 }
894
895 cpl_propertylist_delete(pro_dsnu);
896 } else {
897 cpl_propertylist * pro_dsnu = cpl_propertylist_new();
898
899 cpl_propertylist_append_string(pro_dsnu,
900 CPL_DFS_PRO_CATG, procatg_dsnu);
901
902 cpl_propertylist_append(pro_dsnu, qclist[0]);
903
904 if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
905 NULL, NULL,
906 CPL_BPP_IEEE_FLOAT, recipe_name,
907 pro_dsnu, NULL,
908 package, name_o)) {
909 cpl_msg_error(cpl_func, "Cannot save the product: %s",
910 name_o);
911 cpl_free(name_o);
912 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
913 }
914
915 cpl_propertylist_delete(pro_dsnu);
916 for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
917 error =
918 cpl_image_save(cpl_imagelist_get(dsnu[j], i),
919 name_o, CPL_BPP_IEEE_FLOAT, qclist[j],
920 CPL_IO_EXTEND);
921 cpl_ensure_code(!error, error);
922 }
923 }
924 cpl_free(name_o);
925 }
926
927
928
929 } /* End of if(OPT) */
930
931 /*******************************/
932 /* Write the PAF file(s) */
933 /*******************************/
934
935 /* Get FITS header from reference file */
936 ref_frame = cpl_frameset_get_position(frameset, 0);
937 if((plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
938 0)) == NULL) {
939 cpl_msg_error(cpl_func, "getting header from reference frame");
940 cpl_ensure_code(0, cpl_error_get_code());
941 }
942
943 /* Get the keywords for the paf file */
944 paflist = cpl_propertylist_new();
945 cpl_propertylist_copy_property_regexp(paflist, plist,
946 "^(ARCFILE|MJD-OBS|ESO TPL ID|"
947 "DATE-OBS|ESO DET DIT|ESO DET NDIT|"
948 "ESO DET NCORRS|"
949 "ESO DET MODE NAME)$", 0);
950
951 for(i = 0; i < detmon_dark_config.nb_extensions; i++) {
952 cpl_propertylist * c_paflist = cpl_propertylist_duplicate(paflist);
953 error = cpl_propertylist_append(c_paflist, qclist[i]);
954 cpl_ensure_code(!error, error);
955
956 /* Set the file name for the bpm */
957 if(detmon_dark_config.exts >= 0) {
958 if(!flag_sets) {
959 name_o = cpl_sprintf("%s.paf", recipe_name);
960 assert(name_o != NULL);
961 } else {
962 name_o = cpl_sprintf("%s_set%02d.paf", recipe_name, which_set);
963 assert(name_o != NULL);
964 }
965 } else {
966 if(!flag_sets) {
967 name_o = cpl_sprintf("%s_ext%02d.paf", recipe_name, i+1);
968 assert(name_o != NULL);
969 } else {
970 name_o = cpl_sprintf("%s_set%02d_ext%02d.paf", recipe_name, which_set, i+1);
971 assert(name_o != NULL);
972 }
973 }
974 /* Save the PAF */
975 if(cpl_dfs_save_paf(pipeline_name, recipe_name, c_paflist, name_o)) {
976 cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
977 cpl_free(name_o);
978 cpl_propertylist_delete(paflist);
979 cpl_propertylist_delete(plist);
980 cpl_free(name_o);
981 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
982 }
983 cpl_propertylist_delete(c_paflist);
984 cpl_free(name_o);
985 }
986
987 cpl_propertylist_delete(plist);
988 cpl_propertylist_delete(paflist);
989
990 return cpl_error_get_code();
991}
992/*---------------------------------------------------------------------------*/
999/*---------------------------------------------------------------------------*/
1000cpl_error_code
1001detmon_dark_qc(cpl_propertylist * qclist,
1002 cpl_image * collapsed)
1003{
1004 double mean = cpl_image_get_mean(collapsed);
1005 double stdev = cpl_image_get_stdev(collapsed);
1006
1007
1008 cpl_propertylist_append_double(qclist,DETMON_QC_DARK, mean);
1009 cpl_propertylist_set_comment(qclist,DETMON_QC_DARK,
1010 DETMON_QC_DARK_C);
1011
1012 cpl_propertylist_append_double(qclist,DETMON_QC_DARK_STDEV, stdev);
1013 cpl_propertylist_set_comment(qclist,DETMON_QC_DARK_STDEV,
1014 DETMON_QC_DARK_STDEV_C);
1015 detmon_print_rec_status();
1016
1017 return cpl_error_get_code();
1018}
1019
1020