IIINSTRUMENT Pipeline Reference Manual  6.2.2
isaac_img_twflat.c
1 /* $Id: isaac_img_twflat.c,v 1.45 2013-03-12 08:06:48 llundin Exp $
2  *
3  * This file is part of the ISAAC 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: 2013-03-12 08:06:48 $
24  * $Revision: 1.45 $
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 <string.h>
37 #include <math.h>
38 #include <cpl.h>
39 
40 #include "irplib_utils.h"
41 #include "irplib_flat.h"
42 
43 #include "isaac_utils.h"
44 #include "irplib_oddeven.h"
45 #include "isaac_pfits.h"
46 #include "isaac_dfs.h"
47 
48 /* FIXME: To be removed when CPL4.2 is available */
49 #define PRO_DATANCOM "ESO PRO DATANCOM"
50 
51 /*-----------------------------------------------------------------------------
52  Functions prototypes
53  -----------------------------------------------------------------------------*/
54 
55 static int isaac_img_twflat_create(cpl_plugin *);
56 static int isaac_img_twflat_exec(cpl_plugin *);
57 static int isaac_img_twflat_destroy(cpl_plugin *);
58 static int isaac_img_twflat(cpl_parameterlist *, cpl_frameset *);
59 static cpl_imagelist * isaac_img_twflat_reduce(cpl_frameset *, cpl_frameset *);
60 static int isaac_img_twflat_save(cpl_imagelist *, cpl_image *, int,
61  const cpl_frameset *, cpl_parameterlist *,
62  cpl_frameset *);
63 static int isaac_img_twflat_compare(const cpl_frame *, const cpl_frame *);
64 
65 /*-----------------------------------------------------------------------------
66  Static variables
67  -----------------------------------------------------------------------------*/
68 
69 static struct {
70  double low_thresh;
71  double high_thresh;
72  int nb_badpix;
73  double med_stdev;
74  double med_avg;
75  double med_min;
76  double med_max;
77  int prop_flag;
78  int bpm_flag;
79  int errmap_flag;
80  int intercept_flag;
81  double oddeven_ll_max;
82  double oddeven_lr_max;
83  double oddeven_ul_max;
84  double oddeven_ur_max;
85  double oddeven_ll_stdev;
86  double oddeven_lr_stdev;
87  double oddeven_ul_stdev;
88  double oddeven_ur_stdev;
89  double oddeven_ll_mean;
90  double oddeven_lr_mean;
91  double oddeven_ul_mean;
92  double oddeven_ur_mean;
93 } isaac_img_twflat_config;
94 
95 static char isaac_img_twflat_description[] =
96 "isaac_img_twflat -- ISAAC imaging flat-field creation from twillight images.\n"
97 "The files listed in the Set Of Frames (sof-file) must be tagged:\n"
98 "raw-file.fits "ISAAC_IMG_TWFLAT_RAW" or\n"
99 "raw-file.fits "ISAAC_IMG_TWFLAT_POL_RAW" or\n"
100 "dark-raw-file.fits "ISAAC_CALIB_DARK"\n";
101 
102 /*-----------------------------------------------------------------------------
103  Functions code
104  -----------------------------------------------------------------------------*/
105 
106 /*----------------------------------------------------------------------------*/
114 /*----------------------------------------------------------------------------*/
115 int cpl_plugin_get_info(cpl_pluginlist * list)
116 {
117  cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe));
118  cpl_plugin * plugin = &recipe->interface;
119 
120  cpl_plugin_init(plugin,
121  CPL_PLUGIN_API,
122  ISAAC_BINARY_VERSION,
123  CPL_PLUGIN_TYPE_RECIPE,
124  "isaac_img_twflat",
125  "Twillight flat recipe",
126  isaac_img_twflat_description,
127  "Lars Lundin",
128  PACKAGE_BUGREPORT,
130  isaac_img_twflat_create,
131  isaac_img_twflat_exec,
132  isaac_img_twflat_destroy);
133 
134  cpl_pluginlist_append(list, plugin);
135 
136  return 0;
137 }
138 
139 /*----------------------------------------------------------------------------*/
148 /*----------------------------------------------------------------------------*/
149 static int isaac_img_twflat_create(cpl_plugin * plugin)
150 {
151  cpl_recipe * recipe;
152  cpl_parameter * p;
153 
154  /* Get the recipe out of the plugin */
155  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
156  recipe = (cpl_recipe *)plugin;
157  else return CPL_ERROR_UNSPECIFIED;
158 
159  /* Create the parameters list in the cpl_recipe object */
160  recipe->parameters = cpl_parameterlist_new();
161 
162  /* Fill the parameters list */
163  /* --t */
164  p = cpl_parameter_new_value("isaac.isaac_img_twflat.thresholds",
165  CPL_TYPE_STRING,
166  "Low and high thresholds for the BPM",
167  "isaac.isaac_img_twflat",
168  "0.5,2.0");
169  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "t");
170  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
171  cpl_parameterlist_append(recipe->parameters, p);
172  /* --prop */
173  p = cpl_parameter_new_value("isaac.isaac_img_twflat.proport", CPL_TYPE_BOOL,
174  "flag to activate the proportional fit", "isaac.isaac_img_twflat",
175  FALSE);
176  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "prop");
177  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
178  cpl_parameterlist_append(recipe->parameters, p);
179 
180  /* --bpm */
181  p = cpl_parameter_new_value("isaac.isaac_img_twflat.bpm", CPL_TYPE_BOOL,
182  "flag to create the bad pixels map", "isaac.isaac_img_twflat",
183  TRUE);
184  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "bpm");
185  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
186  cpl_parameterlist_append(recipe->parameters, p);
187 
188  /* --errmap */
189  p = cpl_parameter_new_value("isaac.isaac_img_twflat.errmap", CPL_TYPE_BOOL,
190  "flag to create the error map", "isaac.isaac_img_twflat",
191  FALSE);
192  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "errmap");
193  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
194  cpl_parameterlist_append(recipe->parameters, p);
195 
196  /* --intercept */
197  p = cpl_parameter_new_value("isaac.isaac_img_twflat.intercept",
198  CPL_TYPE_BOOL, "flag to create the intercept image",
199  "isaac.isaac_img_twflat", FALSE);
200  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "intercept");
201  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
202  cpl_parameterlist_append(recipe->parameters, p);
203 
204  /* Return */
205  return 0;
206 }
207 
208 /*----------------------------------------------------------------------------*/
214 /*----------------------------------------------------------------------------*/
215 static int isaac_img_twflat_exec(cpl_plugin * plugin)
216 {
217  cpl_recipe * recipe;
218 
219  /* Get the recipe out of the plugin */
220  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
221  recipe = (cpl_recipe *)plugin;
222  else return CPL_ERROR_UNSPECIFIED;
223 
224  return isaac_img_twflat(recipe->parameters, recipe->frames);
225 }
226 
227 /*----------------------------------------------------------------------------*/
233 /*----------------------------------------------------------------------------*/
234 static int isaac_img_twflat_destroy(cpl_plugin * plugin)
235 {
236  cpl_recipe * recipe;
237 
238  /* Get the recipe out of the plugin */
239  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
240  recipe = (cpl_recipe *)plugin;
241  else return CPL_ERROR_UNSPECIFIED;
242 
243  cpl_parameterlist_delete(recipe->parameters);
244  return 0;
245 }
246 
247 /*----------------------------------------------------------------------------*/
254 /*----------------------------------------------------------------------------*/
255 static int isaac_img_twflat(
256  cpl_parameterlist * parlist,
257  cpl_frameset * framelist)
258 {
259  const char * sval;
260  cpl_parameter * par;
261  cpl_size * labels;
262  cpl_size nlabels;
263  cpl_frameset * flatframes;
264  cpl_frameset * darkframes;
265  cpl_frameset * flat_one;
266  cpl_frameset * dark_one;
267  int ndarks;
268  cpl_imagelist * twflat;
269  cpl_mask * bpm;
270  cpl_image * bpm_im;
271  cpl_boolean did_reduce = CPL_FALSE;
272  int i;
273 
274  /* Initialise */
275  par = NULL;
276  bpm_im = NULL;
277  isaac_img_twflat_config.nb_badpix = -1;
278 
279  /* Retrieve input parameters */
280  /* --t */
281  par = cpl_parameterlist_find(parlist, "isaac.isaac_img_twflat.thresholds");
282  sval = cpl_parameter_get_string(par);
283  if (sscanf(sval, "%lg,%lg",
284  &isaac_img_twflat_config.low_thresh,
285  &isaac_img_twflat_config.high_thresh)!=2) {
286  return CPL_ERROR_UNSPECIFIED;
287  }
288  /* --prop */
289  par = cpl_parameterlist_find(parlist, "isaac.isaac_img_twflat.proport");
290  isaac_img_twflat_config.prop_flag = cpl_parameter_get_bool(par);
291  /* --bpm */
292  par = cpl_parameterlist_find(parlist, "isaac.isaac_img_twflat.bpm");
293  isaac_img_twflat_config.bpm_flag = cpl_parameter_get_bool(par);
294  /* --errmap */
295  par = cpl_parameterlist_find(parlist, "isaac.isaac_img_twflat.errmap");
296  isaac_img_twflat_config.errmap_flag = cpl_parameter_get_bool(par);
297  /* --intercept */
298  par = cpl_parameterlist_find(parlist, "isaac.isaac_img_twflat.intercept");
299  isaac_img_twflat_config.intercept_flag = cpl_parameter_get_bool(par);
300 
301  /* Identify the RAW and CALIB frames in the input frameset */
302  if (isaac_dfs_set_groups(framelist)) {
303  cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames");
304  return CPL_ERROR_UNSPECIFIED;
305  }
306 
307  /* Retrieve raw frames */
308  if ((flatframes = isaac_extract_frameset(framelist,
309  ISAAC_IMG_TWFLAT_RAW)) != NULL) {
310  } else if ((flatframes = isaac_extract_frameset(framelist,
311  ISAAC_IMG_TWFLAT_POL_RAW)) != NULL) {
312  } else {
313  cpl_msg_error(cpl_func, "Cannot find flat frames in the input list");
314  return CPL_ERROR_UNSPECIFIED;
315  }
316  darkframes = isaac_extract_frameset(framelist, ISAAC_CALIB_DARK);
317 
318  /* If dark frames are provided - check their number */
319  if (darkframes != NULL) {
320  ndarks = cpl_frameset_get_size(darkframes);
321  if ((ndarks != 1) && (cpl_frameset_get_size(flatframes) != ndarks)) {
322  cpl_msg_error(cpl_func, "Invalid number of dark frames submitted");
323  cpl_frameset_delete(flatframes);
324  cpl_frameset_delete(darkframes);
325  return CPL_ERROR_UNSPECIFIED;
326  }
327  }
328 
329  /* Labelise all input frames */
330  labels = cpl_frameset_labelise(flatframes, isaac_img_twflat_compare,
331  &nlabels);
332  if (labels == NULL) {
333  cpl_msg_error(cpl_func, "Cannot labelise input frames");
334  cpl_frameset_delete(flatframes);
335  if (darkframes) cpl_frameset_delete(darkframes);
336  return CPL_ERROR_UNSPECIFIED;
337  }
338 
339  /* Extract settings and reduce each of them */
340  for (i=0; i<nlabels; i++) {
341  /* Reduce data set nb i */
342  cpl_msg_info(cpl_func, "Reduce data set no %d out of %d", i+1,
343  (int)nlabels);
344  cpl_msg_indent_more();
345  flat_one = cpl_frameset_extract(flatframes, labels, i);
346  dark_one = NULL;
347  if (darkframes) dark_one = cpl_frameset_extract(darkframes, labels, i);
348  twflat = isaac_img_twflat_reduce(flat_one, dark_one);
349  cpl_msg_indent_less();
350 
351  /* Save the products */
352  cpl_msg_info(cpl_func, "Save the products");
353  cpl_msg_indent_more();
354  if (twflat == NULL) {
355  cpl_msg_warning(cpl_func, "Cannot reduce set nb %d", i+1);
356  } else {
357  /* Create the Bad pixels map */
358  if (isaac_img_twflat_config.bpm_flag) {
359  if ((bpm = cpl_mask_threshold_image_create(
360  cpl_imagelist_get(twflat, 0),
361  isaac_img_twflat_config.low_thresh,
362  isaac_img_twflat_config.high_thresh)) == NULL) {
363  cpl_msg_warning(cpl_func, "Cannot create bad pixels map");
364  } else {
365  cpl_mask_not(bpm);
366  isaac_img_twflat_config.nb_badpix = cpl_mask_count(bpm);
367  bpm_im = cpl_image_new_from_mask(bpm);
368  cpl_mask_delete(bpm);
369  }
370  }
371  isaac_img_twflat_save(twflat, bpm_im, i+1, flat_one, parlist,
372  framelist);
373  if (bpm_im) cpl_image_delete(bpm_im);
374  cpl_imagelist_delete(twflat);
375  if (!cpl_error_get_code()) did_reduce = CPL_TRUE;
376  }
377  cpl_msg_indent_less();
378  cpl_frameset_delete(flat_one);
379  if (dark_one) cpl_frameset_delete(dark_one);
380  }
381 
382  /* Free and return */
383  cpl_frameset_delete(flatframes);
384  if (darkframes) cpl_frameset_delete(darkframes);
385  cpl_free(labels);
386 
387  cpl_ensure_code(did_reduce, CPL_ERROR_ILLEGAL_INPUT);
388 
389  return cpl_error_set_where(cpl_func); /* Propagate error, if any */
390 }
391 
392 /*----------------------------------------------------------------------------*/
403 /*----------------------------------------------------------------------------*/
404 static cpl_imagelist * isaac_img_twflat_reduce(
405  cpl_frameset * flatframes,
406  cpl_frameset * darkframes)
407 {
408  cpl_frame * frame;
409  cpl_propertylist * plist;
410  const char * sval;
411  cpl_image * flat_image;
412  cpl_imagelist * in,
413  * dark,
414  * results;
415  cpl_stats * stats_ima;
416  cpl_vector * medians;
417  double gradient;
418  double norm;
419  int nima;
420  cpl_vector * reve_ll;
421  cpl_vector * reve_lr;
422  cpl_vector * reve_ul;
423  cpl_vector * reve_ur;
424  double ll, lr, ul, ur;
425  int i;
426 
427  /* Test entries */
428  if (flatframes == NULL) return NULL;
429 
430  /* Initialise */
431  nima = cpl_frameset_get_size(flatframes);
432 
433  /* Check the error status */
434  if (cpl_error_get_code()) return NULL;
435 
436  /* Print out the filter and the read-out mode */
437  frame = cpl_frameset_get_position(flatframes, 0);
438  plist=cpl_propertylist_load(cpl_frame_get_filename(frame), 0);
439  sval = isaac_pfits_get_filter(plist);
440  if (cpl_error_get_code()) {
441  cpl_msg_error(cpl_func, "Cannot get the filter or ROM or TPL.ID");
442  cpl_propertylist_delete(plist);
443  return NULL;
444  }
445  cpl_msg_info(cpl_func, "Filter: [%s]", sval);
446  cpl_propertylist_delete(plist);
447 
448  /* Load input image set */
449  cpl_msg_info(cpl_func, "---> Loading input set");
450  if ((in = cpl_imagelist_load_frameset(flatframes, CPL_TYPE_FLOAT, 1,
451  0)) == NULL) {
452  cpl_msg_error(cpl_func, "Cannot load the image set");
453  return NULL;
454  }
455 
456  /* Compute some stats on input images */
457  cpl_msg_info(cpl_func, "---> Computing stats");
458  cpl_msg_info(cpl_func, "image min max med rms");
459  cpl_msg_info(cpl_func, "---------------------------------------------");
460  medians = cpl_vector_new(nima);
461  for (i=0; i<nima; i++) {
462  stats_ima = cpl_stats_new_from_image(cpl_imagelist_get(in, i),
463  CPL_STATS_ALL);
464  if (stats_ima == NULL) {
465  cpl_msg_error(cpl_func, "Cannot compute stats on image %d", i+1);
466  cpl_imagelist_delete(in);
467  cpl_vector_delete(medians);
468  return NULL;
469  }
470  cpl_vector_set(medians, i, cpl_stats_get_median(stats_ima));
471  cpl_msg_info(cpl_func, "%02d %10.2f %10.2f %10.2f %10.2f",
472  i+1,
473  cpl_stats_get_min(stats_ima),
474  cpl_stats_get_max(stats_ima),
475  cpl_stats_get_median(stats_ima),
476  cpl_stats_get_stdev(stats_ima));
477  if (cpl_stats_get_median(stats_ima) < 1e-6) {
478  cpl_msg_error(cpl_func, "image %d has negative flux: aborting",
479  i+1);
480  cpl_imagelist_delete(in);
481  cpl_vector_delete(medians);
482  cpl_stats_delete(stats_ima);
483  return NULL;
484  }
485  cpl_stats_delete(stats_ima);
486  }
487  cpl_msg_info(cpl_func, "---------------------------------------------");
488 
489  /* Compute min max stdev and mean of the medians */
490  isaac_img_twflat_config.med_min = cpl_vector_get_min(medians);
491  isaac_img_twflat_config.med_max = cpl_vector_get_max(medians);
492  isaac_img_twflat_config.med_avg = cpl_vector_get_mean(medians);
493  isaac_img_twflat_config.med_stdev = cpl_vector_get_stdev(medians);
494  cpl_vector_delete(medians);
495 
496  /* Apply dark correction to all planes if requested */
497  if (darkframes) {
498  cpl_msg_info(cpl_func, "---> Subtracting dark");
499  /* Load dark cube */
500  if ((dark = cpl_imagelist_load_frameset(darkframes, CPL_TYPE_FLOAT, 1,
501  0)) == NULL) {
502  cpl_msg_error(cpl_func, "Cannot load the darks set");
503  cpl_imagelist_delete(in);
504  return NULL;
505  }
506  /* Dark correction */
507  if (cpl_imagelist_get_size(dark) == 1) {
508  cpl_imagelist_subtract_image(in, cpl_imagelist_get(dark, 0));
509  } else {
510  cpl_imagelist_subtract(in, dark);
511  }
512  cpl_imagelist_delete(dark);
513 
514  /* With the darks provided, the proportional method is used */
515  cpl_msg_info(cpl_func, "switching to proportional fit");
516  isaac_img_twflat_config.prop_flag = 1;
517  }
518 
519  /* See if flux gradient is large enough for a correct fit */
520  if (!isaac_img_twflat_config.prop_flag) {
521  gradient=fabs(isaac_img_twflat_config.med_max/
522  isaac_img_twflat_config.med_min);
523  if (gradient < 4.0) {
524  cpl_msg_warning(cpl_func, "low flux gradient: %g", gradient);
525  cpl_msg_warning(cpl_func,"a proportional fit may give better ");
526  cpl_msg_warning(cpl_func,"results (requires a master dark frame)");
527  }
528  }
529 
530  /* Monitor the odd/even column effect */
531  cpl_msg_info(cpl_func, "---> Monitor odd/even column effect");
532  reve_ll = cpl_vector_new(nima);
533  reve_lr = cpl_vector_new(nima);
534  reve_ul = cpl_vector_new(nima);
535  reve_ur = cpl_vector_new(nima);
536  for (i=0; i<nima; i++) {
537  irplib_oddeven_monitor(cpl_imagelist_get(in, i), 1, &ll);
538  irplib_oddeven_monitor(cpl_imagelist_get(in, i), 2, &lr);
539  irplib_oddeven_monitor(cpl_imagelist_get(in, i), 3, &ul);
540  irplib_oddeven_monitor(cpl_imagelist_get(in, i), 4, &ur);
541  cpl_vector_set(reve_ll, i, ll);
542  cpl_vector_set(reve_lr, i, lr);
543  cpl_vector_set(reve_ul, i, ul);
544  cpl_vector_set(reve_ur, i, ur);
545  }
546  isaac_img_twflat_config.oddeven_ll_max = cpl_vector_get_max(reve_ll);
547  isaac_img_twflat_config.oddeven_lr_max = cpl_vector_get_max(reve_lr);
548  isaac_img_twflat_config.oddeven_ul_max = cpl_vector_get_max(reve_ul);
549  isaac_img_twflat_config.oddeven_ur_max = cpl_vector_get_max(reve_ur);
550  isaac_img_twflat_config.oddeven_ll_stdev = cpl_vector_get_stdev(reve_ll);
551  isaac_img_twflat_config.oddeven_lr_stdev = cpl_vector_get_stdev(reve_lr);
552  isaac_img_twflat_config.oddeven_ul_stdev = cpl_vector_get_stdev(reve_ul);
553  isaac_img_twflat_config.oddeven_ur_stdev = cpl_vector_get_stdev(reve_ur);
554  isaac_img_twflat_config.oddeven_ll_mean = cpl_vector_get_mean(reve_ll);
555  isaac_img_twflat_config.oddeven_lr_mean = cpl_vector_get_mean(reve_lr);
556  isaac_img_twflat_config.oddeven_ul_mean = cpl_vector_get_mean(reve_ul);
557  isaac_img_twflat_config.oddeven_ur_mean = cpl_vector_get_mean(reve_ur);
558  cpl_vector_delete(reve_ll);
559  cpl_vector_delete(reve_lr);
560  cpl_vector_delete(reve_ul);
561  cpl_vector_delete(reve_ur);
562 
563  /* Fit slopes, get results */
564  cpl_msg_info(cpl_func, "---> Fitting slopes");
565  if (isaac_img_twflat_config.prop_flag) {
566  results = irplib_flat_fit_set(in, 0);
567  if (results == NULL) {
568  cpl_msg_error(cpl_func, "creating twilight flat-field: aborting");
569  cpl_imagelist_delete(in);
570  return NULL;
571  }
572  } else {
573  results = irplib_flat_fit_set(in, 1);
574  if (results == NULL) {
575  cpl_msg_error(cpl_func, "creating twilight flat-field: aborting");
576  cpl_imagelist_delete(in);
577  return NULL;
578  }
579  }
580  cpl_imagelist_delete(in);
581 
582  /* Normalize gain */
583  flat_image = cpl_imagelist_get(results, 0);
584  norm = cpl_image_get_mean(flat_image);
585  cpl_image_divide_scalar(flat_image, norm);
586  if (cpl_error_get_code()) {
587  cpl_imagelist_delete(results);
588  return NULL;
589  }
590 
591  return results;
592 }
593 
594 /*----------------------------------------------------------------------------*/
604 /*----------------------------------------------------------------------------*/
605 static int isaac_img_twflat_save(
606  cpl_imagelist * flat,
607  cpl_image * bpm,
608  int set_nb,
609  const cpl_frameset * set,
610  cpl_parameterlist * parlist,
611  cpl_frameset * set_tot)
612 {
613  const cpl_size nframes = cpl_frameset_get_size(set);
614  cpl_propertylist * plist;
615  cpl_propertylist * paflist;
616  cpl_propertylist * qclist;
617  const cpl_frame * ref_frame;
618  char * filename;
619  const char * sval;
620  int nima, file_id;
621  int nraw;
622 
623  /* Initialise */
624  nima = cpl_imagelist_get_size(flat);
625  if (nima != 2 && nima != 3) return CPL_ERROR_UNSPECIFIED;
626 
627  /* Get the QC params in qclist */
628  qclist = cpl_propertylist_new();
629 
630  /* Get the reference frame */
631  ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
632  if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
633  0)) == NULL) {
634  cpl_msg_error(cpl_func, "getting header from reference frame");
635  cpl_propertylist_delete(qclist);
636  return CPL_ERROR_UNSPECIFIED;
637  }
638  /* Test the status */
639  if (cpl_error_get_code()) {
640  cpl_propertylist_delete(qclist);
641  cpl_propertylist_delete(plist);
642  return CPL_ERROR_UNSPECIFIED;
643  }
644  /* Add FILTER */
645  sval = isaac_pfits_get_filter(plist);
646  if (cpl_error_get_code()) cpl_error_reset();
647  else cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS", sval);
648  /* Add OBJECTIVE */
649  sval = isaac_pfits_get_objective(plist);
650  if (cpl_error_get_code()) cpl_error_reset();
651  else cpl_propertylist_append_string(qclist, "ESO QC OBJECTIVE", sval);
652  cpl_propertylist_delete(plist);
653  cpl_propertylist_append_double(qclist, "ESO QC TWFLAT MEDMIN",
654  isaac_img_twflat_config.med_min);
655  cpl_propertylist_append_double(qclist, "ESO QC TWFLAT MEDMAX",
656  isaac_img_twflat_config.med_max);
657  cpl_propertylist_append_double(qclist, "ESO QC TWFLAT MEDAVG",
658  isaac_img_twflat_config.med_avg);
659  cpl_propertylist_append_double(qclist, "ESO QC TWFLAT MEDSTDEV",
660  isaac_img_twflat_config.med_stdev);
661  if (isaac_img_twflat_config.nb_badpix >=0 ) {
662  cpl_propertylist_append_int(qclist, "ESO QC TWFLAT NBADPIX",
663  isaac_img_twflat_config.nb_badpix);
664  }
665  cpl_propertylist_append_int(qclist, "ESO QC TWFLAT NFRAMES",
666  nframes);
667  cpl_propertylist_append_double(qclist, "ESO QC ODDEVEN LLMAX",
668  isaac_img_twflat_config.oddeven_ll_max);
669  cpl_propertylist_append_double(qclist, "ESO QC ODDEVEN LLMEAN",
670  isaac_img_twflat_config.oddeven_ll_mean);
671  cpl_propertylist_append_double(qclist, "ESO QC ODDEVEN LLSTDEV",
672  isaac_img_twflat_config.oddeven_ll_stdev);
673  cpl_propertylist_append_double(qclist, "ESO QC ODDEVEN LRMAX",
674  isaac_img_twflat_config.oddeven_lr_max);
675  cpl_propertylist_append_double(qclist, "ESO QC ODDEVEN LRMEAN",
676  isaac_img_twflat_config.oddeven_lr_mean);
677  cpl_propertylist_append_double(qclist, "ESO QC ODDEVEN LRSTDEV",
678  isaac_img_twflat_config.oddeven_lr_stdev);
679  cpl_propertylist_append_double(qclist, "ESO QC ODDEVEN ULMAX",
680  isaac_img_twflat_config.oddeven_ul_max);
681  cpl_propertylist_append_double(qclist, "ESO QC ODDEVEN ULMEAN",
682  isaac_img_twflat_config.oddeven_ul_mean);
683  cpl_propertylist_append_double(qclist, "ESO QC ODDEVEN ULSTDEV",
684  isaac_img_twflat_config.oddeven_ul_stdev);
685  cpl_propertylist_append_double(qclist, "ESO QC ODDEVEN URMAX",
686  isaac_img_twflat_config.oddeven_ur_max);
687  cpl_propertylist_append_double(qclist, "ESO QC ODDEVEN URMEAN",
688  isaac_img_twflat_config.oddeven_ur_mean);
689  cpl_propertylist_append_double(qclist, "ESO QC ODDEVEN URSTDEV",
690  isaac_img_twflat_config.oddeven_ur_stdev);
691 
692  /* Write the flat image */
693  filename = cpl_sprintf("isaac_img_twflat_set%02d.fits", set_nb);
694  irplib_dfs_save_image(set_tot,
695  parlist,
696  set,
697  cpl_imagelist_get(flat, 0),
698  CPL_BPP_IEEE_FLOAT,
699  "isaac_img_twflat",
700  ISAAC_IMG_TWFLAT_RES,
701  qclist,
702  NULL,
703  PACKAGE "/" PACKAGE_VERSION,
704  filename);
705  cpl_free(filename);
706 
707  /* Write the bpm image */
708  if (bpm) {
709  filename = cpl_sprintf("isaac_img_twflat_set%02d_bpm.fits", set_nb);
710  irplib_dfs_save_image(set_tot,
711  parlist,
712  set,
713  bpm,
714  CPL_BPP_IEEE_FLOAT,
715  "isaac_img_twflat",
716  ISAAC_IMG_TWFLAT_BPM,
717  qclist,
718  NULL,
719  PACKAGE "/" PACKAGE_VERSION,
720  filename);
721  cpl_free(filename);
722  }
723 
724  /* Write the intercept image */
725  if (isaac_img_twflat_config.intercept_flag && nima == 3) {
726  filename = cpl_sprintf("isaac_img_twflat_set%02d_inter.fits",set_nb);
727  irplib_dfs_save_image(set_tot,
728  parlist,
729  set,
730  cpl_imagelist_get(flat, 1),
731  CPL_BPP_IEEE_FLOAT,
732  "isaac_img_twflat",
733  ISAAC_IMG_TWFLAT_INTERC,
734  qclist,
735  NULL,
736  PACKAGE "/" PACKAGE_VERSION,
737  filename);
738  cpl_free(filename);
739  }
740 
741  /* Write the error map image */
742  if (isaac_img_twflat_config.errmap_flag) {
743  if (nima == 2) file_id = 1;
744  else file_id = 2;
745  filename=cpl_sprintf("isaac_img_twflat_set%02d_errmap.fits", set_nb);
746  irplib_dfs_save_image(set_tot,
747  parlist,
748  set,
749  cpl_imagelist_get(flat, file_id),
750  CPL_BPP_IEEE_FLOAT,
751  "isaac_img_twflat",
752  ISAAC_IMG_TWFLAT_ERR,
753  qclist,
754  NULL,
755  PACKAGE "/" PACKAGE_VERSION,
756  filename);
757  cpl_free(filename);
758  }
759 
760  /* Get FITS header from reference file */
761  if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
762  0)) == NULL) {
763  cpl_msg_error(cpl_func, "getting header from reference frame");
764  cpl_propertylist_delete(qclist);
765  return CPL_ERROR_UNSPECIFIED;
766  }
767 
768  /* Get the keywords for the paf file */
769  paflist = cpl_propertylist_new();
770  cpl_propertylist_copy_property_regexp(paflist, plist,
771  "^(DATE-OBS|ESO DET CHIP NAME|ARCFILE|ESO TPL ID|ESO DET MODE NAME|"
772  "ESO DET NCORRS NAME|ESO DET RSPEED|ESO DET DIT)$", 0);
773  cpl_propertylist_delete(plist);
774 
775 
776  /* Add PRO.DATANCOM keyword (DFS05421) */
777  nraw = 0;
778  for (cpl_size i = 0; i < nframes; i++) {
779  const cpl_frame* iframe = cpl_frameset_get_position_const(set, i);
780  if (cpl_frame_get_group(iframe) == CPL_FRAME_GROUP_RAW) nraw++;
781  }
782 
783  if (!cpl_propertylist_has(paflist, PRO_DATANCOM)) {
784  cpl_propertylist_update_int(paflist, PRO_DATANCOM, nraw);
785  cpl_propertylist_set_comment(paflist, PRO_DATANCOM,
786  "Number of combined frames");
787  }
788  /* The above piece of code regarding DFS05421 has been partially copied
789  from cpl_dfs.c as a workaround for that request until PAF files are
790  completely deprecated (which is planned for the long term). */
791 
792  /* Copy the QC in paflist */
793  cpl_propertylist_copy_property_regexp(paflist, qclist, ".", 0);
794  cpl_propertylist_delete(qclist);
795 
796  /* PRO.CATG */
797  cpl_propertylist_update_string(paflist, CPL_DFS_PRO_CATG,
798  ISAAC_IMG_TWFLAT_RES);
799 
800  /* Save the PAF file */
801  filename = cpl_sprintf("isaac_img_twflat_set%02d.paf", set_nb);
802  cpl_dfs_save_paf("ISAAC",
803  "isaac_img_twflat",
804  paflist,
805  filename);
806  cpl_free(filename);
807  cpl_propertylist_delete(paflist);
808  return 0;
809 }
810 
811 /*----------------------------------------------------------------------------*/
818 /*----------------------------------------------------------------------------*/
819 static int isaac_img_twflat_compare(
820  const cpl_frame * frame1,
821  const cpl_frame * frame2)
822 {
823  int comparison;
824  cpl_propertylist * plist1;
825  cpl_propertylist * plist2;
826  const char * sval1,
827  * sval2;
828 
829  /* Test entries */
830  if (frame1==NULL || frame2==NULL) return CPL_ERROR_UNSPECIFIED;
831 
832  /* Get property lists */
833  if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),
834  0)) == NULL) {
835  cpl_msg_error(cpl_func, "getting header from reference frame");
836  return CPL_ERROR_UNSPECIFIED;
837  }
838  if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),
839  0)) == NULL) {
840  cpl_msg_error(cpl_func, "getting header from reference frame");
841  cpl_propertylist_delete(plist1);
842  return CPL_ERROR_UNSPECIFIED;
843  }
844 
845  /* Test status */
846  if (cpl_error_get_code()) {
847  cpl_propertylist_delete(plist1);
848  cpl_propertylist_delete(plist2);
849  return CPL_ERROR_UNSPECIFIED;
850  }
851 
852  comparison = 1;
853 
854  /* Compare filters */
855  sval1 = isaac_pfits_get_filter(plist1);
856  sval2 = isaac_pfits_get_filter(plist2);
857  if (cpl_error_get_code()) {
858  cpl_msg_error(cpl_func, "cannot get the filter");
859  cpl_propertylist_delete(plist1);
860  cpl_propertylist_delete(plist2);
861  return CPL_ERROR_UNSPECIFIED;
862  }
863  if (strcmp(sval1, sval2)) comparison = 0;
864 
865  cpl_propertylist_delete(plist1);
866  cpl_propertylist_delete(plist2);
867  return comparison;
868 }
869 
870 
int isaac_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: isaac_dfs.c:60
const char * isaac_pfits_get_objective(const cpl_propertylist *plist)
find out the objective
Definition: isaac_pfits.c:642
const char * isaac_pfits_get_filter(const cpl_propertylist *plist)
find out the filter
Definition: isaac_pfits.c:880
cpl_frameset * isaac_extract_frameset(const cpl_frameset *self, const char *tag)
Extract the frames with the given tag from a frameset.
Definition: isaac_utils.c:356
const char * isaac_get_license(void)
Get the pipeline copyright and license.
Definition: isaac_utils.c:62