IIINSTRUMENT Pipeline Reference Manual  4.4.11
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 
48 static cpl_error_code naco_img_dark_reduce(cpl_propertylist *,
49  const irplib_framelist *,
50  cpl_image **, cpl_mask **,
51  cpl_mask **, cpl_mask **);
52 
53 static cpl_error_code naco_img_dark_qc(cpl_propertylist *,
54  cpl_propertylist *,
55  const irplib_framelist *);
56 
57 static 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 
65 static char * naco_img_dark_make_tag(const cpl_frame*,
66  const cpl_propertylist *, int);
67 
68 NACO_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 
85 static 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 /*----------------------------------------------------------------------------*/
117 static 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 /*----------------------------------------------------------------------------*/
264 static 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 /*----------------------------------------------------------------------------*/
432 static 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 /*----------------------------------------------------------------------------*/
473 static 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 /*----------------------------------------------------------------------------*/
572 static 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.
double naco_pfits_get_exptime(const cpl_propertylist *self)
find out the exposure time
Definition: naco_pfits.c:155
const char * naco_pfits_get_mode(const cpl_propertylist *self)
find out the mode name
Definition: naco_pfits.c:268
const char * naco_pfits_get_opti7_name(const cpl_propertylist *self)
find out the OPTI7.NAME key
Definition: naco_pfits.c:329
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