UVES Pipeline Reference Manual  5.5.5b3
uves_reduce_mflat.c
1 /* *
2  * This file is part of the ESO UVES Pipeline *
3  * Copyright (C) 2004,2005 European Southern Observatory *
4  * *
5  * This library is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the Free Software *
17  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA *
18  * */
19 
20 /*
21  * $Author: amodigli $
22  * $Date: 2013-08-08 13:36:46 $
23  * $Revision: 1.53 $
24  */
25 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 /*----------------------------------------------------------------------------*/
35 /*----------------------------------------------------------------------------*/
40 /*-----------------------------------------------------------------------------
41  Includes
42  -----------------------------------------------------------------------------*/
43 #include <uves_reduce_mflat.h>
44 
45 #include <uves.h>
46 #include <uves_backsub.h>
47 #include <uves_chip.h>
48 #include <uves_dfs.h>
49 #include <uves_pfits.h>
50 #include <uves_parameters.h>
51 #include <uves_utils.h>
52 #include <uves_utils_wrappers.h>
53 #include <uves_qclog.h>
54 #include <uves_error.h>
55 #include <uves_msg.h>
56 
57 #include <cpl.h>
58 #include <float.h>
59 #include <string.h>
60 /*-----------------------------------------------------------------------------
61  Functions prototypes
62  -----------------------------------------------------------------------------*/
63 
64 static void uves_mflat_qclog(const cpl_imagelist* raw_images,
65  cpl_table* qclog);
66 
67 static cpl_error_code uves_msflats(cpl_frameset * set, const cpl_parameterlist *parameters,
68  const char *recipe_id,
69  const char *starttime);
70 static void uves_mflat_one(cpl_frameset *frames,
71  const cpl_parameterlist *parameters,
72  bool flames,
73  const char *recipe_id,
74  const char *starttime,
75  const char* prefix);
76 
77 static cpl_error_code
78 uves_mflat_at_ypos(cpl_frameset* set,
79  const cpl_parameterlist* parameters,
80  const char *recipe_id,
81  const char *starttime,
82  const cpl_frameset* raw,
83  const cpl_frameset* cdb,
84  const int ref_x1enc,
85  const int ref_x2enc,
86  const int set_no);
87 
88 static void uves_reduce_mflat(cpl_frameset *frames, const cpl_parameterlist *parameters,
89  bool flames,
90  const char *recipe_id,
91  const char *starttime,
92  const char *prefix);
93 
94 /*-----------------------------------------------------------------------------
95  Implementation
96  -----------------------------------------------------------------------------*/
97 const char * const uves_mflat_desc =
98 "This recipe creates a master flat frame by 1) subtracting the master bias\n"
99 "frame from each flat field frame, 2) dividing each flat field frame by the\n"
100 " exposure time for that frame, 3) taking the median of all bias subtracted,\n"
101 " normalized raw\n flat frames, 4) optionally subtracting the master dark \n"
102 "frame, and 5) subtracting\n the background to get the bias subtracted, \n"
103 "optionally dark subtracted, normalized, background subtracted master \n"
104 "flat-field frame. Symbolically,\n"
105 " masterflat = median( (flat_i - masterbias)/exptime_i ) - masterdark/exptime\n"
106 " - background.\n"
107 "\n"
108 "The input flat field frames must have same tag which must match\n"
109 "(I|D|S|T|SCREEN|)FLAT_(BLUE|RED), for example TFLAT_BLUE or FLAT_RED. Also, a\n"
110 "master bias (MASTER_BIAS_xxxx) and ordertable (ORDER_TABLE_xxxx) must be\n"
111 "provided for each chip (xxxx = BLUE, REDL, REDU). A master dark frame\n"
112 "(MASTER_(P)DARK_xxxx) may optionally be provided. On blue input the recipe\n"
113 "computes one master flat field frame; on red input the recipe produces a\n"
114 "master flat field frame for each chip (MASTER_FLAT_xxxx, MASTER_IFLAT_xxxx,\n"
115 "MASTER_DFLAT_xxxx, MASTER_TFLAT_xxxx or MASTER_SCREEN_FLAT_xxxx).";
116 
117 /*----------------------------------------------------------------------------*/
124 /*----------------------------------------------------------------------------*/
125 int
126 uves_mflat_define_parameters_body(cpl_parameterlist *parameters,
127  const char *recipe_id)
128 {
129 
130  cpl_parameter* p=NULL;
131  /*****************
132  * General *
133  *****************/
134  if (uves_define_global_parameters(parameters) != CPL_ERROR_NONE)
135  {
136  return -1;
137  }
138  if (uves_corr_traps_define_parameters(parameters,recipe_id)
139  != CPL_ERROR_NONE)
140  {
141  return -1;
142  }
143 
144  /**************************************
145  * Master stack generation *
146  **************************************/
147  if (uves_master_flat_define_parameters(parameters,recipe_id)
148  != CPL_ERROR_NONE)
149  {
150  return -1;
151  }
152 
153  if(strcmp(recipe_id,"flames_cal_mkmaster") ==0) {
154  check_nomsg(p=cpl_parameterlist_find(parameters,"flames_cal_mkmaster.norm_method"));
155  cpl_parameter_set_string(p,"exptime");
156  }
157  cleanup:
158 /*
159  if (uves_master_stack_define_parameters(parameters,recipe_id)
160  != CPL_ERROR_NONE)
161  {
162  return -1;
163  }
164 */
165 
166  /****************************
167  * Spline back.sub. *
168  ****************************/
169 
170  if (uves_propagate_parameters_step(UVES_BACKSUB_ID, parameters,
171  recipe_id, NULL) != 0)
172  {
173  return -1;
174  }
175 
176 
177 
178  return (cpl_error_get_code() != CPL_ERROR_NONE);
179 }
180 
181 /*----------------------------------------------------------------------------*/
219 /*----------------------------------------------------------------------------*/
220 static cpl_image *
221 uves_mflat_process_chip(const cpl_imagelist *raw_images,
222  uves_propertylist **raw_headers,
223  uves_propertylist *master_flat_header,
224  const cpl_image *master_bias,
225  const cpl_image *master_dark,
226  const uves_propertylist *mdark_header,
227  const cpl_table *ordertable,
228  const polynomial *order_locations,
229  bool flames,
230  const cpl_parameterlist *parameters,
231  enum uves_chip chip,
232  const char *recipe_id,
233  bool debug_mode,
234  cpl_image **background)
235 
236 {
237  cpl_image *master_flat = NULL; /* Result */
238  cpl_image *master_flat_tmp = NULL; /* Result */
239 
240  cpl_image *current_flat = NULL;
241 
242  int i;
243  const char* FLAT_METHOD=NULL;
244  cpl_vector* exptimes=NULL;
245  cpl_vector* gain_vals=NULL;
246  double mdark_exposure=0;
247  cpl_image* mdark_scaled=NULL;
248  double fnoise=0;
249  double gain=0;
250  cpl_imagelist *raw_images_local=NULL;
251 
252  /* First process each input image and store the results in a new image list */
253  /* Get recipe parameters */
254  check( uves_get_parameter(parameters, NULL, recipe_id, "norm_method",
255  CPL_TYPE_STRING, &FLAT_METHOD),
256  "Could not read parameter");
257  uves_string_toupper((char*)FLAT_METHOD);
258 
259  raw_images_local=(cpl_imagelist*) raw_images;
260  exptimes=cpl_vector_new(cpl_imagelist_get_size(raw_images));
261  gain_vals=cpl_vector_new(cpl_imagelist_get_size(raw_images));
262  /* to remove compiler warnings */
263  for (i = 0; i < cpl_imagelist_get_size(raw_images); i++)
264  {
265  double exposure_time = 0.0;
266 
267  const uves_propertylist *current_header = NULL;
268 
269  current_flat = cpl_image_duplicate(cpl_imagelist_get_const(raw_images, i));
270  current_header = raw_headers[i];
271 
272  /* Subtract master bias */
273  if (master_bias != NULL)
274  {
275  uves_msg("Subtracting master bias");
276  check( uves_subtract_bias(current_flat, master_bias),
277  "Error subtracting master bias");
278  }
279  else
280  {
281  uves_msg("Skipping bias subtraction");
282  }
283 
284  /* Normalize to unit exposure time: */
285  check( exposure_time = uves_pfits_get_exptime(current_header),
286  "Error reading exposure time");
287  check( gain = uves_pfits_get_gain(current_header,chip),
288  "Error reading gain value");
289 
290  uves_msg("Normalizing flat from %f s to unit exposure time", exposure_time);
291  check( cpl_image_divide_scalar(current_flat, exposure_time),
292  "Error normalizing flat field");
293  check( uves_pfits_set_exptime(master_flat_header, 1.0),
294  "Error writing master frame exposure time");
295  cpl_vector_set(exptimes,i,exposure_time);
296  cpl_vector_set(gain_vals,i,gain);
297 
298  /* Append to imagelist */
299  check( cpl_imagelist_set(raw_images_local, /* Image list */
300  current_flat, /* Image to insert */
301  i), /* Position (number_of_images=>append) */
302  "Could not insert image into image list");
303 
304  /* Don't deallocate the image. It will be deallocated when
305  the image list is deallocated */
306  current_flat = NULL;
307  }
308 
309  /* subtract master dark if present */
310  if (master_dark != NULL)
311  {
312  uves_msg("Subtracting master dark scaled to unit exposure time");
313  check_nomsg( mdark_exposure = uves_pfits_get_exptime(mdark_header));
314 
315  mdark_scaled=cpl_image_duplicate(master_dark);
316  cpl_image_divide_scalar(mdark_scaled,mdark_exposure);
317  check( cpl_imagelist_subtract_image(raw_images_local,mdark_scaled),
318  "Error subtracting master dark");
319  uves_free_image(&mdark_scaled);
320  }
321  else
322  {
323  uves_msg("Skipping dark subtraction");
324  }
325 
326 
327  /* Take median of all input flats */
328  if(strcmp(FLAT_METHOD,"EXPTIME")==0) {
329  uves_msg("Calculating stack median");
330  check(master_flat=cpl_imagelist_collapse_median_create(raw_images_local),
331  "Error computing median");
332  } else {
333  uves_msg("Calculating stack normalized master");
334  check( master_flat_tmp = uves_flat_create_normalized_master(raw_images_local,
335  ordertable,
336  order_locations,gain_vals,&fnoise),
337  "Error computing master flat with normalization");
338 
339  check( master_flat = uves_flat_create_normalized_master2(raw_images_local,
340  ordertable,
341  order_locations,
342  master_flat_tmp),
343  "Error computing master flat with normalization");
344  uves_free_image(&master_flat_tmp);
345  uves_propertylist_append_c_double(master_flat_header,UVES_FNOISE,fnoise,
346  "Master flat RMS on frame");
347 
348  }
349  /*clean mem and reset local pointers to null */
350  raw_images_local=NULL;
351  uves_free_vector(&exptimes);
352  uves_free_vector(&gain_vals);
353 
354  if (debug_mode && !flames)
355  {
356  check( uves_save_image_local("Pre-background subtracted master flat", "pre",
357  master_flat, chip, -1, -1, master_flat_header, true),
358  "Error saving image");
359  }
360 
361  /* Subtract background from master flat */
362  if (!flames)
363  {
364  uves_msg("Subtracting background");
365 
366  check( uves_backsub_spline(master_flat,
367  /* Info about chip (wavelength, ...) is
368  stored in any raw header,
369  so just pass the first one */
370  raw_headers[0],
371  ordertable, order_locations,
372  parameters, recipe_id,
373  chip,
374  true, /* Use flat-field parameters? */
375  background),
376  "Error subtracting background from master flat");
377  }
378  else
379  {
380  uves_msg("Skipping background subtraction");
381  }
382  uves_pfits_set_extname(master_flat_header,"Master flat");
383  cleanup:
384 
385 
386  uves_free_image(&current_flat);
387  if (cpl_error_get_code() != CPL_ERROR_NONE)
388  {
389  uves_free_image(&master_flat);
390  }
391 
392  return master_flat;
393 }
394 
395 /*----------------------------------------------------------------------------*/
407 /*----------------------------------------------------------------------------*/
408 void
409 uves_mflat_exe_body(cpl_frameset *frames,
410  const cpl_parameterlist *parameters,
411  const char *starttime,
412  const char *recipe_id)
413 {
414  /* Do FLAMES reduction if SFLAT frame is given */
415  if (cpl_frameset_find(frames, UVES_SFLAT(false)) != NULL) {
416 
417  check(uves_msflats(frames, parameters, recipe_id, starttime),
418  "find same sflats failed");
419  }
420  else {
421  bool flames = false;
422  check(uves_mflat_one(frames, parameters, flames, recipe_id,
423  starttime, ""),
424  "Master flat one failed");
425  }
426 
427  cleanup:
428  return;
429 }
430 
431 /*----------------------------------------------------------------------------*/
437 /*----------------------------------------------------------------------------*/
438 static cpl_error_code
439 uves_msflats(cpl_frameset * set, const cpl_parameterlist *parameters,
440  const char *recipe_id,
441  const char *starttime)
442 {
443  /* Pseudocode:
444  extract raw frames from set
445  extract cdb frames from set
446  identifies how many different Y position we have
447  for each Y pos:
448  extract from the raw_set the raw frames corresponding to each Y pos
449  merge in a new wrk_set the cdb_set
450  computes the corresponding master flat
451  put the products in the final set
452  endfor
453  */
454  cpl_frameset* raw=NULL;
455  cpl_frameset* cdb=NULL;
456  cpl_frameset* pro=NULL;
457  int status=0;
458  int x1enc=0;
459  int x2enc=0;
460 
461  cpl_table* encoder_tbl=NULL;
462  int nset=0;
463  int i=0;
464 
465  //Extracts SFLAT raw frames
466  check(raw=uves_frameset_extract(set,UVES_SFLAT(false)),
467  "Extract %s frames failed",
468  UVES_SFLAT(false));
469 
470  check(uves_extract_frames_group_type(set,&cdb,CPL_FRAME_GROUP_CALIB),
471  "Extract cdb frames failed");
472  check(uves_sflats_get_encoder_steps(raw,&encoder_tbl,&nset),
473  "Get encoder steps failed");
474  uves_msg("Check Slit Flat Field Y nominal positions within each set");
475  for(i=0;i<nset;i++) {
476 
477  uves_msg("Slit Flat field set %d: x1enc = %d x2enc = %d",
478  i+1,
479  cpl_table_get_int(encoder_tbl,"x1enc",i,&status),
480  cpl_table_get_int(encoder_tbl,"x2enc",i,&status));
481 
482  }
483 
484  for(i=0;i<nset;i++) {
485  x1enc=cpl_table_get_int(encoder_tbl,"x1enc",i,&status);
486  x2enc=cpl_table_get_int(encoder_tbl,"x2enc",i,&status);
487 
488  uves_msg("Processing set %d", i+1);
489 
490  check(uves_mflat_at_ypos(set,parameters,recipe_id,starttime,raw,cdb,x1enc,x2enc,i+1),
491  "Master flat one failed");
492  }
493 
494  cleanup:
495  uves_free_table(&encoder_tbl);
496  uves_free_frameset(&raw);
497  uves_free_frameset(&cdb);
498  uves_free_frameset(&pro);
499 
500  return cpl_error_get_code();
501 }
502 
503 
504 /*----------------------------------------------------------------------------*/
510 /*----------------------------------------------------------------------------*/
511 static cpl_error_code
512 uves_mflat_at_ypos(cpl_frameset* set,
513  const cpl_parameterlist* parameters,
514  const char *recipe_id,
515  const char *starttime,
516  const cpl_frameset* raw,
517  const cpl_frameset* cdb,
518  const int ref_x1enc,
519  const int ref_x2enc,
520  const int set_no)
521 {
522 
523  const cpl_frame* frm_tmp=NULL;
524  char* file=NULL;
525  uves_propertylist* plist=NULL;
526  cpl_size i=0;
527  const int threshold = 5;
528  cpl_frame* frm_dup=NULL;
529  cpl_frameset* tmp=NULL;
530  cpl_frameset* pro=NULL;
531  int x1enc=0;
532  int x2enc=0;
533  char prefix[255];
534  bool flames = true;
535 
536  check_nomsg(tmp=cpl_frameset_new());
537  for(i=0;i<cpl_frameset_get_size(raw);i++)
538  {
539  check_nomsg(frm_tmp=cpl_frameset_get_frame_const(raw,i));
540  check_nomsg(file=cpl_strdup(cpl_frame_get_filename(frm_tmp)));
541  check_nomsg(plist=uves_propertylist_load(file,0));
544 
545  if( (fabs(x1enc - ref_x1enc) <= threshold) &&
546  (fabs(x2enc - ref_x2enc) <= threshold) ) {
547  uves_msg_debug("file=%s x1enc=%d x2enc=%d",file,x1enc,x2enc);
548  check(frm_dup = cpl_frame_duplicate(frm_tmp),"duplicate");
549  check(cpl_frameset_insert(tmp,frm_dup),"insert");
550  }
551  cpl_free(file);
552  uves_free_propertylist(&plist);
553  }
554  check_nomsg(uves_frameset_merge(tmp,cdb));
555  sprintf(prefix,"%s%d%s","set",set_no,"_");
556  check(uves_mflat_one(tmp,parameters, flames, recipe_id, starttime,prefix),"Master flat one failed");
557  check_nomsg(uves_extract_frames_group_type(tmp,&pro,CPL_FRAME_GROUP_PRODUCT));
558  check_nomsg(uves_frameset_merge(set,pro));
559 
560  cleanup:
561  uves_free_frameset(&tmp);
562  uves_free_frameset(&pro);
563  uves_free_propertylist(&plist);
564 
565  return cpl_error_get_code();
566 }
567 /*----------------------------------------------------------------------------*/
580 /*----------------------------------------------------------------------------*/
581 static void
582 uves_mflat_one(cpl_frameset *frames,
583  const cpl_parameterlist *parameters,
584  bool flames,
585  const char *recipe_id,
586  const char *starttime,
587  const char* prefix)
588 {
589  /* Do flat-fielding */
590  check_nomsg( uves_reduce_mflat(frames, parameters,
591  flames, recipe_id,
592  starttime, prefix) );
593 
594  cleanup:
595  return;
596 }
597 
598 /*----------------------------------------------------------------------------*/
609 /*----------------------------------------------------------------------------*/
610 static void
611 uves_reduce_mflat(cpl_frameset *frames, const cpl_parameterlist *parameters,
612  bool flames,
613  const char *recipe_id,
614  const char *starttime,
615  const char *prefix)
616 {
617  bool debug_mode;
618 
619  /* Input */
620  cpl_imagelist *raw_images[2] = {NULL, NULL}; /* An image list for both chips */
621  uves_propertylist **raw_headers[2] = {NULL, NULL}; /* Two arrays of pointers */
622 
623  /* Master bias */
624  cpl_image *master_bias = NULL;
625  uves_propertylist *master_bias_header = NULL;
626 
627  /* Master dark */
628  cpl_image *master_dark = NULL;
629  uves_propertylist *master_dark_header = NULL;
630 
631  /* Order table */
632  cpl_table *ordertable = NULL;
633  uves_propertylist *ordertable_header = NULL;
634  polynomial *order_locations = NULL;
635  cpl_table *traces = NULL;
636 
637  /* Reference master flat */
638  cpl_image *ref_flat = NULL;
639  uves_propertylist *ref_flat_header = NULL;
640 
641  /* Output */
642  cpl_table *qclog[] = {NULL, NULL};
643  cpl_image *master_flat = NULL;
644  cpl_image *background = NULL;
645  uves_propertylist *product_header[] = {NULL, NULL};
646  cpl_image *ratio = NULL;
647 
648  /* Local variables */
649  char *product_filename = NULL;
650  char pro_filename[255];
651  const char *product_tag[2] = {NULL, NULL};
652  bool blue;
653  enum uves_chip chip;
654  const char* PROCESS_CHIP=NULL;
655 
656 
657 
658 
659  const char *ordertable_filename = "";
660  const char *master_bias_filename = "";
661  const char *master_dark_filename = "";
662  const char *chip_name = "";
663  int raw_index = 0;
664  const char *ref_flat_filename;
665 
666  /* Read recipe parameters */
667  {
668  /* General */
669  check( uves_get_parameter(parameters, NULL, "uves", "debug", CPL_TYPE_BOOL , &debug_mode ),
670  "Could not read parameter");
671  }
672  check( uves_get_parameter(parameters, NULL, "uves", "process_chip", CPL_TYPE_STRING, &PROCESS_CHIP), "Could not read parameter");
673 
674  uves_string_toupper((char*)PROCESS_CHIP);
675 
676  /* Load and check raw flat images and headers, identify arm (blue/red) */
677  /* On success, 'raw_headers' will be an array with the same size as 'raw_images' */
678  /* Set product tags to match input tag */
679 
680  if (cpl_frameset_find(frames, UVES_FLAT(true )) != NULL ||
681  cpl_frameset_find(frames, UVES_FLAT(false)) != NULL)
682  {
683  check( uves_load_raw_imagelist(frames,
684  flames,
685  UVES_FLAT(true), UVES_FLAT(false),
686  CPL_TYPE_DOUBLE,
687  raw_images, raw_headers, product_header,
688  &blue), "Error loading raw flat frames");
689 
690  for (chip = uves_chip_get_first(blue); chip != UVES_CHIP_INVALID;
691  chip = uves_chip_get_next(chip))
692  {
693  product_tag[uves_chip_get_index(chip)] = UVES_MASTER_FLAT(chip);
694  }
695  }
696  else if (cpl_frameset_find(frames, UVES_DFLAT(true )) != NULL ||
697  cpl_frameset_find(frames, UVES_DFLAT(false)) != NULL)
698  {
699  check( uves_load_raw_imagelist(frames,
700  flames,
701  UVES_DFLAT(true), UVES_DFLAT(false),
702  CPL_TYPE_DOUBLE,
703  raw_images, raw_headers, product_header,
704  &blue), "Error loading raw flat frames");
705  for (chip = uves_chip_get_first(blue);
706  chip != UVES_CHIP_INVALID;
707  chip = uves_chip_get_next(chip))
708  {
709  product_tag[uves_chip_get_index(chip)] = UVES_MASTER_DFLAT(chip);
710  }
711  }
712  else if (cpl_frameset_find(frames, UVES_IFLAT(true )) != NULL ||
713  cpl_frameset_find(frames, UVES_IFLAT(false)) != NULL)
714  {
715  check( uves_load_raw_imagelist(frames,
716  flames,
717  UVES_IFLAT(true), UVES_IFLAT(false),
718  CPL_TYPE_DOUBLE,
719  raw_images, raw_headers, product_header,
720  &blue), "Error loading raw flat frames");
721  for (chip = uves_chip_get_first(blue);
722  chip != UVES_CHIP_INVALID;
723  chip = uves_chip_get_next(chip))
724  {
725  product_tag[uves_chip_get_index(chip)] = UVES_MASTER_IFLAT(chip);
726  }
727  }
728  else if (cpl_frameset_find(frames, UVES_TFLAT(true )) != NULL ||
729  cpl_frameset_find(frames, UVES_TFLAT(false)) != NULL)
730  {
731  check( uves_load_raw_imagelist(frames,
732  flames,
733  UVES_TFLAT(true), UVES_TFLAT(false),
734  CPL_TYPE_DOUBLE,
735  raw_images, raw_headers, product_header,
736  &blue), "Error loading raw flat frames");
737  for (chip = uves_chip_get_first(blue);
738  chip != UVES_CHIP_INVALID;
739  chip = uves_chip_get_next(chip))
740  {
741  product_tag[uves_chip_get_index(chip)] = UVES_MASTER_TFLAT(chip);
742  }
743  }
744  else if (cpl_frameset_find(frames, UVES_SCREEN_FLAT(true )) != NULL ||
745  cpl_frameset_find(frames, UVES_SCREEN_FLAT(false)) != NULL)
746  {
747  check( uves_load_raw_imagelist(frames,
748  flames,
749  UVES_SCREEN_FLAT(true), UVES_SCREEN_FLAT(false),
750  CPL_TYPE_DOUBLE,
751  raw_images, raw_headers, product_header,
752  &blue), "Error loading raw flat frames");
753  for (chip = uves_chip_get_first(blue);
754  chip != UVES_CHIP_INVALID;
755  chip = uves_chip_get_next(chip))
756  {
757  product_tag[uves_chip_get_index(chip)] = UVES_MASTER_SCREEN_FLAT(chip);
758  }
759  }
760  else if (cpl_frameset_find(frames, UVES_SFLAT(true )) != NULL ||
761  cpl_frameset_find(frames, UVES_SFLAT(false)) != NULL)
762  {
763  check( uves_load_raw_imagelist(frames,
764  flames,
765  UVES_SFLAT(true), UVES_SFLAT(false),
766  CPL_TYPE_DOUBLE,
767  raw_images, raw_headers, product_header,
768  &blue), "Error loading raw flat frames");
769  for (chip = uves_chip_get_first(blue);
770  chip != UVES_CHIP_INVALID;
771  chip = uves_chip_get_next(chip))
772  {
773  product_tag[uves_chip_get_index(chip)] = UVES_MASTER_SFLAT(chip);
774  }
775  }
776  else
777  {
778  assure(false, CPL_ERROR_DATA_NOT_FOUND,
779  "Missing input flat frame: "
780  "%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s or %s expected",
781  UVES_FLAT(true) , UVES_FLAT(false),
782  UVES_DFLAT(true), UVES_DFLAT(false),
783  UVES_IFLAT(true), UVES_IFLAT(false),
784  UVES_TFLAT(true), UVES_TFLAT(false),
785  UVES_SCREEN_FLAT(true), UVES_SCREEN_FLAT(false),
786  UVES_SFLAT(true), UVES_SFLAT(false));
787  }
788 
789  /* Loop over one or two chips */
790  for (chip = uves_chip_get_first(blue);
791  chip != UVES_CHIP_INVALID;
792  chip = uves_chip_get_next(chip))
793  {
794 
795  if(strcmp(PROCESS_CHIP,"REDU") == 0) {
796  chip = uves_chip_get_next(chip);
797  }
798 
799  raw_index = uves_chip_get_index(chip);
800 
801  uves_msg("Processing %s chip", uves_chip_tostring_upper(chip));
802 
803  /* Chip name of first input frame */
804  check_nomsg( chip_name = uves_pfits_get_chipid(raw_headers[raw_index][0], chip));
805 
806  /* Load master bias, set pointer to NULL if not present */
807  uves_free_image(&master_bias);
808  uves_free_propertylist(&master_bias_header);
809  if (cpl_frameset_find(frames, UVES_MASTER_BIAS(chip)) != NULL)
810  {
811  uves_free_image(&master_bias);
812  uves_free_propertylist(&master_bias_header);
813  check( uves_load_mbias(frames,
814  chip_name,
815  &master_bias_filename, &master_bias,
816  &master_bias_header, chip),
817  "Error loading master bias");
818 
819  uves_msg_low("Using master bias in '%s'", master_bias_filename);
820  }
821  else
822  {
823  uves_msg_low("No master bias in SOF. Bias subtraction not done");
824  }
825 
826  /* Load master dark, set pointer to NULL if not present */
827  uves_free_image(&master_dark);
828  uves_free_propertylist(&master_dark_header);
829  if (cpl_frameset_find(frames, UVES_MASTER_DARK(chip)) != NULL ||
830  cpl_frameset_find(frames, UVES_MASTER_PDARK(chip)) != NULL)
831  {
832  uves_free_image(&master_dark);
833  uves_free_propertylist(&master_dark_header);
834  check( uves_load_mdark(frames, chip_name,
835  &master_dark_filename, &master_dark,
836  &master_dark_header, chip),
837  "Error loading master dark");
838 
839  uves_msg_low("Using master dark in '%s'", master_dark_filename);
840  }
841  else
842  {
843  uves_msg_low("No master dark in SOF. Dark subtraction not done");
844  }
845 
846  /* Load the order table for this chip */
847  if (flames)
848  /* FLAMES does not do background subtraction (here)
849  and therefore does not need an ordertable */
850  {
851  if (cpl_frameset_find(frames, UVES_ORDER_TABLE(flames, chip)) != NULL)
852  {
853  uves_msg_warning("Order table (%s) is not used in FLAMES reduction",
854  UVES_ORDER_TABLE(flames, chip));
855  }
856  }
857  else
858  {
859  uves_free_table (&ordertable);
860  uves_free_propertylist(&ordertable_header);
861  uves_polynomial_delete(&order_locations);
862  uves_free_table (&traces);
863 
864  check( uves_load_ordertable(frames,
865  flames,
866  chip_name,
867  &ordertable_filename,
868  &ordertable,
869  &ordertable_header,
870  NULL,
871  &order_locations,
872  &traces, NULL, NULL,
873  NULL, NULL, /* fibre_pos,fibre_mask */
874  chip,
875  false),
876  "Could not load order table");
877  uves_msg("Using order table in '%s'", ordertable_filename);
878  }
879 
880  /* Compute QC parameters and save */
881  uves_msg("Computing QC parameters");
882  uves_qclog_delete(&qclog[0]);
883  qclog[0] = uves_qclog_init(raw_headers[raw_index][0], chip);
884 
885  check(uves_mflat_qclog(raw_images[raw_index],
886  qclog[0]),"error computing qclog");
887 
888 
889 
890  /* Process chip */
891  uves_free_image(&master_flat);
892  uves_free_image(&background);
893  check( master_flat = uves_mflat_process_chip(
894  raw_images[raw_index], raw_headers[raw_index],
895  product_header[raw_index],
896  master_bias,
897  master_dark, master_dark_header,
898  ordertable, order_locations,
899  flames,
900  parameters,
901  chip,
902  recipe_id,
903  debug_mode,
904  &background),
905  "Error processing chip");
906 
907  /* Finished. Save */
908  uves_msg("Saving products");
909 
910  cpl_free(product_filename);
911  check( product_filename = uves_masterflat_filename(chip),
912  "Error getting filename");
913  strcpy(pro_filename,prefix);
914  strcat(pro_filename,product_filename);
915  check( uves_frameset_insert(
916  frames,
917  master_flat,
918  CPL_FRAME_GROUP_PRODUCT,
919  CPL_FRAME_TYPE_IMAGE,
920  CPL_FRAME_LEVEL_INTERMEDIATE,
921  pro_filename,
922  product_tag[raw_index],
923  raw_headers[raw_index][0],
924  product_header[raw_index],
925  NULL,
926  parameters,
927  recipe_id,
928  PACKAGE "/" PACKAGE_VERSION, qclog,
929  starttime, true, UVES_ALL_STATS),
930  "Could not add master flat %s %s to frameset",
931  product_filename, product_tag[raw_index]);
932  uves_msg("Master flat %s %s added to frameset",
933  pro_filename, product_tag[raw_index]);
934 
935  /* Save background image */
936  if (!flames)
937  {
938  cpl_free(product_filename);
939  check( product_filename = uves_masterflat_bkg_filename(chip),
940  "Error getting filename");
941  strcpy(pro_filename,prefix);
942  strcat(pro_filename,product_filename);
943  uves_pfits_set_extname(product_header[raw_index],
944  "Inter-order background");
945  check( uves_frameset_insert(frames,
946  background,
947  CPL_FRAME_GROUP_PRODUCT,
948  CPL_FRAME_TYPE_IMAGE,
949  CPL_FRAME_LEVEL_INTERMEDIATE,
950  pro_filename,
951  UVES_BKG_FLAT(chip),
952  raw_headers[raw_index][0],
953  product_header[raw_index],
954  NULL,
955  parameters,
956  recipe_id,
957  PACKAGE "/" PACKAGE_VERSION, NULL,
958  starttime, false,
959  CPL_STATS_MIN | CPL_STATS_MAX),
960  "Could not add background image '%s' to frameset",
961  product_filename);
962  uves_msg("Master flat background '%s' added to frameset",
963  product_filename);
964  }
965 
966  /* Compute and save ratio MASTER_TFLAT / REF_TFLAT */
967  if (strcmp(recipe_id, make_str(UVES_TFLAT_ID)) == 0)
968  {
969 
970  uves_free_image(&ref_flat);
971  uves_free_propertylist(&ref_flat_header);
972 
973  check( uves_load_ref_flat(frames, chip_name, &ref_flat_filename,
974  &ref_flat, &ref_flat_header,
975  chip),
976  "Error loading reference flat field");
977 
978  uves_msg("Using reference flat field in '%s'", ref_flat_filename);
979 
980  check( ratio = cpl_image_divide_create(master_flat, ref_flat),
981  "Error computing ratio of master and reference flat");
982 
983  cpl_free(product_filename);
984  check( product_filename = uves_flat_ratio_filename(chip),
985  "Error getting filename");
986 
987  check( uves_frameset_insert(frames,
988  ratio,
989  CPL_FRAME_GROUP_PRODUCT,
990  CPL_FRAME_TYPE_IMAGE,
991  CPL_FRAME_LEVEL_INTERMEDIATE,
992  product_filename,
993  UVES_RATIO_TFLAT(chip),
994  raw_headers[raw_index][0],
995  product_header[raw_index],
996  NULL,
997  parameters,
998  recipe_id,
999  PACKAGE "/" PACKAGE_VERSION,
1000  qclog,
1001  starttime, false,
1002  UVES_ALL_STATS),
1003  "Could not add ratio image '%s' to frameset", product_filename);
1004 
1005  uves_msg("Master flat ratio '%s' added to frameset", product_filename);
1006  }
1007 
1008 
1009  if(strcmp(PROCESS_CHIP,"REDL") == 0) {
1010  chip = uves_chip_get_next(chip);
1011  }
1012 
1013 
1014  } /* For each chip */
1015 
1016  cleanup:
1017  /* Input */
1018  if (raw_images[0] != NULL)
1019  {
1020  int i;
1021  for (i = 0; i < cpl_imagelist_get_size(raw_images[0]); i++)
1022  {
1023  if (raw_headers[0] != NULL) uves_free_propertylist(&raw_headers[0][i]);
1024  if (raw_headers[1] != NULL) uves_free_propertylist(&raw_headers[1][i]);
1025  }
1026  cpl_free(raw_headers[0]); raw_headers[0] = NULL;
1027  cpl_free(raw_headers[1]); raw_headers[1] = NULL;
1028  }
1029 
1030  uves_free_imagelist(&raw_images[0]);
1031  uves_free_imagelist(&raw_images[1]);
1032 
1033  /* Master bias */
1034  uves_free_image(&master_bias);
1035  uves_free_propertylist(&master_bias_header);
1036 
1037  /* Master dark */
1038  uves_free_image(&master_dark);
1039  uves_free_propertylist(&master_dark_header);
1040 
1041  /* Order table */
1042  uves_free_table(&ordertable);
1043  uves_free_propertylist(&ordertable_header);
1044  uves_polynomial_delete(&order_locations);
1045  uves_free_table(&traces);
1046 
1047  /* Reference master flat */
1048  uves_free_image(&ref_flat);
1049  uves_free_propertylist(&ref_flat_header);
1050 
1051  /* Output */
1052  uves_qclog_delete(&qclog[0]);
1053  uves_free_image(&master_flat);
1054  uves_free_image(&background);
1055  uves_free_image(&ratio);
1056  uves_free_propertylist(&product_header[0]);
1057  uves_free_propertylist(&product_header[1]);
1058  cpl_free(product_filename);
1059 
1060  return;
1061 }
1062 
1063 
1064 /*----------------------------------------------------------------------------*/
1070 /*----------------------------------------------------------------------------*/
1071 
1072 static void
1073 uves_mflat_qclog(const cpl_imagelist* raw_images,
1074  cpl_table* qclog)
1075 {
1076  int nraw=0;
1077 
1079  "QC TEST1 ID",
1080  "Test-on-Master-Flat",
1081  "Name of QC test",
1082  "%s"));
1083  check_nomsg(nraw=cpl_imagelist_get_size(raw_images));
1084 
1086  "PRO DATANCOM",
1087  nraw,
1088  "Number of frames combined",
1089  "%d"));
1090  cleanup:
1091  return;
1092 }
int uves_mflat_define_parameters_body(cpl_parameterlist *parameters, const char *recipe_id)
Setup the recipe options.
void uves_polynomial_delete(polynomial **p)
Delete a polynomial.
#define uves_msg_warning(...)
Print an warning message.
Definition: uves_msg.h:87
int uves_qclog_add_string(cpl_table *table, const char *key_name, const char *value, const char *key_help, const char *format)
Add string key to QC-LOG table.
Definition: uves_qclog.c:683
static cpl_error_code uves_mflat_at_ypos(cpl_frameset *set, const cpl_parameterlist *parameters, const char *recipe_id, const char *starttime, const cpl_frameset *raw, const cpl_frameset *cdb, const int ref_x1enc, const int ref_x2enc, const int set_no)
Computes coherent master sflats.
cpl_image * uves_flat_create_normalized_master(cpl_imagelist *flats, const cpl_table *ordertable, const polynomial *order_locations, const cpl_vector *gain_vals, double *fnoise)
Stack images using k-sigma clipping.
Definition: uves_utils.c:702
double uves_pfits_get_gain(const uves_propertylist *plist, enum uves_chip chip)
Find out the gain.
Definition: uves_pfits.c:887
#define check_nomsg(CMD)
Definition: uves_error.h:204
cpl_image * uves_flat_create_normalized_master2(cpl_imagelist *flats, const cpl_table *ordertable, const polynomial *order_locations, const cpl_image *mflat)
Stack images using k-sigma clipping.
Definition: uves_utils.c:551
cpl_error_code uves_subtract_bias(cpl_image *image, const cpl_image *master_bias)
Subtract bias.
Definition: uves_utils.c:2394
int uves_qclog_delete(cpl_table **table)
delete QC-LOG table
Definition: uves_qclog.c:716
int uves_pfits_get_slit3_x2encoder(const uves_propertylist *plist)
find out the value of UVES_ENCODER_REF2
Definition: uves_pfits.c:174
int uves_qclog_add_int(cpl_table *table, const char *key_name, const int value, const char *key_help, const char *format)
Add integer key to QC-LOG table.
Definition: uves_qclog.c:521
static cpl_image * uves_mflat_process_chip(const cpl_imagelist *raw_images, uves_propertylist **raw_headers, uves_propertylist *master_flat_header, const cpl_image *master_bias, const cpl_image *master_dark, const uves_propertylist *mdark_header, const cpl_table *ordertable, const polynomial *order_locations, bool flames, const cpl_parameterlist *parameters, enum uves_chip chip, const char *recipe_id, bool debug_mode, cpl_image **background)
Process a single chip.
#define uves_msg(...)
Print a message on 'info' or 'debug' level.
Definition: uves_msg.h:119
uves_propertylist * uves_propertylist_load(const char *name, int position)
Create a property list from a file.
void uves_mflat_exe_body(cpl_frameset *frames, const cpl_parameterlist *parameters, const char *starttime, const char *recipe_id)
Get the command line options and execute the data reduction.
int uves_pfits_get_slit3_x1encoder(const uves_propertylist *plist)
find out the value of UVES_ENCODER_REF1
Definition: uves_pfits.c:156
double uves_pfits_get_exptime(const uves_propertylist *plist)
Find out the exposure time in seconds.
Definition: uves_pfits.c:922
int uves_chip_get_index(enum uves_chip chip)
Convert to integer.
Definition: uves_chip.c:124
enum uves_chip uves_chip_get_first(bool blue)
Get first chip for blue or red arm.
Definition: uves_chip.c:92
cpl_error_code uves_pfits_set_extname(uves_propertylist *plist, const char *extname)
Write the EXTNAME keyword.
Definition: uves_pfits.c:2736
static void uves_mflat_qclog(const cpl_imagelist *raw_images, cpl_table *qclog)
Process a single chip.
cpl_error_code uves_pfits_set_exptime(uves_propertylist *plist, double exptime)
Write the exposure time.
Definition: uves_pfits.c:944
#define uves_msg_low(...)
Print a message on a lower message level.
Definition: uves_msg.h:105
static void uves_reduce_mflat(cpl_frameset *frames, const cpl_parameterlist *parameters, bool flames, const char *recipe_id, const char *starttime, const char *prefix)
Get the command line options and execute the data reduction.
enum uves_chip uves_chip_get_next(enum uves_chip chip)
Get next chip.
Definition: uves_chip.c:108
static void uves_mflat_one(cpl_frameset *frames, const cpl_parameterlist *parameters, bool flames, const char *recipe_id, const char *starttime, const char *prefix)
Get the command line options and execute the data reduction.
#define uves_msg_debug(...)
Print a debug message.
Definition: uves_msg.h:97
const char * uves_chip_tostring_upper(enum uves_chip chip)
Convert to string.
Definition: uves_chip.c:156
const char * uves_string_toupper(char *s)
Convert all lowercase characters in a string into uppercase characters.
Definition: uves_utils.c:1493
cpl_error_code uves_propertylist_append_c_double(uves_propertylist *self, const char *name, double value, const char *comment)
Append a double value to a property list.
#define check(CMD,...)
Definition: uves_error.h:198
cpl_table * uves_qclog_init(const uves_propertylist *raw_header, enum uves_chip chip)
Init QC-LOG table.
Definition: uves_qclog.c:410
static cpl_error_code uves_msflats(cpl_frameset *set, const cpl_parameterlist *parameters, const char *recipe_id, const char *starttime)
Computes coherent master sflats.
const char * uves_pfits_get_chipid(const uves_propertylist *plist, enum uves_chip chip)
Find out the chip ID.
Definition: uves_pfits.c:619
cpl_frameset * uves_frameset_extract(const cpl_frameset *frames, const char *tag)
Extract frames with given tag from frameset.
Definition: uves_utils.c:1557