IIINSTRUMENT Pipeline Reference Manual  4.4.10
naco_img_lampflat.c
1 /* $Id: naco_img_lampflat.c,v 1.60 2010-03-04 15:57:20 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: 2010-03-04 15:57:20 $
24  * $Revision: 1.60 $
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  Recipe defines
40  -----------------------------------------------------------------------------*/
41 
42 #define RECIPE_STRING "naco_img_lampflat"
43 
44 /*-----------------------------------------------------------------------------
45  Private Functions prototypes
46  -----------------------------------------------------------------------------*/
47 
48 static cpl_image * naco_img_lampflat_reduce(cpl_propertylist *,
49  const irplib_framelist *,
50  int, int, int, int);
51 
52 static cpl_error_code naco_img_lampflat_qc(cpl_propertylist *,
53  cpl_propertylist *,
54  const irplib_framelist *);
55 
56 static cpl_error_code naco_img_lampflat_save(cpl_frameset *,
57  const cpl_parameterlist *,
58  const cpl_propertylist *,
59  const cpl_propertylist *,
60  const cpl_image *,
61  int, const irplib_framelist *);
62 
63 static char * naco_img_lampflat_make_tag(const cpl_frame*,
64  const cpl_propertylist *, int);
65 
66 NACO_RECIPE_DEFINE(naco_img_lampflat, NACO_PARAM_REJBORD,
67  "Flat recipe using a lamp",
68  RECIPE_STRING " -- NACO imaging flat-field creation from "
69  "lamp images.\n"
70  "The files listed in the Set Of Frames (sof-file) "
71  "must be tagged:\n"
72  "NACO-raw-file.fits " NACO_IMG_LAMPFLAT_RAW "\n"
73  "\n"
74  "Furthermore, the input set of frames must have values of "
75  "the FITS key "
76  NACO_PFITS_INT_LAMP2 " that alternate between zero and "
77  "non-zero (with non-zero for the first frame).\n"
78  "It is further required that the light from the lamp is "
79  "in a range without a significant thermal background.");
80 
81 
82 /*----------------------------------------------------------------------------*/
86 /*----------------------------------------------------------------------------*/
87 
88 /*-----------------------------------------------------------------------------
89  Functions code
90  -----------------------------------------------------------------------------*/
91 
92 /*----------------------------------------------------------------------------*/
99 /*----------------------------------------------------------------------------*/
100 static int naco_img_lampflat(cpl_frameset * framelist,
101  const cpl_parameterlist * parlist)
102 {
103  cpl_errorstate cleanstate = cpl_errorstate_get();
104  irplib_framelist * allframes = NULL;
105  irplib_framelist * rawframes = NULL;
106  irplib_framelist * f_one = NULL;
107  const char ** taglist = NULL;
108  const char * rej_bord;
109  cpl_image * lamp_flat = NULL;
110  cpl_propertylist * qclist = cpl_propertylist_new();
111  cpl_propertylist * paflist = cpl_propertylist_new();
112  int nb_good = 0;
113  int nsets;
114  int rej_left, rej_right, rej_bottom, rej_top;
115  int i;
116 
117 
118  /* Retrieve input parameters */
119  rej_bord = naco_parameterlist_get_string(parlist, RECIPE_STRING, NACO_PARAM_REJBORD);
120  skip_if (0);
121  skip_if_ne(sscanf(rej_bord, "%d %d %d %d",
122  &rej_left, &rej_right, &rej_bottom, &rej_top), 4,
123  "number(s) in string parameter (%s): \"%s\"",
124  CPL_XSTRINGIFY(NACO_PARAM_REJBORD), rej_bord);
125 
126  /* Identify the RAW and CALIB frames in the input frameset */
127  skip_if (naco_dfs_set_groups(framelist));
128 
129  allframes = irplib_framelist_cast(framelist);
130  skip_if(allframes == NULL);
131 
132  rawframes = irplib_framelist_extract(allframes, NACO_IMG_LAMPFLAT_RAW);
133  skip_if(rawframes == NULL);
134  irplib_framelist_empty(allframes);
135 
136  skip_if(irplib_framelist_load_propertylist_all(rawframes, 0, "^("
137  IRPLIB_PFITS_REGEXP_RECAL "|"
138  NACO_PFITS_REGEXP_LAMPFLAT "|"
139  NACO_PFITS_REGEXP_LAMPFLAT_PAF
140  ")$", CPL_FALSE));
141 
142  taglist = naco_framelist_set_tag(rawframes, naco_img_lampflat_make_tag,
143  &nsets);
144  skip_if(taglist == NULL);
145 
146  cpl_msg_info(cpl_func, "Identified %d setting(s) in %d frames",
147  nsets, irplib_framelist_get_size(rawframes));
148 
149  /* Extract settings and reduce each of them */
150  for (i=0 ; i < nsets ; i++) {
151 
152  /* Reduce data set nb i */
153  cpl_msg_info(cpl_func, "Reducing data set %d of %d", i+1, nsets);
154 
155  /* Reduce data set nb i */
156  f_one = irplib_framelist_extract(rawframes, taglist[i]);
157 
158  /* Reset the tag */
159  skip_if(irplib_framelist_set_tag_all(f_one, NACO_IMG_LAMPFLAT_RAW));
160 
161  cpl_msg_info(cpl_func, "Reducing frame set %d of %d (size=%d) with "
162  "setting: %s", i+1, nsets,
163  irplib_framelist_get_size(f_one), taglist[i]);
164 
165  skip_if (f_one == NULL);
166 
167  lamp_flat = naco_img_lampflat_reduce(qclist, f_one, rej_left, rej_right,
168  rej_bottom, rej_top);
169 
170  /* Save the products */
171  if (lamp_flat == NULL) {
172  if (nsets > 1)
173  irplib_error_recover(cleanstate, "Could not compute the flat for "
174  "this setting");
175  } else {
176  skip_if(naco_img_lampflat_qc(qclist, paflist, f_one));
177  /* PRO.CATG */
178  bug_if(cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
179  NACO_IMG_LAMPFLAT_RES));
180  skip_if(naco_img_lampflat_save(framelist, parlist, qclist, paflist,
181  lamp_flat, i+1, f_one));
182  cpl_image_delete(lamp_flat);
183  lamp_flat = NULL;
184  nb_good++;
185  }
186  cpl_propertylist_empty(qclist);
187  cpl_propertylist_empty(paflist);
188  irplib_framelist_delete(f_one);
189  f_one = NULL;
190  }
191 
192  irplib_ensure(nb_good > 0, CPL_ERROR_DATA_NOT_FOUND,
193  "None of the %d sets could be reduced", nsets);
194 
195  end_skip;
196 
197  cpl_free(taglist);
198  cpl_image_delete(lamp_flat);
199  irplib_framelist_delete(f_one);
200  irplib_framelist_delete(allframes);
201  irplib_framelist_delete(rawframes);
202  cpl_propertylist_delete(qclist);
203  cpl_propertylist_delete(paflist);
204 
205  return cpl_error_get_code();
206 }
207 
208 /*----------------------------------------------------------------------------*/
219 /*----------------------------------------------------------------------------*/
220 static cpl_image * naco_img_lampflat_reduce(cpl_propertylist * qclist,
221  const irplib_framelist * framelist,
222  int rej_left, int rej_right,
223  int rej_bottom, int rej_top)
224 {
225  int nfiles;
226  cpl_image * image = NULL;
227  cpl_image * aver = NULL;
228  cpl_image * diff = NULL;
229  cpl_image * prev = NULL;
230  cpl_image * image0= NULL;
231  double gain, fp_noise;
232  double lamp_flux = DBL_MAX; /* Avoid uninit warning */
233  double std_diff[3];
234  double mean = DBL_MAX; /* Avoid uninit warning */
235  double square;
236  int i;
237 
238 
239  bug_if (framelist == NULL);
240 
241  nfiles = irplib_framelist_get_size(framelist);
242 
243  /* At least 4 frames are requested for the gain computation */
244  skip_if_lt(nfiles, 4, "frames");
245 
246  /* Verify that the number of frames is even */
247  irplib_ensure (nfiles % 2 == 0, CPL_ERROR_ILLEGAL_INPUT,
248  "The number of frames must be even, not %d", nfiles);
249 
250  skip_if (irplib_framelist_contains(framelist, NACO_PFITS_DOUBLE_DIT,
251  CPL_TYPE_DOUBLE, CPL_TRUE, 1e-5));
252 
253  skip_if (irplib_framelist_contains(framelist, NACO_PFITS_INT_LAMP2,
254  CPL_TYPE_INT, CPL_FALSE, 0.0));
255 
256  /* Print out the file names */
257  /* Verify that the frame sequence is lamp on - lamp off */
258  for (i=0 ; i < nfiles ; i++) {
259  const cpl_frame * frame = irplib_framelist_get_const(framelist, i);
260  const char * name = cpl_frame_get_filename(frame);
261  const cpl_propertylist * plist
262  = irplib_framelist_get_propertylist_const(framelist, i);
263  int ival;
264 
265  skip_if(name == NULL);
266  skip_if(plist == NULL);
267 
268  if (i == 0) {
269  /* Print out the filter used in this set of frames */
270  const char * sval = naco_pfits_get_filter(plist);
271 
272  skip_if (0);
273  cpl_msg_info(cpl_func, "Filter: [%s]", sval);
274 
275  /* Copy the required keys to the list of QC parameters */
276  skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS",
277  sval));
278  sval = naco_pfits_get_opti3_name(plist);
279  skip_if (0);
280  skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER NDENS",
281  sval));
282  sval = naco_pfits_get_opti4_name(plist);
283  skip_if (0);
284  skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER POL",
285  sval));
286  }
287 
288  cpl_msg_info(cpl_func, "File %02d: %s", i+1, name);
289 
290  /* Get lamp info from frame 2*i */
291  ival = naco_pfits_get_lamp2(plist);
292  if (i % 2) {
293  irplib_ensure (ival == 0, CPL_ERROR_ILLEGAL_INPUT,
294  "Frame number %d must have %s set to zero, not %d",
295  i+1, NACO_PFITS_INT_LAMP2, ival);
296  } else {
297  irplib_ensure (ival != 0, CPL_ERROR_ILLEGAL_INPUT,
298  "Frame number %d must have a non-zero %s",
299  i+1, NACO_PFITS_INT_LAMP2);
300  }
301 
302  irplib_check(image = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0),
303  "Could not load FITS-image from %s", name);
304 
305  if (i == 0) {
306  irplib_check(mean = cpl_image_get_mean(image),
307  "Could not compute mean");
308  image0 = image; image = NULL;
309  } else if (i <= 3) {
310  const int ifirst = i == 3 ? 1 : 0;
311  double noise;
312  /* Compute noise on : on1 - off1 */
313  /* Compute noise on : on1 - on2 */
314  /* Compute noise on : off1 - off2 */
315  irplib_check(diff = cpl_image_subtract_create(image0, image),
316  "Could not subtract the images %d and %d",
317  ifirst+1, i+1);
318 
319  irplib_check(cpl_flux_get_noise_window(diff, NULL, -1, -1,
320  &noise, NULL),
321  "Could not compute noise on difference between"
322  " images %d and %d", ifirst+1, i+1);
323 
324  std_diff[i-1] = noise * noise;
325 
326  if (i == 1) {
327  /* LAMPFLUX */
328  /* Print out the filter used in this set of frames */
329  const double median = cpl_image_get_median(diff);
330  const double ditval = naco_pfits_get_dit(plist);
331 
332  skip_if (cpl_error_get_code());
333  skip_if (ditval <= 0.0);
334 
335  lamp_flux = median / ditval;
336 
337  /* The 1st contribution to the average of differences */
338  aver = diff;
339 
340  } else {
341  cpl_image_delete(diff);
342  diff = NULL;
343  /* Finished with image[i-2] */
344  cpl_image_delete(image0);
345  /* Update image0 - to either image[i-1] or none */
346  image0 = i == 2 ? prev : NULL;
347  }
348 
349  }
350 
351  if (i > 1 && i % 2 != 0) {
352  /* Compute the dark subtraction */
353  irplib_check(cpl_image_subtract(prev, image),
354  "Could not correct for the dark");
355 
356  /* Sum up the dark corrected frames */
357  irplib_check(cpl_image_add(aver, prev),
358  "Could not sum up the dark corrected images");
359 
360  cpl_image_delete(image);
361  cpl_image_delete(prev);
362  prev = NULL;
363  } else {
364  prev = image;
365  }
366  image = NULL;
367  }
368 
369  /* Compute the QC parameters */
370  cpl_msg_info(cpl_func, "Computing the QC parameters");
371 
372  /* Deduce GAIN */
373  square = std_diff[1] - std_diff[2];
374  if (square != 0.0) square = 2.0*mean/square;
375  gain = square > 0.0 ? sqrt(square) : 0.0;
376 
377  /* Deduce FPNOISE */
378  square = std_diff[0] - std_diff[1] - std_diff[2];
379  fp_noise = square > 0.0 ? sqrt(square) : 0.0;
380 
381  /* Print results */
382  cpl_msg_info(cpl_func, "Gain: %g", gain);
383  cpl_msg_info(cpl_func, "Noise: %g", fp_noise);
384  cpl_msg_info(cpl_func, "Lamp flux: %g", lamp_flux);
385 
386  /* Average the dark corrected frames */
387  cpl_msg_info(cpl_func, "Average the dark corrected frames");
388  irplib_check(cpl_image_divide_scalar(aver, (double)(nfiles/2)),
389  "Could not average the %d dark corrected frames", nfiles/2);
390 
391  /* Normalize the flat */
392  irplib_check(mean
393  = cpl_image_get_mean_window(aver, rej_left,
394  cpl_image_get_size_x(aver)
395  -rej_right,
396  rej_bottom,
397  cpl_image_get_size_y(aver)
398  -rej_top);
399  cpl_image_divide_scalar(aver, mean),
400  "Could not average the %d dark corrected frames", nfiles/2);
401 
402  /* Add QC parameters */
403  skip_if(cpl_propertylist_append_double(qclist, "ESO QC GAIN", gain));
404  skip_if(cpl_propertylist_append_double(qclist, "ESO QC FPNOISE", fp_noise));
405  skip_if(cpl_propertylist_append_double(qclist, "ESO QC LAMPFLUX",
406  lamp_flux));
407 
408  end_skip;
409 
410  if (cpl_error_get_code()) {
411  cpl_image_delete(aver);
412  aver = NULL;
413  }
414 
415  cpl_image_delete(image);
416  cpl_image_delete(diff);
417  cpl_image_delete(prev);
418  cpl_image_delete(image0);
419 
420  return aver;
421 }
422 
423 
424 /*----------------------------------------------------------------------------*/
432 /*----------------------------------------------------------------------------*/
433 static cpl_error_code naco_img_lampflat_qc(cpl_propertylist * qclist,
434  cpl_propertylist * paflist,
435  const irplib_framelist * rawframes)
436 {
437 
438  const cpl_propertylist * reflist
439  = irplib_framelist_get_propertylist_const(rawframes, 0);
440  const char pafcopy[] = "^(" NACO_PFITS_REGEXP_LAMPFLAT_PAF ")$";
441 
442 
443  bug_if (0);
444 
445 
446  /* THE PAF FILE FOR QC PARAMETERS */
447  skip_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
448  0));
449  skip_if (cpl_propertylist_append(paflist, qclist));
450 
451  bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist, "^("
452  IRPLIB_PFITS_REGEXP_RECAL
453  ")$", 0));
454 
455  end_skip;
456 
457  return cpl_error_get_code();
458 }
459 
460 /*----------------------------------------------------------------------------*/
472 /*----------------------------------------------------------------------------*/
473 static cpl_error_code naco_img_lampflat_save(cpl_frameset * set_tot,
474  const cpl_parameterlist * parlist,
475  const cpl_propertylist * qclist,
476  const cpl_propertylist * paflist,
477  const cpl_image * flat,
478  int set_nb,
479  const irplib_framelist * rawframes)
480 {
481  cpl_frameset * proframes = irplib_frameset_cast(rawframes);
482  char * filename = NULL;
483 
484 
485 
486  /* This will catch rawframes == NULL */
487  bug_if (0);
488 
489  /* SAVE THE COMBINED IMAGE */
490  filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_FITS, set_nb);
491  skip_if (irplib_dfs_save_image(set_tot, parlist, proframes, flat,
492  CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
493  NACO_IMG_LAMPFLAT_RES, qclist, NULL,
494  naco_pipe_id, filename));
495 
496 #ifdef NACO_SAVE_PAF
497  cpl_free(filename);
498  filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_PAF, set_nb);
499  skip_if (cpl_dfs_save_paf("NACO", RECIPE_STRING, paflist, filename));
500 #else
501  bug_if(paflist == NULL);
502 #endif
503 
504  end_skip;
505 
506  cpl_free(filename);
507  cpl_frameset_delete(proframes);
508 
509  return cpl_error_get_code();
510 
511 }
512 
513 
514 /*----------------------------------------------------------------------------*/
524 /*----------------------------------------------------------------------------*/
525 static char * naco_img_lampflat_make_tag(const cpl_frame* self,
526  const cpl_propertylist * plist,
527  int dummy)
528 {
529 
530  char * tag = NULL;
531  const char * filter;
532  const char * opti3;
533  const char * opti7;
534  const char * rom;
535  const char * mode;
536  double dit;
537 
538 
539  skip_if (cpl_error_get_code());
540 
541  skip_if(self == NULL);
542  skip_if(plist == NULL);
543  skip_if(dummy < 0); /* Avoid warning of unused variable */
544 
545 
546  /* filters */
547  filter = naco_pfits_get_filter(plist);
548  skip_if(cpl_error_get_code());
549 
550  /* the objective */
551  opti7 = naco_pfits_get_opti7_name(plist);
552  skip_if(cpl_error_get_code());
553 
554  /* the OPTI3_NAME */
555  opti3 = naco_pfits_get_opti3_name(plist);
556  skip_if(cpl_error_get_code());
557 
558  /* the ROM */
559  rom = naco_pfits_get_rom_name(plist);
560  skip_if(cpl_error_get_code());
561 
562  /* the mode */
563  mode = naco_pfits_get_mode(plist);
564  skip_if(cpl_error_get_code());
565 
566  /* Compare the DIT */
567  dit = naco_pfits_get_dit(plist);
568  skip_if(cpl_error_get_code());
569 
570 
571  tag = cpl_sprintf("%s:%s:%s:%s:%s:%.5f", filter,
572  opti7, opti3, rom, mode, dit);
573  bug_if(tag == NULL);
574 
575  end_skip;
576 
577  if (cpl_error_get_code()) {
578  cpl_free(tag);
579  tag = NULL;
580  }
581 
582  return tag;
583 
584 }
naco_pfits_get_opti7_name
const char * naco_pfits_get_opti7_name(const cpl_propertylist *self)
find out the OPTI7.NAME key
Definition: naco_pfits.c:329
naco_framelist_set_tag
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
naco_pfits_get_dit
double naco_pfits_get_dit(const cpl_propertylist *self)
find out the DIT
Definition: naco_pfits.c:131
naco_pfits_get_lamp2
int naco_pfits_get_lamp2(const cpl_propertylist *self)
find out the INS.LAMP2.SET keyword
Definition: naco_pfits.c:256
naco_parameterlist_get_string
const char * naco_parameterlist_get_string(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO string parameter.
Definition: naco_parameter.c:604
naco_pfits_get_filter
const char * naco_pfits_get_filter(const cpl_propertylist *self)
find out the filter
Definition: naco_pfits.c:167
naco_pfits_get_rom_name
const char * naco_pfits_get_rom_name(const cpl_propertylist *self)
find out the read out mode name
Definition: naco_pfits.c:389
naco_pfits_get_opti4_name
const char * naco_pfits_get_opti4_name(const cpl_propertylist *self)
find out the OPTI4.NAME key
Definition: naco_pfits.c:316
naco_pfits_get_mode
const char * naco_pfits_get_mode(const cpl_propertylist *self)
find out the mode name
Definition: naco_pfits.c:268
naco_pfits_get_opti3_name
const char * naco_pfits_get_opti3_name(const cpl_propertylist *self)
find out the OPTI3.NAME key
Definition: naco_pfits.c:304
naco_dfs_set_groups
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: naco_dfs.c:62