IIINSTRUMENT Pipeline Reference Manual 4.4.3
visir_img_dark.c
1/* $Id: visir_img_dark.c,v 1.28 2011-12-21 14:42:52 llundin Exp $
2 *
3 * This file is part of the VISIR Pipeline
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: llundin $
23 * $Date: 2011-12-21 14:42:52 $
24 * $Revision: 1.28 $
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 "visir_recipe.h"
37
38/*-----------------------------------------------------------------------------
39 Defines
40 -----------------------------------------------------------------------------*/
41
42#define RECIPE_STRING "visir_img_dark"
43
44
45/*-----------------------------------------------------------------------------
46 Private Functions prototypes
47 -----------------------------------------------------------------------------*/
48
49static cpl_error_code visir_img_dark_reduce(cpl_propertylist *,
50 const irplib_framelist *,
51 cpl_image **, cpl_mask **,
52 cpl_mask **, cpl_mask **);
53
54static cpl_error_code visir_img_dark_save(cpl_frameset *,
55 const cpl_parameterlist *,
56 const cpl_propertylist *,
57 const cpl_image *, const cpl_mask *,
58 const cpl_mask *, const cpl_mask *,
59 int, const irplib_framelist *);
60
61static char * visir_img_dark_make_tag(const cpl_frame*,
62 const cpl_propertylist *, int);
63
64VISIR_RECIPE_DEFINE(visir_img_dark,
65 VISIR_PARAM_REJBORD |
66 VISIR_PARAM_HOT_LIM |
67 VISIR_PARAM_COLD_LIM |
68 VISIR_PARAM_DEV_LIM |
69 VISIR_PARAM_NSAMPLES |
70 VISIR_PARAM_HALFSIZE,
71 "Dark recipe",
72 "This recipe computes the dark.\n"
73 "The files listed in the Set Of Frames (sof-file) must be "
74 "tagged either\n"
75 "VISIR-dark-image-raw-file.fits " VISIR_IMG_DARK_RAW " or\n"
76 "VISIR-dark-spectro-raw-file.fits " VISIR_SPC_DARK_RAW "\n"
77 "\n"
78 "The corresponding four products will each have a FITS "
79 "card\n'HIERARCH ESO PRO CATG' with values (for imaging)\n"
80 VISIR_IMG_DARK_AVG_PROCATG "\n"
81 VISIR_IMG_DARK_HOT_PROCATG "\n"
82 VISIR_IMG_DARK_COLD_PROCATG "\n"
83 VISIR_IMG_DARK_DEV_PROCATG "\n"
84 " or (for spectroscopy)\n"
85 VISIR_SPC_DARK_AVG_PROCATG "\n"
86 VISIR_SPC_DARK_HOT_PROCATG "\n"
87 VISIR_SPC_DARK_COLD_PROCATG "\n"
88 VISIR_SPC_DARK_DEV_PROCATG "\n");
89
90/*-----------------------------------------------------------------------------
91 Static variables
92 -----------------------------------------------------------------------------*/
93
94enum _visir_dark_mode_ {
95 visir_dark_none = 0,
96 visir_dark_img,
97 visir_dark_spc
98};
99
100typedef enum _visir_dark_mode_ visir_dark_mode;
101
102static struct {
103 /* Inputs */
104 visir_dark_mode mode;
105 int rej_left;
106 int rej_right;
107 int rej_bottom;
108 int rej_top;
109 double hot_thresh;
110 double cold_thresh;
111 double dev_thresh;
112 int hsize;
113 int nsamples;
114} visir_img_dark_config;
115
116/*----------------------------------------------------------------------------*/
120/*----------------------------------------------------------------------------*/
121
122/*-----------------------------------------------------------------------------
123 Functions code
124 -----------------------------------------------------------------------------*/
125
126
127/*----------------------------------------------------------------------------*/
134/*----------------------------------------------------------------------------*/
135static int visir_img_dark(cpl_frameset * framelist,
136 const cpl_parameterlist * parlist)
137{
138 irplib_framelist* allframes = NULL;
139 irplib_framelist* rawframes = NULL;
140 const char ** taglist = NULL;
141 const char * rej_bord;
142 const char * orgtag = NULL; /* Avoid (false) uninit warning */
143 irplib_framelist* f_one = NULL;
144 cpl_imagelist * i_one = NULL;
145 cpl_image * avg = NULL;
146 cpl_mask * hot = NULL;
147 cpl_mask * cold = NULL;
148 cpl_mask * dev = NULL;
149 cpl_propertylist * qclist = cpl_propertylist_new();
150 int nsets;
151 int i;
152 int nb_good = 0;
153
154
155 /* Retrieve input parameters */
156 rej_bord = visir_parameterlist_get_string(parlist, RECIPE_STRING,
157 VISIR_PARAM_REJBORD);
158 skip_if (0);
159 skip_if (sscanf(rej_bord, "%d %d %d %d",
160 &visir_img_dark_config.rej_left,
161 &visir_img_dark_config.rej_right,
162 &visir_img_dark_config.rej_bottom,
163 &visir_img_dark_config.rej_top) != 4);
164
165 visir_img_dark_config.hot_thresh =
166 visir_parameterlist_get_double(parlist, RECIPE_STRING,
167 VISIR_PARAM_HOT_LIM);
168 visir_img_dark_config.dev_thresh =
169 visir_parameterlist_get_double(parlist, RECIPE_STRING,
170 VISIR_PARAM_DEV_LIM);
171 visir_img_dark_config.cold_thresh =
172 visir_parameterlist_get_double(parlist, RECIPE_STRING,
173 VISIR_PARAM_COLD_LIM);
174 visir_img_dark_config.hsize =
175 visir_parameterlist_get_int(parlist, RECIPE_STRING, VISIR_PARAM_HALFSIZE);
176 visir_img_dark_config.nsamples =
177 visir_parameterlist_get_int(parlist, RECIPE_STRING, VISIR_PARAM_NSAMPLES);
178
179 skip_if (0);
180
181 /* Identify the RAW and CALIB frames in the input frameset */
182 skip_if (visir_dfs_set_groups(framelist));
183
184 allframes = irplib_framelist_cast(framelist);
185 skip_if(allframes == NULL);
186
187 rawframes = irplib_framelist_extract_regexp(allframes,
188 "^(" VISIR_IMG_DARK_RAW
189 "|" VISIR_SPC_DARK_RAW ")$",
190 CPL_FALSE);
191 skip_if(rawframes == NULL);
192
193 /* Verify uniqueness of frame type */
194 visir_img_dark_config.mode = visir_dark_none;
195 if (cpl_frameset_find(framelist, VISIR_IMG_DARK_RAW)) {
196 visir_img_dark_config.mode = visir_dark_img;
197 orgtag = VISIR_IMG_DARK_RAW;
198 }
199 if (cpl_frameset_find(framelist, VISIR_SPC_DARK_RAW)) {
200 skip_if (visir_img_dark_config.mode);
201 visir_img_dark_config.mode = visir_dark_spc;
202 orgtag = VISIR_SPC_DARK_RAW;
203 }
204
205 bug_if(visir_img_dark_config.mode == visir_dark_none);
206
207 skip_if(irplib_framelist_load_propertylist_all(rawframes, 0, "^("
208 VISIR_PFITS_REGEXP_DARK "|"
209 VISIR_PFITS_REGEXP_DARK_PAF
210 ")$", CPL_FALSE));
211
212 skip_if(visir_dfs_check_framelist_tag(rawframes));
213
214 taglist = visir_framelist_set_tag(rawframes, visir_img_dark_make_tag, &nsets);
215 skip_if(taglist == NULL);
216
217 cpl_msg_info(cpl_func, "Identified %d setting(s) in %d frames",
218 nsets, irplib_framelist_get_size(rawframes));
219
220 /* Extract settings and reduce each of them */
221 for (i=0 ; i < nsets ; i++) {
222
223 /* Reduce data set nb i */
224 f_one = irplib_framelist_extract(rawframes, taglist[i]);
225
226 /* Reset the tag */
227 skip_if(irplib_framelist_set_tag_all(f_one, orgtag));
228
229 cpl_msg_info(cpl_func, "Reducing frame set %d of %d (size=%d) with "
230 "setting: %s", i+1, nsets,
231 irplib_framelist_get_size(f_one), taglist[i]);
232
233 skip_if (f_one == NULL);
234
235 /* At least 2 frames required */
236 if (irplib_framelist_get_size(f_one) < 2) {
237 cpl_msg_warning(cpl_func, "Setting %d skipped (Need at least 2 "
238 "frames)", i+1);
239 irplib_framelist_delete(f_one);
240 f_one = NULL;
241 continue;
242 }
243
244 skip_if(visir_img_dark_reduce(qclist, f_one, &avg, &hot, &cold, &dev));
245
246 /* Save the products */
247 skip_if (visir_img_dark_save(framelist, parlist, qclist, avg, hot,
248 cold, dev, i+1, f_one));
249
250 nb_good++;
251
252 cpl_image_delete(avg);
253 cpl_mask_delete(hot);
254 cpl_mask_delete(cold);
255 cpl_mask_delete(dev);
256 irplib_framelist_delete(f_one);
257 cpl_propertylist_empty(qclist);
258 avg = NULL;
259 cold = NULL;
260 hot = NULL;
261 dev = NULL;
262 f_one = NULL;
263 }
264
265 skip_if (nb_good == 0);
266
267 end_skip;
268
269 cpl_imagelist_delete(i_one);
270 cpl_free(taglist);
271 cpl_image_delete(avg);
272 cpl_mask_delete(hot);
273 cpl_mask_delete(cold);
274 cpl_mask_delete(dev);
275 irplib_framelist_delete(f_one);
276 irplib_framelist_delete(allframes);
277 irplib_framelist_delete(rawframes);
278 cpl_propertylist_delete(qclist);
279
280 return cpl_error_get_code();
281}
282
283/*----------------------------------------------------------------------------*/
296/*----------------------------------------------------------------------------*/
297static cpl_error_code visir_img_dark_reduce(cpl_propertylist * qclist,
298 const irplib_framelist * f_one,
299 cpl_image ** pavg, cpl_mask ** phot,
300 cpl_mask ** pcold, cpl_mask ** pdev)
301{
302
303 cpl_image * dark = NULL;
304 cpl_image * diff = NULL;
305 char * ron_key = NULL;
306 double rms;
307 double lower, upper;
308 double dark_med;
309 double mean;
310 int ndevpix;
311 cpl_size zone[4];
312 int coldpix_nb;
313 int hotpix_nb;
314 int nfiles;
315 int i;
316
317 skip_if (f_one == NULL);
318
319 nfiles = irplib_framelist_get_size(f_one);
320
321 skip_if (nfiles < 2);
322
323 for (i=0 ; i < nfiles ; i++) {
324 const cpl_frame * frame = irplib_framelist_get_const(f_one, i);
325 const char * name = cpl_frame_get_filename(frame);
326 cpl_size next = cpl_frame_get_nextensions(frame);
327
328 cpl_image_delete(diff);
329 diff = dark;
330 irplib_check(dark = cpl_image_load(name, CPL_TYPE_FLOAT, 0, next),
331 "Could not load FITS-image from %s", name);
332
333 if (i == 0) {
334 const int nx = cpl_image_get_size_x(dark);
335 const int ny = cpl_image_get_size_y(dark);
336
337 zone[0] = visir_img_dark_config.rej_left+1;
338 zone[1] = nx - visir_img_dark_config.rej_right;
339 zone[2] = visir_img_dark_config.rej_bottom+1;
340 zone[3] = ny - visir_img_dark_config.rej_top;
341
342 *pavg = cpl_image_duplicate(dark);
343 skip_if(*pavg == NULL);
344 } else {
345 const cpl_propertylist * plist
346 = irplib_framelist_get_propertylist_const(f_one, i-1);
347 const int ndit = visir_pfits_get_ndit(plist);
348 const char ron_format[] = "ESO QC RON%d";
349 double ron;
350
351 skip_if(0);
352
353 irplib_ensure(ndit > 0, CPL_ERROR_ILLEGAL_INPUT,
354 VISIR_PFITS_INT_NDIT " must be positive, not %d",
355 ndit);
356
357 skip_if(cpl_image_subtract(diff, dark));
358
359 /* Compute the read-out noise */
360 irplib_check(cpl_flux_get_noise_window(diff, zone,
361 visir_img_dark_config.hsize,
362 visir_img_dark_config.nsamples,
363 &rms, NULL),
364 "Cannot compute the RON for difference between images "
365 "%d and %d", i, i+1);
366
367 /* Normalise the RON with NDIT */
368 ron = rms * sqrt(ndit/2.0);
369
370 /* Add QC parameters */
371 cpl_free(ron_key);
372 ron_key = cpl_sprintf(ron_format, i);
373
374 bug_if(ron_key == NULL);
375
376 skip_if(cpl_propertylist_append_double(qclist, ron_key, ron));
377
378 /* Sum up the darks */
379 skip_if(cpl_image_add(*pavg, dark));
380
381 }
382
383 }
384 cpl_image_delete(dark);
385 dark = NULL;
386
387 mean = cpl_image_get_mean(diff);
388
389 /* Use the rms of the difference of the last two images to
390 create the deviant pixel map */
391 lower = mean - rms * visir_img_dark_config.dev_thresh;
392 upper = mean + rms * visir_img_dark_config.dev_thresh;
393 cpl_mask_delete(*pdev);
394 irplib_check(*pdev = cpl_mask_threshold_image_create(diff, lower, upper),
395 "Cannot compute the deviant pixel map");
396 cpl_image_delete(diff);
397 diff = NULL;
398
399 skip_if (cpl_mask_not(*pdev));
400 ndevpix = cpl_mask_count(*pdev);
401 skip_if (0);
402
403 /* Average it to the master dark */
404 skip_if(cpl_image_divide_scalar(*pavg, (double)nfiles));
405
406 /* Compute median-rms of the central part of the dark */
407 dark_med = cpl_image_get_median_window(*pavg, zone[0], zone[2], zone[1],
408 zone[3]);
409
410 irplib_check (cpl_flux_get_noise_window(*pavg, zone,
411 visir_img_dark_config.hsize,
412 visir_img_dark_config.nsamples,
413 &rms, NULL),
414 "Cannot compute the RON of the master dark");
415
416 lower = dark_med - rms * visir_img_dark_config.cold_thresh;
417 upper = dark_med + rms * visir_img_dark_config.hot_thresh;
418
419 /* Create the cold pixel map */
420 cpl_mask_delete(*pcold);
421 irplib_check(*pcold = cpl_mask_threshold_image_create(*pavg, -FLT_MAX,
422 lower),
423 "Cannot compute the cold pixel map");
424 coldpix_nb = cpl_mask_count(*pcold);
425 skip_if (0);
426
427 /* Create the hot pixel map */
428 cpl_mask_delete(*phot);
429 irplib_check(*phot = cpl_mask_threshold_image_create(*pavg, upper, DBL_MAX),
430 "Cannot compute the hot pixel map");
431 hotpix_nb = cpl_mask_count(*phot);
432 skip_if (0);
433
434 /* Add QC parameters */
435
436 skip_if(cpl_propertylist_append_double(qclist, "ESO QC DARKMED", dark_med));
437 skip_if(cpl_propertylist_append_int(qclist, "ESO QC NBCOLPIX", coldpix_nb));
438 skip_if(cpl_propertylist_append_int(qclist, "ESO QC NBHOTPIX", hotpix_nb));
439 skip_if(cpl_propertylist_append_int(qclist, "ESO QC NBDEVPIX", ndevpix));
440
441 end_skip;
442
443 cpl_image_delete(dark);
444 cpl_image_delete(diff);
445 cpl_free(ron_key);
446
447 return cpl_error_get_code();
448}
449
450/*----------------------------------------------------------------------------*/
464/*----------------------------------------------------------------------------*/
465static cpl_error_code visir_img_dark_save(cpl_frameset * set_tot,
466 const cpl_parameterlist * parlist,
467 const cpl_propertylist * qclist,
468 const cpl_image * avg,
469 const cpl_mask * hot,
470 const cpl_mask * cold,
471 const cpl_mask * dev,
472 int set_nb,
473 const irplib_framelist * f_one)
474{
475 cpl_frameset * set = irplib_frameset_cast(f_one);
476 const cpl_propertylist * plist
477 = irplib_framelist_get_propertylist_const(f_one, 0);
478 cpl_propertylist * paflist = cpl_propertylist_new();
479 cpl_image * image = NULL;
480 const char pafcopy[] = "^(" VISIR_PFITS_REGEXP_DARK_PAF ")$";
481 char * filename = NULL;
482 const char * procatg_avg;
483 const char * procatg_dev;
484 const char * procatg_hot;
485 const char * procatg_cold;
486
487
488 /* This will catch f_one == NULL or plist == NULL */
489 skip_if (0);
490
491
492 switch (visir_img_dark_config.mode) {
493 case visir_dark_img:
494 procatg_avg = VISIR_IMG_DARK_AVG_PROCATG;
495 procatg_dev = VISIR_IMG_DARK_DEV_PROCATG;
496 procatg_hot = VISIR_IMG_DARK_HOT_PROCATG;
497 procatg_cold = VISIR_IMG_DARK_COLD_PROCATG;
498 break;
499 case visir_dark_spc:
500 procatg_avg = VISIR_SPC_DARK_AVG_PROCATG;
501 procatg_dev = VISIR_SPC_DARK_DEV_PROCATG;
502 procatg_hot = VISIR_SPC_DARK_HOT_PROCATG;
503 procatg_cold = VISIR_SPC_DARK_COLD_PROCATG;
504 break;
505 default:
506 bug_if(1);
507 }
508
509
510 /* Write the average image */
511 filename = cpl_sprintf(RECIPE_STRING "_set%02d_avg" CPL_DFS_FITS,
512 set_nb);
513 skip_if (irplib_dfs_save_image(set_tot, parlist, set, avg, CPL_BPP_IEEE_FLOAT,
514 RECIPE_STRING, procatg_avg, qclist, NULL,
515 visir_pipe_id, filename));
516
517 /* Write the hotpixel map */
518 image = cpl_image_new_from_mask(hot);
519 skip_if(0);
520
521 cpl_free(filename);
522 filename = cpl_sprintf(RECIPE_STRING "_set%02d_hotpix" CPL_DFS_FITS,
523 set_nb);
524 skip_if (irplib_dfs_save_image(set_tot, parlist, set, image, CPL_BPP_32_SIGNED,
525 RECIPE_STRING, procatg_hot, qclist, NULL,
526 visir_pipe_id, filename));
527 cpl_image_delete(image);
528 image = NULL;
529
530 /* Write the coldpixel map */
531 image = cpl_image_new_from_mask(cold);
532 skip_if(0);
533
534 cpl_free(filename);
535 filename = cpl_sprintf(RECIPE_STRING "_set%02d_coldpix" CPL_DFS_FITS,
536 set_nb);
537 skip_if (irplib_dfs_save_image(set_tot, parlist, set, image, CPL_BPP_32_SIGNED,
538 RECIPE_STRING, procatg_cold, qclist, NULL,
539 visir_pipe_id, filename));
540 cpl_image_delete(image);
541 image = NULL;
542
543 /* Write the deviant pixel map */
544 image = cpl_image_new_from_mask(dev);
545 skip_if(0);
546
547 cpl_free(filename);
548 filename = cpl_sprintf(RECIPE_STRING "_set%02d_devpix" CPL_DFS_FITS,
549 set_nb);
550 skip_if (irplib_dfs_save_image(set_tot, parlist, set, image,
551 CPL_BPP_32_SIGNED, RECIPE_STRING,
552 procatg_dev, qclist, NULL, visir_pipe_id,
553 filename));
554 cpl_image_delete(image);
555 image = NULL;
556
557#ifdef VISIR_SAVE_PAF
558 /* THE PAF FILE FOR QC PARAMETERS */
559
560 skip_if (cpl_propertylist_copy_property_regexp(paflist, plist, pafcopy, 0));
561 skip_if (cpl_propertylist_append(paflist, qclist));
562
563 /* PRO.CATG */
564 bug_if (cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
565 procatg_avg));
566
567 cpl_free(filename);
568 filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_PAF, set_nb);
569 skip_if (cpl_dfs_save_paf("VISIR", RECIPE_STRING, paflist, filename));
570#else
571 bug_if(paflist == NULL);
572 bug_if(plist == NULL);
573 bug_if(pafcopy == NULL);
574#endif
575
576 end_skip;
577
578 cpl_image_delete(image);
579 cpl_frameset_delete(set);
580 cpl_propertylist_delete(paflist);
581 cpl_free(filename);
582
583 return cpl_error_get_code();
584}
585
586
587/*----------------------------------------------------------------------------*/
597/*----------------------------------------------------------------------------*/
598static char * visir_img_dark_make_tag(const cpl_frame* self,
599 const cpl_propertylist * plist, int dummy)
600{
601
602 char * tag = NULL;
603 double etime;
604
605
606 skip_if (0);
607
608 skip_if(self == NULL);
609 skip_if(plist == NULL);
610 skip_if(dummy < 0); /* Avoid warning of unused variable */
611
612 /* exposure time */
613 etime = visir_pfits_get_exptime(plist);
614 skip_if(0);
615
616 tag = cpl_sprintf("%.5f", etime);
617 bug_if(tag == NULL);
618
619 end_skip;
620
621 if (cpl_error_get_code()) {
622 cpl_free(tag);
623 tag = NULL;
624 }
625
626 return tag;
627
628}
629
cpl_error_code visir_dfs_check_framelist_tag(const irplib_framelist *self)
Check the tags in a frameset (group raw only)
Definition: visir_dfs.c:234
int visir_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: visir_dfs.c:72
int visir_parameterlist_get_int(const cpl_parameterlist *self, const char *recipe, visir_parameter bitmask)
Retrieve the value of a VISIR integer parameter.
const char * visir_parameterlist_get_string(const cpl_parameterlist *self, const char *recipe, visir_parameter bitmask)
Retrieve the value of a VISIR string parameter.
double visir_parameterlist_get_double(const cpl_parameterlist *self, const char *recipe, visir_parameter bitmask)
Retrieve the value of a VISIR parameter of type double.
double visir_pfits_get_exptime(const cpl_propertylist *self)
The exposure time.
Definition: visir_pfits.c:422
int visir_pfits_get_ndit(const cpl_propertylist *self)
The NDIT keyword.
Definition: visir_pfits.c:535