IIINSTRUMENT Pipeline Reference Manual 4.4.13
naco_img_dark.c
1/* $Id: naco_img_dark.c,v 1.75 2011-12-22 11:12:38 llundin Exp $
2 *
3 * This file is part of the NACO 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-22 11:12:38 $
24 * $Revision: 1.75 $
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 "naco_recipe.h"
37
38/*-----------------------------------------------------------------------------
39 Defines
40 -----------------------------------------------------------------------------*/
41
42#define RECIPE_STRING "naco_img_dark"
43
44/*-----------------------------------------------------------------------------
45 Private Functions prototypes
46 -----------------------------------------------------------------------------*/
47
48static cpl_error_code naco_img_dark_reduce(cpl_propertylist *,
49 const irplib_framelist *,
50 cpl_image **, cpl_mask **,
51 cpl_mask **, cpl_mask **);
52
53static cpl_error_code naco_img_dark_qc(cpl_propertylist *,
54 cpl_propertylist *,
55 const irplib_framelist *);
56
57static cpl_error_code naco_img_dark_save(cpl_frameset *,
58 const cpl_parameterlist *,
59 const cpl_propertylist *,
60 const cpl_propertylist *,
61 const cpl_image *, const cpl_mask *,
62 const cpl_mask *, const cpl_mask *,
63 int, const irplib_framelist *);
64
65static char * naco_img_dark_make_tag(const cpl_frame*,
66 const cpl_propertylist *, int);
67
68NACO_RECIPE_DEFINE(naco_img_dark,
69 NACO_PARAM_REJBORD |
70 NACO_PARAM_HOT_LIM |
71 NACO_PARAM_COLD_LIM |
72 NACO_PARAM_DEV_LIM |
73 NACO_PARAM_NSAMPLES |
74 NACO_PARAM_HALFSIZE,
75 "Dark recipe",
76 "naco_img_dark -- NACO imaging dark recipe.\n"
77 "The files listed in the Set Of Frames (sof-file) "
78 "must be tagged:\n"
79 "NACO-raw-file.fits " NACO_IMG_DARK_RAW "\n");
80
81/*-----------------------------------------------------------------------------
82 Static variables
83 -----------------------------------------------------------------------------*/
84
85static struct {
86 /* Inputs */
87 int rej_left;
88 int rej_right;
89 int rej_bottom;
90 int rej_top;
91 double hot_thresh;
92 double cold_thresh;
93 double dev_thresh;
94 int hsize;
95 int nsamples;
96} naco_img_dark_config;
97
98/*----------------------------------------------------------------------------*/
102/*----------------------------------------------------------------------------*/
103
104/*-----------------------------------------------------------------------------
105 Functions code
106 -----------------------------------------------------------------------------*/
107
108
109/*----------------------------------------------------------------------------*/
116/*----------------------------------------------------------------------------*/
117static int naco_img_dark(cpl_frameset * framelist,
118 const cpl_parameterlist * parlist)
119{
120 irplib_framelist* allframes = NULL;
121 irplib_framelist* rawframes = NULL;
122 const char ** taglist = NULL;
123 const char * rej_bord;
124 irplib_framelist* f_one = NULL;
125 cpl_imagelist * i_one = NULL;
126 cpl_image * avg = NULL;
127 cpl_mask * hot = NULL;
128 cpl_mask * cold = NULL;
129 cpl_mask * dev = NULL;
130 cpl_propertylist * qclist = cpl_propertylist_new();
131 cpl_propertylist * paflist = cpl_propertylist_new();
132 int nsets;
133 int i;
134 int nb_good = 0;
135
136
137 /* Retrieve input parameters */
138 rej_bord = naco_parameterlist_get_string(parlist, RECIPE_STRING, NACO_PARAM_REJBORD);
139 skip_if (0);
140 skip_if_ne(sscanf(rej_bord, "%d %d %d %d",
141 &naco_img_dark_config.rej_left,
142 &naco_img_dark_config.rej_right,
143 &naco_img_dark_config.rej_bottom,
144 &naco_img_dark_config.rej_top), 4,
145 "number(s) in string parameter (%s): \"%s\"",
146 CPL_XSTRINGIFY(NACO_PARAM_REJBORD), rej_bord);
147
148 naco_img_dark_config.hot_thresh =
149 naco_parameterlist_get_double(parlist, RECIPE_STRING, NACO_PARAM_HOT_LIM);
150 naco_img_dark_config.dev_thresh =
151 naco_parameterlist_get_double(parlist, RECIPE_STRING, NACO_PARAM_DEV_LIM);
152 naco_img_dark_config.cold_thresh =
153 naco_parameterlist_get_double(parlist, RECIPE_STRING, NACO_PARAM_COLD_LIM);
154 naco_img_dark_config.hsize =
155 naco_parameterlist_get_int(parlist, RECIPE_STRING, NACO_PARAM_HALFSIZE);
156 naco_img_dark_config.nsamples =
157 naco_parameterlist_get_int(parlist, RECIPE_STRING, NACO_PARAM_NSAMPLES);
158
159 skip_if (0);
160
161 /* Identify the RAW and CALIB frames in the input frameset */
162 skip_if (naco_dfs_set_groups(framelist));
163
164 allframes = irplib_framelist_cast(framelist);
165 skip_if(allframes == NULL);
166
167 rawframes = irplib_framelist_extract(allframes, NACO_IMG_DARK_RAW);
168 skip_if(rawframes == NULL);
169 irplib_framelist_empty(allframes);
170
171 skip_if(irplib_framelist_load_propertylist_all(rawframes, 0, "^("
172 IRPLIB_PFITS_REGEXP_RECAL "|"
173 NACO_PFITS_REGEXP_DARK "|"
174 NACO_PFITS_REGEXP_DARK_PAF
175 ")$", CPL_FALSE));
176
177 taglist = naco_framelist_set_tag(rawframes, naco_img_dark_make_tag, &nsets);
178 skip_if(taglist == NULL);
179
180 cpl_msg_info(cpl_func, "Identified %d setting(s) in %d frames",
181 nsets, irplib_framelist_get_size(rawframes));
182
183 /* Extract settings and reduce each of them */
184 for (i=0 ; i < nsets ; i++) {
185
186 /* Reduce data set nb i */
187 f_one = irplib_framelist_extract(rawframes, taglist[i]);
188
189 /* Reset the tag */
190 skip_if(irplib_framelist_set_tag_all(f_one, NACO_IMG_DARK_RAW));
191
192 cpl_msg_info(cpl_func, "Reducing frame set %d of %d (size=%d) with "
193 "setting: %s", i+1, nsets,
194 irplib_framelist_get_size(f_one), taglist[i]);
195
196 skip_if (f_one == NULL);
197
198 /* At least 2 frames required */
199 if (irplib_framelist_get_size(f_one) < 2) {
200 cpl_msg_warning(cpl_func, "Setting %d skipped (Need at least 2 "
201 "frames)", i+1);
202 irplib_framelist_delete(f_one);
203 f_one = NULL;
204 continue;
205 }
206
207 skip_if(naco_img_dark_reduce(qclist, f_one, &avg, &hot, &cold, &dev));
208
209 skip_if(naco_img_dark_qc(qclist, paflist, f_one));
210
211 /* Save the products */
212 skip_if (naco_img_dark_save(framelist, parlist, qclist, paflist,
213 avg, hot, cold, dev, i+1, f_one));
214
215 nb_good++;
216
217 cpl_image_delete(avg);
218 cpl_mask_delete(hot);
219 cpl_mask_delete(cold);
220 cpl_mask_delete(dev);
221 irplib_framelist_delete(f_one);
222 cpl_propertylist_empty(qclist);
223 cpl_propertylist_empty(paflist);
224 avg = NULL;
225 cold = NULL;
226 hot = NULL;
227 dev = NULL;
228 f_one = NULL;
229 }
230
231 skip_if (nb_good == 0);
232
233 end_skip;
234
235 cpl_imagelist_delete(i_one);
236 cpl_free(taglist);
237 cpl_image_delete(avg);
238 cpl_mask_delete(hot);
239 cpl_mask_delete(cold);
240 cpl_mask_delete(dev);
241 irplib_framelist_delete(f_one);
242 irplib_framelist_delete(allframes);
243 irplib_framelist_delete(rawframes);
244 cpl_propertylist_delete(qclist);
245 cpl_propertylist_delete(paflist);
246
247 return cpl_error_get_code();
248}
249
250/*----------------------------------------------------------------------------*/
263/*----------------------------------------------------------------------------*/
264static cpl_error_code naco_img_dark_reduce(cpl_propertylist * qclist,
265 const irplib_framelist * f_one,
266 cpl_image ** pavg, cpl_mask ** phot,
267 cpl_mask ** pcold, cpl_mask ** pdev)
268{
269
270 cpl_image * dark = NULL;
271 cpl_image * diff = NULL;
272 char * ron_key = NULL;
273 double rms;
274 double lower, upper;
275 double dark_med;
276 double mean;
277 int ndevpix;
278 cpl_size zone[4];
279 int coldpix_nb;
280 int hotpix_nb;
281 int nfiles;
282 int i;
283
284 skip_if (f_one == NULL);
285
286 nfiles = irplib_framelist_get_size(f_one);
287
288 skip_if (nfiles < 2);
289
290 skip_if (irplib_framelist_contains(f_one, "NAXIS1",
291 CPL_TYPE_INT, CPL_TRUE, 0.0));
292
293 skip_if (irplib_framelist_contains(f_one, "NAXIS2",
294 CPL_TYPE_INT, CPL_TRUE, 0.0));
295
296 for (i=0 ; i < nfiles ; i++) {
297 const cpl_frame * frame = irplib_framelist_get_const(f_one, i);
298 const char * name = cpl_frame_get_filename(frame);
299
300 cpl_image_delete(diff);
301 diff = dark;
302 irplib_check(dark = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0),
303 "Could not load FITS-image from %s", name);
304
305 if (i == 0) {
306 const int nx = cpl_image_get_size_x(dark);
307 const int ny = cpl_image_get_size_y(dark);
308
309 zone[0] = naco_img_dark_config.rej_left+1;
310 zone[1] = nx - naco_img_dark_config.rej_right;
311 zone[2] = naco_img_dark_config.rej_bottom+1;
312 zone[3] = ny - naco_img_dark_config.rej_top;
313
314 *pavg = cpl_image_duplicate(dark);
315 skip_if(*pavg == NULL);
316 } else {
317 const cpl_propertylist * plist
318 = irplib_framelist_get_propertylist_const(f_one, i-1);
319 const int ndit = naco_pfits_get_ndit(plist);
320 const char ron_format[] = "ESO QC RON%d";
321 double ron;
322
323 skip_if(0);
324
325 irplib_ensure(ndit > 0, CPL_ERROR_ILLEGAL_INPUT,
326 NACO_PFITS_INT_NDIT " must be positive, not %d",
327 ndit);
328
329 skip_if(cpl_image_subtract(diff, dark));
330
331 /* Compute the read-out noise */
332 irplib_check(cpl_flux_get_noise_window(diff, zone,
333 naco_img_dark_config.hsize,
334 naco_img_dark_config.nsamples,
335 &rms, NULL),
336 "Cannot compute the RON for difference between images "
337 "%d and %d", i, i+1);
338
339 /* Normalise the RON with NDIT */
340 ron = rms * sqrt(ndit/2.0);
341
342 /* Add QC parameters */
343 cpl_free(ron_key);
344 ron_key = cpl_sprintf(ron_format, i);
345
346 bug_if(ron_key == NULL);
347
348 skip_if(cpl_propertylist_append_double(qclist, ron_key, ron));
349
350 /* Sum up the darks */
351 skip_if(cpl_image_add(*pavg, dark));
352
353 }
354
355 }
356 cpl_image_delete(dark);
357 dark = NULL;
358
359 mean = cpl_image_get_mean(diff);
360
361 /* Use the rms of the difference of the last two images to
362 create the deviant pixel map */
363 lower = mean - rms * naco_img_dark_config.dev_thresh;
364 upper = mean + rms * naco_img_dark_config.dev_thresh;
365 cpl_mask_delete(*pdev);
366 irplib_check(*pdev = cpl_mask_threshold_image_create(diff, lower, upper),
367 "Cannot compute the deviant pixel map");
368 cpl_image_delete(diff);
369 diff = NULL;
370
371 skip_if (cpl_mask_not(*pdev));
372 ndevpix = cpl_mask_count(*pdev);
373 skip_if (0);
374
375 /* Average it to the master dark */
376 skip_if(cpl_image_divide_scalar(*pavg, (double)nfiles));
377
378 /* Compute median-rms of the central part of the dark */
379 dark_med = cpl_image_get_median_window(*pavg, zone[0], zone[2], zone[1],
380 zone[3]);
381
382 irplib_check (cpl_flux_get_noise_window(*pavg, zone,
383 naco_img_dark_config.hsize,
384 naco_img_dark_config.nsamples,
385 &rms, NULL),
386 "Cannot compute the RON of the master dark");
387
388 lower = dark_med - rms * naco_img_dark_config.cold_thresh;
389 upper = dark_med + rms * naco_img_dark_config.hot_thresh;
390
391 /* Create the cold pixel map */
392 cpl_mask_delete(*pcold);
393 irplib_check(*pcold = cpl_mask_threshold_image_create(*pavg, -FLT_MAX,
394 lower),
395 "Cannot compute the cold pixel map");
396 coldpix_nb = cpl_mask_count(*pcold);
397 skip_if (0);
398
399 /* Create the hot pixel map */
400 cpl_mask_delete(*phot);
401 irplib_check(*phot = cpl_mask_threshold_image_create(*pavg, upper, DBL_MAX),
402 "Cannot compute the hot pixel map");
403 hotpix_nb = cpl_mask_count(*phot);
404 skip_if (0);
405
406 /* Add QC parameters */
407
408 skip_if(cpl_propertylist_append_double(qclist, "ESO QC DARKMED", dark_med));
409 skip_if(cpl_propertylist_append_int(qclist, "ESO QC NBCOLPIX", coldpix_nb));
410 skip_if(cpl_propertylist_append_int(qclist, "ESO QC NBHOTPIX", hotpix_nb));
411 skip_if(cpl_propertylist_append_int(qclist, "ESO QC NBDEVPIX", ndevpix));
412
413 end_skip;
414
415 cpl_image_delete(dark);
416 cpl_image_delete(diff);
417 cpl_free(ron_key);
418
419 return cpl_error_get_code();
420}
421
422
423/*----------------------------------------------------------------------------*/
431/*----------------------------------------------------------------------------*/
432static cpl_error_code naco_img_dark_qc(cpl_propertylist * qclist,
433 cpl_propertylist * paflist,
434 const irplib_framelist * rawframes)
435{
436
437 const cpl_propertylist * reflist
438 = irplib_framelist_get_propertylist_const(rawframes, 0);
439 const char pafcopy[] = "^(" NACO_PFITS_REGEXP_DARK_PAF ")$";
440
441
442 bug_if (0);
443
444 bug_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
445 0));
446 bug_if (cpl_propertylist_append(paflist, qclist));
447
448 bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist, "^("
449 IRPLIB_PFITS_REGEXP_RECAL
450 ")$", 0));
451
452 end_skip;
453
454 return cpl_error_get_code();
455}
456
457/*----------------------------------------------------------------------------*/
472/*----------------------------------------------------------------------------*/
473static cpl_error_code naco_img_dark_save(cpl_frameset * set_tot,
474 const cpl_parameterlist * parlist,
475 const cpl_propertylist * qclist,
476 const cpl_propertylist * paflist,
477 const cpl_image * avg,
478 const cpl_mask * hot,
479 const cpl_mask * cold,
480 const cpl_mask * dev,
481 int set_nb,
482 const irplib_framelist * f_one)
483{
484 cpl_frameset * set_one = irplib_frameset_cast(f_one);
485 cpl_image * image = NULL;
486 char * filename = NULL;
487
488
489 bug_if (0);
490
491 /* Write the average image */
492 filename = cpl_sprintf(RECIPE_STRING "_set%02d_avg" CPL_DFS_FITS,
493 set_nb);
494 skip_if (irplib_dfs_save_image(set_tot, parlist, set_one, avg,
495 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
496 NACO_IMG_DARK_AVG, qclist, NULL, naco_pipe_id,
497 filename));
498
499 /* Write the hotpixel map */
500 image = cpl_image_new_from_mask(hot);
501 bug_if(0);
502
503 cpl_free(filename);
504 filename = cpl_sprintf(RECIPE_STRING "_set%02d_hotpix" CPL_DFS_FITS,
505 set_nb);
506 skip_if (irplib_dfs_save_image(set_tot, parlist, set_one, image,
507 CPL_BPP_8_UNSIGNED, RECIPE_STRING, NACO_IMG_DARK_HOT,
508 qclist, NULL, naco_pipe_id, filename));
509
510 /* Write the coldpixel map */
511 cpl_image_delete(image);
512 image = cpl_image_new_from_mask(cold);
513 bug_if(0);
514
515 cpl_free(filename);
516 filename = cpl_sprintf(RECIPE_STRING "_set%02d_coldpix" CPL_DFS_FITS,
517 set_nb);
518 skip_if (irplib_dfs_save_image(set_tot, parlist, set_one, image,
519 CPL_BPP_8_UNSIGNED, RECIPE_STRING,
520 NACO_IMG_DARK_COLD, qclist, NULL, naco_pipe_id,
521 filename));
522
523 /* Write the deviant pixel map */
524 cpl_image_delete(image);
525 image = cpl_image_new_from_mask(dev);
526 bug_if(0);
527
528 cpl_free(filename);
529 filename = cpl_sprintf(RECIPE_STRING "_set%02d_devpix" CPL_DFS_FITS,
530 set_nb);
531 skip_if (irplib_dfs_save_image(set_tot, parlist, set_one, image,
532 CPL_BPP_8_UNSIGNED, RECIPE_STRING, NACO_IMG_DARK_DEV,
533 qclist, NULL, naco_pipe_id, filename));
534 cpl_image_delete(image);
535 image = NULL;
536
537#ifdef NACO_SAVE_PAF
538 /* THE PAF FILE FOR QC PARAMETERS */
539
540 /* PRO.CATG */
541 bug_if(cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
542 NACO_IMG_DARK_AVG));
543
544 cpl_free(filename);
545 filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_PAF, set_nb);
546 skip_if (cpl_dfs_save_paf("NACO", RECIPE_STRING, paflist, filename));
547#else
548 bug_if(paflist == NULL);
549#endif
550
551 end_skip;
552
553 cpl_image_delete(image);
554 cpl_frameset_delete(set_one);
555 cpl_free(filename);
556
557 return cpl_error_get_code();
558}
559
560
561/*----------------------------------------------------------------------------*/
571/*----------------------------------------------------------------------------*/
572static char * naco_img_dark_make_tag(const cpl_frame* self,
573 const cpl_propertylist * plist, int dummy)
574{
575
576 char * tag = NULL;
577 const char * mode;
578 const char * name;
579 double etime;
580 int irom;
581
582
583 skip_if (cpl_error_get_code());
584
585 skip_if(self == NULL);
586 skip_if(plist == NULL);
587 skip_if(dummy < 0); /* Avoid warning of unused variable */
588
589 /* exposure time */
590 etime = naco_pfits_get_exptime(plist);
591 skip_if(cpl_error_get_code());
592
593 /* readout mode */
594 irom = naco_pfits_get_rom(plist);
595 skip_if(cpl_error_get_code());
596
597
598 /* detector mode */
599 mode = naco_pfits_get_mode(plist);
600 skip_if(cpl_error_get_code());
601
602 /* Compare the camera */
603 name = naco_pfits_get_opti7_name(plist);
604 skip_if(cpl_error_get_code());
605
606 tag = cpl_sprintf("%s:%s:%d:%.5f", name, mode, irom,
607 etime);
608 bug_if(tag == NULL);
609
610 end_skip;
611
612 if (cpl_error_get_code()) {
613 cpl_free(tag);
614 tag = NULL;
615 }
616
617 return tag;
618
619}
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: naco_dfs.c:62
double naco_parameterlist_get_double(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO parameter of type double.
int naco_parameterlist_get_int(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO integer parameter.
const char * naco_parameterlist_get_string(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO string parameter.
const char * naco_pfits_get_opti7_name(const cpl_propertylist *self)
find out the OPTI7.NAME key
Definition: naco_pfits.c:329
const char * naco_pfits_get_mode(const cpl_propertylist *self)
find out the mode name
Definition: naco_pfits.c:268
double naco_pfits_get_exptime(const cpl_propertylist *self)
find out the exposure time
Definition: naco_pfits.c:155
int naco_pfits_get_ndit(const cpl_propertylist *self)
find out the NDIT keyword
Definition: naco_pfits.c:292
int naco_pfits_get_rom(const cpl_propertylist *self)
find out the read out mode
Definition: naco_pfits.c:377
const char ** naco_framelist_set_tag(irplib_framelist *self, char *(*pftag)(const cpl_frame *, const cpl_propertylist *, int), int *pntags)
Retag a framelist according to the given tagging function.
Definition: naco_utils.c:176