NACO Pipeline Reference Manual  4.4.0
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 (sscanf(rej_bord, "%d %d %d %d",
122  &rej_left, &rej_right, &rej_bottom, &rej_top) != 4);
123 
124  /* Identify the RAW and CALIB frames in the input frameset */
125  skip_if (naco_dfs_set_groups(framelist));
126 
127  allframes = irplib_framelist_cast(framelist);
128  skip_if(allframes == NULL);
129 
130  rawframes = irplib_framelist_extract(allframes, NACO_IMG_LAMPFLAT_RAW);
131  skip_if(rawframes == NULL);
132  irplib_framelist_empty(allframes);
133 
134  skip_if(irplib_framelist_load_propertylist_all(rawframes, 0, "^("
135  IRPLIB_PFITS_REGEXP_RECAL "|"
136  NACO_PFITS_REGEXP_LAMPFLAT "|"
137  NACO_PFITS_REGEXP_LAMPFLAT_PAF
138  ")$", CPL_FALSE));
139 
140  taglist = naco_framelist_set_tag(rawframes, naco_img_lampflat_make_tag,
141  &nsets);
142  skip_if(taglist == NULL);
143 
144  cpl_msg_info(cpl_func, "Identified %d setting(s) in %d frames",
145  nsets, irplib_framelist_get_size(rawframes));
146 
147  /* Extract settings and reduce each of them */
148  for (i=0 ; i < nsets ; i++) {
149 
150  /* Reduce data set nb i */
151  cpl_msg_info(cpl_func, "Reducing data set %d of %d", i+1, nsets);
152 
153  /* Reduce data set nb i */
154  f_one = irplib_framelist_extract(rawframes, taglist[i]);
155 
156  /* Reset the tag */
157  skip_if(irplib_framelist_set_tag_all(f_one, NACO_IMG_LAMPFLAT_RAW));
158 
159  cpl_msg_info(cpl_func, "Reducing frame set %d of %d (size=%d) with "
160  "setting: %s", i+1, nsets,
161  irplib_framelist_get_size(f_one), taglist[i]);
162 
163  skip_if (f_one == NULL);
164 
165  lamp_flat = naco_img_lampflat_reduce(qclist, f_one, rej_left, rej_right,
166  rej_bottom, rej_top);
167 
168  /* Save the products */
169  if (lamp_flat == NULL) {
170  if (nsets > 1)
171  irplib_error_recover(cleanstate, "Could not compute the flat for "
172  "this setting");
173  } else {
174  skip_if(naco_img_lampflat_qc(qclist, paflist, f_one));
175  /* PRO.CATG */
176  bug_if(cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
177  NACO_IMG_LAMPFLAT_RES));
178  skip_if(naco_img_lampflat_save(framelist, parlist, qclist, paflist,
179  lamp_flat, i+1, f_one));
180  cpl_image_delete(lamp_flat);
181  lamp_flat = NULL;
182  nb_good++;
183  }
184  cpl_propertylist_empty(qclist);
185  cpl_propertylist_empty(paflist);
187  f_one = NULL;
188  }
189 
190  irplib_ensure(nb_good > 0, CPL_ERROR_DATA_NOT_FOUND,
191  "None of the %d sets could be reduced", nsets);
192 
193  end_skip;
194 
195  cpl_free(taglist);
196  cpl_image_delete(lamp_flat);
198  irplib_framelist_delete(allframes);
199  irplib_framelist_delete(rawframes);
200  cpl_propertylist_delete(qclist);
201  cpl_propertylist_delete(paflist);
202 
203  return cpl_error_get_code();
204 }
205 
206 /*----------------------------------------------------------------------------*/
217 /*----------------------------------------------------------------------------*/
218 static cpl_image * naco_img_lampflat_reduce(cpl_propertylist * qclist,
219  const irplib_framelist * framelist,
220  int rej_left, int rej_right,
221  int rej_bottom, int rej_top)
222 {
223  int nfiles;
224  cpl_image * image = NULL;
225  cpl_image * aver = NULL;
226  cpl_image * diff = NULL;
227  cpl_image * prev = NULL;
228  cpl_image * image0= NULL;
229  double gain, fp_noise;
230  double lamp_flux = DBL_MAX; /* Avoid uninit warning */
231  double std_diff[3];
232  double mean = DBL_MAX; /* Avoid uninit warning */
233  double square;
234  int i;
235 
236 
237  bug_if (framelist == NULL);
238 
239  nfiles = irplib_framelist_get_size(framelist);
240 
241  /* At least 4 frames are requested for the gain computation */
242  skip_if_lt(nfiles, 4, "frames");
243 
244  /* Verify that the number of frames is even */
245  irplib_ensure (nfiles % 2 == 0, CPL_ERROR_ILLEGAL_INPUT,
246  "The number of frames must be even, not %d", nfiles);
247 
248  skip_if (irplib_framelist_contains(framelist, NACO_PFITS_DOUBLE_DIT,
249  CPL_TYPE_DOUBLE, CPL_TRUE, 1e-5));
250 
251  skip_if (irplib_framelist_contains(framelist, NACO_PFITS_INT_LAMP2,
252  CPL_TYPE_INT, CPL_FALSE, 0.0));
253 
254  /* Print out the file names */
255  /* Verify that the frame sequence is lamp on - lamp off */
256  for (i=0 ; i < nfiles ; i++) {
257  const cpl_frame * frame = irplib_framelist_get_const(framelist, i);
258  const char * name = cpl_frame_get_filename(frame);
259  const cpl_propertylist * plist
261  int ival;
262 
263  skip_if(name == NULL);
264  skip_if(plist == NULL);
265 
266  if (i == 0) {
267  /* Print out the filter used in this set of frames */
268  const char * sval = naco_pfits_get_filter(plist);
269 
270  skip_if (0);
271  cpl_msg_info(cpl_func, "Filter: [%s]", sval);
272 
273  /* Copy the required keys to the list of QC parameters */
274  skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS",
275  sval));
276  sval = naco_pfits_get_opti3_name(plist);
277  skip_if (0);
278  skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER NDENS",
279  sval));
280  sval = naco_pfits_get_opti4_name(plist);
281  skip_if (0);
282  skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER POL",
283  sval));
284  }
285 
286  cpl_msg_info(cpl_func, "File %02d: %s", i+1, name);
287 
288  /* Get lamp info from frame 2*i */
289  ival = naco_pfits_get_lamp2(plist);
290  if (i % 2) {
291  irplib_ensure (ival == 0, CPL_ERROR_ILLEGAL_INPUT,
292  "Frame number %d must have %s set to zero, not %d",
293  i+1, NACO_PFITS_INT_LAMP2, ival);
294  } else {
295  irplib_ensure (ival != 0, CPL_ERROR_ILLEGAL_INPUT,
296  "Frame number %d must have a non-zero %s",
297  i+1, NACO_PFITS_INT_LAMP2);
298  }
299 
300  irplib_check(image = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0),
301  "Could not load FITS-image from %s", name);
302 
303  if (i == 0) {
304  irplib_check(mean = cpl_image_get_mean(image),
305  "Could not compute mean");
306  image0 = image; image = NULL;
307  } else if (i <= 3) {
308  const int ifirst = i == 3 ? 1 : 0;
309  double noise;
310  /* Compute noise on : on1 - off1 */
311  /* Compute noise on : on1 - on2 */
312  /* Compute noise on : off1 - off2 */
313  irplib_check(diff = cpl_image_subtract_create(image0, image),
314  "Could not subtract the images %d and %d",
315  ifirst+1, i+1);
316 
317  irplib_check(cpl_flux_get_noise_window(diff, NULL, -1, -1,
318  &noise, NULL),
319  "Could not compute noise on difference between"
320  " images %d and %d", ifirst+1, i+1);
321 
322  std_diff[i-1] = noise * noise;
323 
324  if (i == 1) {
325  /* LAMPFLUX */
326  /* Print out the filter used in this set of frames */
327  const double median = cpl_image_get_median(diff);
328  const double ditval = naco_pfits_get_dit(plist);
329 
330  skip_if (cpl_error_get_code());
331  skip_if (ditval <= 0.0);
332 
333  lamp_flux = median / ditval;
334 
335  /* The 1st contribution to the average of differences */
336  aver = diff;
337 
338  } else {
339  cpl_image_delete(diff);
340  diff = NULL;
341  /* Finished with image[i-2] */
342  cpl_image_delete(image0);
343  /* Update image0 - to either image[i-1] or none */
344  image0 = i == 2 ? prev : NULL;
345  }
346 
347  }
348 
349  if (i > 1 && i % 2 != 0) {
350  /* Compute the dark subtraction */
351  irplib_check(cpl_image_subtract(prev, image),
352  "Could not correct for the dark");
353 
354  /* Sum up the dark corrected frames */
355  irplib_check(cpl_image_add(aver, prev),
356  "Could not sum up the dark corrected images");
357 
358  cpl_image_delete(image);
359  cpl_image_delete(prev);
360  prev = NULL;
361  } else {
362  prev = image;
363  }
364  image = NULL;
365  }
366 
367  /* Compute the QC parameters */
368  cpl_msg_info(cpl_func, "Computing the QC parameters");
369 
370  /* Deduce GAIN */
371  square = std_diff[1] - std_diff[2];
372  if (square != 0.0) square = 2.0*mean/square;
373  gain = square > 0.0 ? sqrt(square) : 0.0;
374 
375  /* Deduce FPNOISE */
376  square = std_diff[0] - std_diff[1] - std_diff[2];
377  fp_noise = square > 0.0 ? sqrt(square) : 0.0;
378 
379  /* Print results */
380  cpl_msg_info(cpl_func, "Gain: %g", gain);
381  cpl_msg_info(cpl_func, "Noise: %g", fp_noise);
382  cpl_msg_info(cpl_func, "Lamp flux: %g", lamp_flux);
383 
384  /* Average the dark corrected frames */
385  cpl_msg_info(cpl_func, "Average the dark corrected frames");
386  irplib_check(cpl_image_divide_scalar(aver, (double)(nfiles/2)),
387  "Could not average the %d dark corrected frames", nfiles/2);
388 
389  /* Normalize the flat */
390  irplib_check(mean
391  = cpl_image_get_mean_window(aver, rej_left,
392  cpl_image_get_size_x(aver)
393  -rej_right,
394  rej_bottom,
395  cpl_image_get_size_y(aver)
396  -rej_top);
397  cpl_image_divide_scalar(aver, mean),
398  "Could not average the %d dark corrected frames", nfiles/2);
399 
400  /* Add QC parameters */
401  skip_if(cpl_propertylist_append_double(qclist, "ESO QC GAIN", gain));
402  skip_if(cpl_propertylist_append_double(qclist, "ESO QC FPNOISE", fp_noise));
403  skip_if(cpl_propertylist_append_double(qclist, "ESO QC LAMPFLUX",
404  lamp_flux));
405 
406  end_skip;
407 
408  if (cpl_error_get_code()) {
409  cpl_image_delete(aver);
410  aver = NULL;
411  }
412 
413  cpl_image_delete(image);
414  cpl_image_delete(diff);
415  cpl_image_delete(prev);
416  cpl_image_delete(image0);
417 
418  return aver;
419 }
420 
421 
422 /*----------------------------------------------------------------------------*/
430 /*----------------------------------------------------------------------------*/
431 static cpl_error_code naco_img_lampflat_qc(cpl_propertylist * qclist,
432  cpl_propertylist * paflist,
433  const irplib_framelist * rawframes)
434 {
435 
436  const cpl_propertylist * reflist
438  const char pafcopy[] = "^(" NACO_PFITS_REGEXP_LAMPFLAT_PAF ")$";
439 
440 
441  bug_if (0);
442 
443 
444  /* THE PAF FILE FOR QC PARAMETERS */
445  skip_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
446  0));
447  skip_if (cpl_propertylist_append(paflist, qclist));
448 
449  bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist, "^("
450  IRPLIB_PFITS_REGEXP_RECAL
451  ")$", 0));
452 
453  bug_if (irplib_pfits_set_airmass(qclist, rawframes));
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 }
cpl_frameset * irplib_frameset_cast(const irplib_framelist *self)
Create a CPL frameset from an irplib_framelist.
const char * naco_pfits_get_rom_name(const cpl_propertylist *self)
find out the read out mode name
Definition: naco_pfits.c:389
double naco_pfits_get_dit(const cpl_propertylist *self)
find out the DIT
Definition: naco_pfits.c:131
const char * naco_pfits_get_opti4_name(const cpl_propertylist *self)
find out the OPTI4.NAME key
Definition: naco_pfits.c:316
int naco_pfits_get_lamp2(const cpl_propertylist *self)
find out the INS.LAMP2.SET keyword
Definition: naco_pfits.c:256
cpl_error_code irplib_framelist_set_tag_all(irplib_framelist *self, const char *tag)
Set the tag of all frames in the list.
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: naco_dfs.c:62
cpl_error_code irplib_pfits_set_airmass(cpl_propertylist *self, const irplib_framelist *rawframes)
Update/Set the AIRMASS property.
Definition: irplib_pfits.c:373
const char * naco_pfits_get_opti7_name(const cpl_propertylist *self)
find out the OPTI7.NAME key
Definition: naco_pfits.c:329
const cpl_propertylist * irplib_framelist_get_propertylist_const(const irplib_framelist *self, int pos)
Get the propertylist of the specified frame in the framelist.
void irplib_framelist_empty(irplib_framelist *self)
Erase all frames from a framelist.
cpl_error_code irplib_dfs_save_image(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_image *image, cpl_type_bpp bpp, const char *recipe, const char *procat, const cpl_propertylist *applist, const char *remregexp, const char *pipe_id, const char *filename)
Save an image as a DFS-compliant pipeline product.
Definition: irplib_utils.c:208
cpl_error_code irplib_framelist_load_propertylist_all(irplib_framelist *self, int ind, const char *regexp, cpl_boolean invert)
Load the propertylists of all frames in the framelist.
irplib_framelist * irplib_framelist_extract(const irplib_framelist *self, const char *tag)
Extract the frames with the given tag from a framelist.
const cpl_frame * irplib_framelist_get_const(const irplib_framelist *self, int pos)
Get the specified frame from the framelist.
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
const char * naco_pfits_get_opti3_name(const cpl_propertylist *self)
find out the OPTI3.NAME key
Definition: naco_pfits.c:304
void irplib_framelist_delete(irplib_framelist *self)
Deallocate an irplib_framelist with its frames and properties.
cpl_error_code irplib_framelist_contains(const irplib_framelist *self, const char *key, cpl_type type, cpl_boolean is_equal, double fp_tol)
Verify that a property is present for all frames.
const char * naco_pfits_get_mode(const cpl_propertylist *self)
find out the mode name
Definition: naco_pfits.c:268
irplib_framelist * irplib_framelist_cast(const cpl_frameset *frameset)
Create an irplib_framelist from a cpl_framelist.
const char * naco_parameterlist_get_string(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO string parameter.
int irplib_framelist_get_size(const irplib_framelist *self)
Get the size of a framelist.
const char * naco_pfits_get_filter(const cpl_propertylist *self)
find out the filter
Definition: naco_pfits.c:167