OMEGA Pipeline Reference Manual  1.0.5
omega_fringes_flat.c
1 /* $Id: omega_fringes_flat.c,v 1.2 2012-01-12 12:05:09 agabasch Exp $
2  *
3  * This file is part of the OMEGA 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: agabasch $
23  * $Date: 2012-01-12 12:05:09 $
24  * $Revision: 1.2 $
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 "omega_recipe.h"
37 #include "omega_wcscor.h"
38 
63 /*-----------------------------------------------------------------------------
64  Functions prototypes
65  -----------------------------------------------------------------------------*/
66 
67 static int omega_fringes_flat_create(cpl_plugin *) ;
68 static int omega_fringes_flat_exec(cpl_plugin *) ;
69 static int omega_fringes_flat_destroy(cpl_plugin *) ;
70 static int omega_fringes_flat(cpl_frameset *, cpl_parameterlist *) ;
71 cpl_image *omega_fringes_flat_process(omega_fits *scifits, cpl_image *bias, cpl_image *flat,
72  cpl_image *bpm, cpl_parameterlist *pars, int ext);
73 
74 static int omega_fringes_load_calib(int ext);
75 static void omega_fringes_init(void);
76 static void omega_fringes_tidy(int level);
77 
78 
79 /* Input and Output structures */
80 static struct {
81  /* Inputs. Parameters */
82  int extnum;
83  int oc;
84 
85 }omega_fringes_config;
86 
87 static struct {
88 
89  /* Calib frames */
90  cpl_size *labels;
91  const cpl_frame *mbiasfr;
92  const cpl_frame *mflatfr;
93  const cpl_frame *bpmfr;
94  cpl_frameset *sciset;
95  omega_fits *scifits;
96 
97  /* Products */
98  cpl_image *bpm;
99  cpl_image *mbias;
100  cpl_image *mflat;
101  cpl_image *fringes;
102 
103 }ps;
104 
105 #define RECIPE "omega_fringes_flat"
106 
107 /*----------------------------------------------------------------------------*/
116 /*----------------------------------------------------------------------------*/
117 int cpl_plugin_get_info(cpl_pluginlist * list)
118 {
119  cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe)) ;
120  cpl_plugin * plugin = &recipe->interface ;
121 
122  cpl_plugin_init(plugin,
123  CPL_PLUGIN_API,
124  OMEGA_BINARY_VERSION,
125  CPL_PLUGIN_TYPE_RECIPE,
126  "omega_fringes_flat",
127  "OMEGA - Create Fringes Flat.",
128  "This recipe is used to create a Fringes Flat if the filter \n"
129  "requires it. The recipe always takes as input a list of at least 3 \n"
130  "science frames, a master bias and a master flat. In addition to these, \n"
131  "an optional Bad Pixels Map may be provided.",
132  "Sandra Castro",
133  "scastro@eso.org",
135  omega_fringes_flat_create,
136  omega_fringes_flat_exec,
137  omega_fringes_flat_destroy) ;
138 
139  cpl_pluginlist_append(list, plugin) ;
140 
141  return 0;
142 }
143 
144 /*----------------------------------------------------------------------------*/
153 /*----------------------------------------------------------------------------*/
154 static int omega_fringes_flat_create(cpl_plugin * plugin)
155 {
156  cpl_recipe * recipe;
157  cpl_parameter * p ;
158 
159  /* Do not create the recipe if an error code is already set */
160  if (cpl_error_get_code() != CPL_ERROR_NONE) {
161  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
162  cpl_func, __LINE__, cpl_error_get_where());
163  return (int)cpl_error_get_code();
164  }
165 
166  if (plugin == NULL) {
167  cpl_msg_error(cpl_func, "Null plugin");
168  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
169  }
170 
171  /* Verify plugin type */
172  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
173  cpl_msg_error(cpl_func, "Plugin is not a recipe");
174  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
175  }
176 
177  /* Get the recipe */
178  recipe = (cpl_recipe *)plugin;
179 
180  /* Create the parameters list in the cpl_recipe object */
181  recipe->parameters = cpl_parameterlist_new() ;
182  if (recipe->parameters == NULL) {
183  cpl_msg_error(cpl_func, "Parameter list allocation failed");
184  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
185  }
186 
187  /* Fill the parameters list */
188  p = cpl_parameter_new_value("omega.omega_fringes_flat.ExtensionNumber",
189  CPL_TYPE_INT,
190  "FITS extension number to load (1 to 32). (-1 == all)",
191  "omega_fringes_flat",
192  -1) ;
193 
194  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"ext") ;
195  cpl_parameterlist_append(recipe->parameters, p) ;
196 
197  p = cpl_parameter_new_range("omega.omega_fringes_flat.OverscanMethod",
198  CPL_TYPE_INT,
199  "Overscan Correction Method",
200  "omega_fringes_flat",
201  0, 0, 6);
202  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "oc-meth") ;
203  cpl_parameterlist_append(recipe->parameters, p) ;
204 
205  /* Return */
206  return 0;
207 }
208 
209 /*----------------------------------------------------------------------------*/
215 /*----------------------------------------------------------------------------*/
216 static int omega_fringes_flat_exec(cpl_plugin * plugin)
217 {
218  cpl_recipe * recipe;
219  int recipe_status;
220 
221  /* Return immediately if an error code is already set */
222  if (cpl_error_get_code() != CPL_ERROR_NONE) {
223  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
224  cpl_func, __LINE__, cpl_error_get_where());
225  return (int)cpl_error_get_code();
226  }
227 
228  if (plugin == NULL) {
229  cpl_msg_error(cpl_func, "Null plugin");
230  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
231  }
232 
233  /* Verify plugin type */
234  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
235  cpl_msg_error(cpl_func, "Plugin is not a recipe");
236  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
237  }
238 
239  /* Get the recipe */
240  recipe = (cpl_recipe *)plugin;
241 
242  /* Verify parameter and frame lists */
243  if (recipe->parameters == NULL) {
244  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
245  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
246  }
247  if (recipe->frames == NULL) {
248  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
249  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
250  }
251 
252  /* Invoke the recipe */
253  recipe_status = omega_fringes_flat(recipe->frames, recipe->parameters);
254 
255  /* Ensure DFS-compliance of the products */
256  if (cpl_dfs_update_product_header(recipe->frames)) {
257  if (!recipe_status) recipe_status = (int)cpl_error_get_code();
258  }
259 
260  return recipe_status;
261 }
262 
263 /*----------------------------------------------------------------------------*/
269 /*----------------------------------------------------------------------------*/
270 static int omega_fringes_flat_destroy(cpl_plugin * plugin)
271 {
272  cpl_recipe * recipe;
273 
274  if (plugin == NULL) {
275  cpl_msg_error(cpl_func, "Null plugin");
276  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
277  }
278 
279  /* Verify plugin type */
280  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
281  cpl_msg_error(cpl_func, "Plugin is not a recipe");
282  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
283  }
284 
285  /* Get the recipe */
286  recipe = (cpl_recipe *)plugin;
287 
288  cpl_parameterlist_delete(recipe->parameters) ;
289 
290  return 0 ;
291 }
292 
293 /*----------------------------------------------------------------------------*/
300 /*----------------------------------------------------------------------------*/
301 static int omega_fringes_flat(cpl_frameset *set, cpl_parameterlist *pars)
302 {
303 
304  int i,j,jst,jfn,isfirst;
305  cpl_size nlab;
306  int nraw = 0;
307  char *outfile = NULL;
308 
309  cpl_frame *sciframe, *product_frame;
310  cpl_parameter *par;
311  cpl_image *image;
312  cpl_imagelist *ilist;
313  cpl_propertylist *qclist;
314  cpl_stats *stats;
315 
316 
317  /*Start the recipe */
318  if (!pars) {
319  cpl_msg_error (cpl_func, "Parameters list not found");
320  return -1;
321  }
322 
323  if (cpl_frameset_is_empty(set) == 1) {
324  cpl_msg_error (cpl_func, "Frameset not found");
325  return -1;
326  }
327 
328  /* Retrieve input parameters */
329  par = cpl_parameterlist_find(pars, "omega.omega_fringes_flat.ExtensionNumber") ;
330  omega_fringes_config.extnum = cpl_parameter_get_int(par) ;
331 
332  /* Identify the RAW and CALIB frames in the input frameset */
333  if (oc_dfs_set_groups(set)) {
334  cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames") ;
335  return -1 ;
336  }
337 
338  /*Initialized things*/
339  omega_fringes_init();
340 
341  /* Verify the frameset contents. */
342  if ((ps.labels = cpl_frameset_labelise(set,omega_compare_tags,
343  &nlab)) == NULL) {
344  cpl_msg_error(cpl_func,"Cannot labelise the input frameset");
345  omega_fringes_tidy(0);
346  return -1;
347  }
348  if ((ps.sciset = omega_frameset_subgroup(set,ps.labels,nlab,
349  FRINGES_RAW)) == NULL) {
350  cpl_msg_error(cpl_func,"Cannot find fringes frames in input frameset");
351  omega_fringes_tidy(0);
352  return -1;
353  }
354 
355 
356  /* Verify the frameset contents. */
357  nraw = cpl_frameset_count_tags(ps.sciset, FRINGES_RAW);
358  if (nraw < 3) {
359  cpl_msg_error (cpl_func, "Need at least 3 (%s) frames to run "
360  "this recipe", FRINGES_RAW);
361  omega_fringes_tidy(0);
362  return -1;
363  }
364 
365  cpl_msg_info (cpl_func,"There are %d %s frames in frame set",nraw, FRINGES_RAW);
366 
367  /* Check for calibration frames */
368  /* Master Bias */
369  ps.mbiasfr = cpl_frameset_find_const(set, OMEGA_CALIB_BIAS);
370  if (ps.mbiasfr == NULL) {
371  cpl_msg_error(cpl_func,"Cannot find %s frame in frame set", OMEGA_CALIB_BIAS);
372  omega_fringes_tidy(0);
373  }
374  cpl_msg_info(cpl_func,"Using %s %s",OMEGA_CALIB_BIAS, cpl_frame_get_filename(ps.mbiasfr));
375 
376  /* Master Flat */
377  ps.mflatfr = cpl_frameset_find_const(set, OMEGA_CALIB_FLAT);
378  if(ps.mflatfr == NULL) {
379  cpl_msg_error(cpl_func,"Cannot find %s frame in frame set", OMEGA_CALIB_FLAT);
380  omega_fringes_tidy(0);
381  return -1;
382  }
383  cpl_msg_info(cpl_func,"Using %s %s", OMEGA_CALIB_FLAT, cpl_frame_get_filename(ps.mflatfr));
384 
385  /* Bad Pixels Map */
386  ps.bpmfr = cpl_frameset_find (set,OMEGA_CALIB_BPM);
387  if(ps.bpmfr != NULL)
388  cpl_msg_info(cpl_func,"Using %s %s",OMEGA_CALIB_BPM,cpl_frame_get_filename(ps.bpmfr));
389 
390  /* Get first frame from frame set */
391  sciframe = cpl_frameset_get_first(ps.sciset);
392 
393  /* Loop for each of the image extensions */
394  omega_extensions(sciframe, omega_fringes_config.extnum,&jst,&jfn);
395  if(omega_fringes_config.extnum == 0){
396  cpl_msg_error(cpl_func,"Unsupported extension request, %d",omega_fringes_config.extnum);
397  omega_fringes_tidy(0);
398  return -1;
399  }
400 
401  for (j = jst; j <= jfn; j++) {
402  isfirst = (j == jst);
403  cpl_msg_indent_more();
404  cpl_msg_info(cpl_func,".....Working on extension %d.....",j);
405  cpl_msg_indent_less();
406 
407  /* Load calibration frames */
408  if(omega_fringes_load_calib(j) != 0){
409  cpl_msg_error(cpl_func,"Cannot load calibration frame(s)");
410  freespace(outfile);
411  omega_fringes_tidy(0);
412  return -1;
413  }
414 
415  ilist = cpl_imagelist_new();
416 
417  sciframe = cpl_frameset_get_first(ps.sciset);
418  for(i = 0; i < nraw; i++) {
419  /* Load omega_fits structure for this extension */
420  ps.scifits = omega_fits_load(sciframe, CPL_TYPE_FLOAT, j);
421 
422  /* Call processing routine */
423  image = omega_fringes_flat_process(ps.scifits,ps.mbias,ps.mflat,ps.bpm, pars, j);
424  if(image == NULL){
425  cpl_msg_error(cpl_func,"Cannot reduce image %d of %d",i,nraw);
426  freespace(outfile);
427  freeilist(ilist);
428  omega_fringes_tidy(0);
429  return -1;
430  }
431 
432  cpl_imagelist_set(ilist, image,i);
433  sciframe = cpl_frameset_get_next(ps.sciset);
434  freefits(ps.scifits);
435  ps.scifits = NULL;
436 
437  }
438  ps.fringes = omega_fringes_create(ilist,ps.bpm,nraw);
439  freeilist(ilist);
440 
441  if(isfirst){
442  outfile = cpl_sprintf("%s_%s.fits", INSTRUME,FRINGES_PROCATG);
443  product_frame = omega_product_frame(outfile, FRINGES_PROCATG, CPL_FRAME_TYPE_IMAGE);
444  }
445 
446  stats = cpl_stats_new_from_image(ps.fringes, CPL_STATS_ALL);
447  qclist = cpl_propertylist_new();
448  cpl_propertylist_append_double(qclist, "HIERARCH ESO QC FRINGESMIN", cpl_stats_get_min(stats));
449  cpl_propertylist_append_double(qclist, "HIERARCH ESO QC FRINGESMAX", cpl_stats_get_max(stats));
450  cpl_propertylist_append_double(qclist, "HIERARCH ESO QC FRINGESMEAN", cpl_stats_get_mean(stats));
451  cpl_propertylist_append_double(qclist, "HIERARCH ESO QC FRINGESDEV", cpl_stats_get_stdev(stats));
452  cpl_propertylist_append_double(qclist, "HIERARCH ESO QC FRINGESMED", cpl_stats_get_median(stats));
453  freestats(stats);
454 
455  cpl_msg_info(cpl_func,"Saving Fringes Flat");
456  /* Save Fringes Flat */
457  if(omega_save_image(ps.fringes,set,pars,NULL,qclist,CPL_BPP_IEEE_FLOAT,outfile,
458  RECIPE,product_frame,NULL,isfirst) == -1){
459  cpl_msg_error(cpl_func,"Cannot save product %s",FRINGES_PROCATG);
460  freeplist(qclist);
461  freespace(outfile);
462  omega_fringes_tidy(0);
463  return -1;
464  }
465 
466  freeplist(qclist);
467  omega_fringes_tidy(1);
468  }
469 
470  freespace(outfile);
471  omega_fringes_tidy(0);
472 
473  return 0;
474 }
475 
488 cpl_image *omega_fringes_flat_process(omega_fits *scifits, cpl_image *mbias, cpl_image *mflat,
489  cpl_image *bpm, cpl_parameterlist *pars, int ext)
490 {
491  int oc = 0;
492 
493  cpl_image *fringes;
494  cpl_parameter *p;
495  cpl_propertylist *xlist;
496 
497  if((scifits == NULL) || (mbias == NULL) || (mflat == NULL) ||
498  (bpm == NULL))
499  return NULL;
500 
501  /* Get a few parameters */
502  p = cpl_parameterlist_find(pars, "omega.omega_fringes_flat.OverscanMethod") ;
503  omega_fringes_config.oc = cpl_parameter_get_int(p);
504 
505  /* Check overscan correction method consistency */
506  oc = omega_pfits_get_overscan(ps.mbiasfr, ext);
507  if(oc != omega_fringes_config.oc) {
508  cpl_msg_warning (cpl_func, "Overscan correction mode for Master Bias (oc = %d) differs from "
509  "the one used here (oc = %d)", oc, omega_fringes_config.oc);
510  }
511 
512  /* Trim and overscan correct all images */
513  if((fringes = omega_trim_oscan_correct(scifits, omega_fringes_config.oc)) == NULL){
514  cpl_msg_error(cpl_func,"Unable to trim image");
515  return NULL;
516  }
517 
518  /* Correct coordinates after trimming */
519  xlist = omega_fits_get_ehu(scifits);
520  omega_shift_refpix(omega_fits_get_frame(scifits), ext, xlist);
521 
522  /* Subtract the bias */
523  omega_biascor(fringes, mbias);
524 
525  /* Divide by the flat */
526  if(omega_flatcor(fringes, mflat, NULL) != 0){
527  cpl_msg_error(cpl_func,"Error in flat correction");
528  freeimage(fringes);
529  xlist = NULL;
530  return NULL;
531  }
532 
533  xlist = NULL;
534 
535  return fringes;
536 }
537 
538 static int omega_fringes_load_calib(int ext)
539 {
540 
541  /* Load mandatory calibration frames */
542  /* master bias */
543  ps.mbias = cpl_image_load(cpl_frame_get_filename(ps.mbiasfr), CPL_TYPE_FLOAT, 0, ext);
544  if(ps.mbias == NULL){
545  cpl_msg_error(cpl_func,"Cannot load Master Bias. %s", cpl_error_get_message());
546  return -1;
547  }
548  /* master flat */
549  ps.mflat = cpl_image_load(cpl_frame_get_filename(ps.mflatfr),CPL_TYPE_FLOAT,0,ext);
550  if (ps.mflat == NULL){
551  cpl_msg_error(cpl_func,"Cannot load Master Flat. %s",cpl_error_get_message());
552  return -1;
553  }
554 
555  /* Optional */
556  /* bad pixels map */
557  if(ps.bpmfr != NULL){
558  ps.bpm = cpl_image_load(cpl_frame_get_filename(ps.bpmfr), CPL_TYPE_INT, 0, ext);
559  if(ps.bpm == NULL)
560  cpl_msg_warning(cpl_func, "Cannot load BPM. %s", cpl_error_get_message());
561 
562  }
563 
564  return 0;
565 }
566 
567 /* Initialize the pointers */
568 static void omega_fringes_init(void)
569 {
570  ps.sciset = NULL;
571  ps.bpmfr = NULL;
572  ps.mbiasfr = NULL;
573  ps.mflatfr = NULL;
574  ps.scifits = NULL;
575  ps.labels = NULL;
576  ps.mbias = NULL;
577  ps.mflat = NULL;
578  ps.bpm = NULL;
579  ps.fringes = NULL;
580 }
581 
582 /*
583  * Free any allocated memory
584  */
585 static void omega_fringes_tidy(int level)
586 {
587  freeimage(ps.mbias);
588  freeimage(ps.mflat);
589  freeimage(ps.bpm);
590  freeimage(ps.fringes);
591  if(level == 1)
592  return;
593 
594  freeframeset(ps.sciset);
595  freespace(ps.labels);
596  freefits(ps.scifits);
597 }
598