UVES Pipeline Reference Manual  5.4.0
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");
313  check_nomsg( mdark_exposure = uves_pfits_get_exptime(mdark_header));
314  mdark_scaled=cpl_image_duplicate(master_dark);
315  cpl_image_divide_scalar(mdark_scaled,mdark_exposure);
316  check( cpl_imagelist_subtract_image(raw_images_local,mdark_scaled),
317  "Error subtracting master dark");
318  uves_free_image(&mdark_scaled);
319  }
320  else
321  {
322  uves_msg("Skipping dark subtraction");
323  }
324 
325 
326  /* Take median of all input flats */
327  if(strcmp(FLAT_METHOD,"EXPTIME")==0) {
328  uves_msg("Calculating stack median");
329  check(master_flat=cpl_imagelist_collapse_median_create(raw_images_local),
330  "Error computing median");
331  } else {
332  uves_msg("Calculating stack normalized master");
333  check( master_flat_tmp = uves_flat_create_normalized_master(raw_images_local,
334  ordertable,
335  order_locations,gain_vals,&fnoise),
336  "Error computing master flat with normalization");
337 
338  check( master_flat = uves_flat_create_normalized_master2(raw_images_local,
339  ordertable,
340  order_locations,
341  master_flat_tmp),
342  "Error computing master flat with normalization");
343  uves_free_image(&master_flat_tmp);
344  uves_propertylist_append_c_double(master_flat_header,UVES_FNOISE,fnoise,
345  "Master flat RMS on frame");
346 
347  }
348  /*clean mem and reset local pointers to null */
349  raw_images_local=NULL;
350  uves_free_vector(&exptimes);
351  uves_free_vector(&gain_vals);
352 
353  if (debug_mode && !flames)
354  {
355  check( uves_save_image_local("Pre-background subtracted master flat", "pre",
356  master_flat, chip, -1, -1, master_flat_header, true),
357  "Error saving image");
358  }
359 
360  /* Subtract background from master flat */
361  if (!flames)
362  {
363  uves_msg("Subtracting background");
364 
365  check( uves_backsub_spline(master_flat,
366  /* Info about chip (wavelength, ...) is
367  stored in any raw header,
368  so just pass the first one */
369  raw_headers[0],
370  ordertable, order_locations,
371  parameters, recipe_id,
372  chip,
373  true, /* Use flat-field parameters? */
374  background),
375  "Error subtracting background from master flat");
376  }
377  else
378  {
379  uves_msg("Skipping background subtraction");
380  }
381 
382  cleanup:
383 
384 
385  uves_free_image(&current_flat);
386  if (cpl_error_get_code() != CPL_ERROR_NONE)
387  {
388  uves_free_image(&master_flat);
389  }
390 
391  return master_flat;
392 }
393 
394 /*----------------------------------------------------------------------------*/
406 /*----------------------------------------------------------------------------*/
407 void
408 uves_mflat_exe_body(cpl_frameset *frames,
409  const cpl_parameterlist *parameters,
410  const char *starttime,
411  const char *recipe_id)
412 {
413  /* Do FLAMES reduction if SFLAT frame is given */
414  if (cpl_frameset_find(frames, UVES_SFLAT(false)) != NULL) {
415 
416  check(uves_msflats(frames, parameters, recipe_id, starttime),
417  "find same sflats failed");
418  }
419  else {
420  bool flames = false;
421  check(uves_mflat_one(frames, parameters, flames, recipe_id,
422  starttime, ""),
423  "Master flat one failed");
424  }
425 
426  cleanup:
427  return;
428 }
429 
430 /*----------------------------------------------------------------------------*/
436 /*----------------------------------------------------------------------------*/
437 static cpl_error_code
438 uves_msflats(cpl_frameset * set, const cpl_parameterlist *parameters,
439  const char *recipe_id,
440  const char *starttime)
441 {
442  /* Pseudocode:
443  extract raw frames from set
444  extract cdb frames from set
445  identifies how many different Y position we have
446  for each Y pos:
447  extract from the raw_set the raw frames corresponding to each Y pos
448  merge in a new wrk_set the cdb_set
449  computes the corresponding master flat
450  put the products in the final set
451  endfor
452  */
453  cpl_frameset* raw=NULL;
454  cpl_frameset* cdb=NULL;
455  cpl_frameset* pro=NULL;
456  int status=0;
457  int x1enc=0;
458  int x2enc=0;
459 
460  cpl_table* encoder_tbl=NULL;
461  int nset=0;
462  int i=0;
463 
464  //Extracts SFLAT raw frames
465  check(raw=uves_frameset_extract(set,UVES_SFLAT(false)),
466  "Extract %s frames failed",
467  UVES_SFLAT(false));
468 
469  check(uves_extract_frames_group_type(set,&cdb,CPL_FRAME_GROUP_CALIB),
470  "Extract cdb frames failed");
471  check(uves_sflats_get_encoder_steps(raw,&encoder_tbl,&nset),
472  "Get encoder steps failed");
473  uves_msg("Check Slit Flat Field Y nominal positions within each set");
474  for(i=0;i<nset;i++) {
475 
476  uves_msg("Slit Flat field set %d: x1enc = %d x2enc = %d",
477  i+1,
478  cpl_table_get_int(encoder_tbl,"x1enc",i,&status),
479  cpl_table_get_int(encoder_tbl,"x2enc",i,&status));
480 
481  }
482 
483  for(i=0;i<nset;i++) {
484  x1enc=cpl_table_get_int(encoder_tbl,"x1enc",i,&status);
485  x2enc=cpl_table_get_int(encoder_tbl,"x2enc",i,&status);
486 
487  uves_msg("Processing set %d", i+1);
488 
489  check(uves_mflat_at_ypos(set,parameters,recipe_id,starttime,raw,cdb,x1enc,x2enc,i+1),
490  "Master flat one failed");
491  }
492 
493  cleanup:
494  uves_free_table(&encoder_tbl);
495  uves_free_frameset(&raw);
496  uves_free_frameset(&cdb);
497  uves_free_frameset(&pro);
498 
499  return cpl_error_get_code();
500 }
501 
502 
503 /*----------------------------------------------------------------------------*/
509 /*----------------------------------------------------------------------------*/
510 static cpl_error_code
511 uves_mflat_at_ypos(cpl_frameset* set,
512  const cpl_parameterlist* parameters,
513  const char *recipe_id,
514  const char *starttime,
515  const cpl_frameset* raw,
516  const cpl_frameset* cdb,
517  const int ref_x1enc,
518  const int ref_x2enc,
519  const int set_no)
520 {
521 
522  const cpl_frame* frm_tmp=NULL;
523  char* file=NULL;
524  uves_propertylist* plist=NULL;
525  cpl_size i=0;
526  const int threshold = 5;
527  cpl_frame* frm_dup=NULL;
528  cpl_frameset* tmp=NULL;
529  cpl_frameset* pro=NULL;
530  int x1enc=0;
531  int x2enc=0;
532  char prefix[255];
533  bool flames = true;
534 
535  check_nomsg(tmp=cpl_frameset_new());
536  for(i=0;i<cpl_frameset_get_size(raw);i++)
537  {
538  check_nomsg(frm_tmp=cpl_frameset_get_frame_const(raw,i));
539  check_nomsg(file=cpl_strdup(cpl_frame_get_filename(frm_tmp)));
540  check_nomsg(plist=uves_propertylist_load(file,0));
543 
544  if( (fabs(x1enc - ref_x1enc) <= threshold) &&
545  (fabs(x2enc - ref_x2enc) <= threshold) ) {
546  uves_msg_debug("file=%s x1enc=%d x2enc=%d",file,x1enc,x2enc);
547  check(frm_dup = cpl_frame_duplicate(frm_tmp),"duplicate");
548  check(cpl_frameset_insert(tmp,frm_dup),"insert");
549  }
550  cpl_free(file);
551  uves_free_propertylist(&plist);
552  }
553  check_nomsg(uves_frameset_merge(tmp,cdb));
554  sprintf(prefix,"%s%d%s","set",set_no,"_");
555  check(uves_mflat_one(tmp,parameters, flames, recipe_id, starttime,prefix),"Master flat one failed");
556  check_nomsg(uves_extract_frames_group_type(tmp,&pro,CPL_FRAME_GROUP_PRODUCT));
557  check_nomsg(uves_frameset_merge(set,pro));
558 
559  cleanup:
560  uves_free_frameset(&tmp);
561  uves_free_frameset(&pro);
562  uves_free_propertylist(&plist);
563 
564  return cpl_error_get_code();
565 }
566 /*----------------------------------------------------------------------------*/
579 /*----------------------------------------------------------------------------*/
580 static void
581 uves_mflat_one(cpl_frameset *frames,
582  const cpl_parameterlist *parameters,
583  bool flames,
584  const char *recipe_id,
585  const char *starttime,
586  const char* prefix)
587 {
588  /* Do flat-fielding */
589  check_nomsg( uves_reduce_mflat(frames, parameters,
590  flames, recipe_id,
591  starttime, prefix) );
592 
593  cleanup:
594  return;
595 }
596 
597 /*----------------------------------------------------------------------------*/
608 /*----------------------------------------------------------------------------*/
609 static void
610 uves_reduce_mflat(cpl_frameset *frames, const cpl_parameterlist *parameters,
611  bool flames,
612  const char *recipe_id,
613  const char *starttime,
614  const char *prefix)
615 {
616  bool debug_mode;
617 
618  /* Input */
619  cpl_imagelist *raw_images[2] = {NULL, NULL}; /* An image list for both chips */
620  uves_propertylist **raw_headers[2] = {NULL, NULL}; /* Two arrays of pointers */
621 
622  /* Master bias */
623  cpl_image *master_bias = NULL;
624  uves_propertylist *master_bias_header = NULL;
625 
626  /* Master dark */
627  cpl_image *master_dark = NULL;
628  uves_propertylist *master_dark_header = NULL;
629 
630  /* Order table */
631  cpl_table *ordertable = NULL;
632  uves_propertylist *ordertable_header = NULL;
633  polynomial *order_locations = NULL;
634  cpl_table *traces = NULL;
635 
636  /* Reference master flat */
637  cpl_image *ref_flat = NULL;
638  uves_propertylist *ref_flat_header = NULL;
639 
640  /* Output */
641  cpl_table *qclog[] = {NULL, NULL};
642  cpl_image *master_flat = NULL;
643  cpl_image *background = NULL;
644  uves_propertylist *product_header[] = {NULL, NULL};
645  cpl_image *ratio = NULL;
646 
647  /* Local variables */
648  char *product_filename = NULL;
649  char pro_filename[255];
650  const char *product_tag[2] = {NULL, NULL};
651  bool blue;
652  enum uves_chip chip;
653  const char* PROCESS_CHIP=NULL;
654 
655 
656 
657 
658  const char *ordertable_filename = "";
659  const char *master_bias_filename = "";
660  const char *master_dark_filename = "";
661  const char *chip_name = "";
662  int raw_index = 0;
663  const char *ref_flat_filename;
664 
665  /* Read recipe parameters */
666  {
667  /* General */
668  check( uves_get_parameter(parameters, NULL, "uves", "debug", CPL_TYPE_BOOL , &debug_mode ),
669  "Could not read parameter");
670  }
671  check( uves_get_parameter(parameters, NULL, "uves", "process_chip", CPL_TYPE_STRING, &PROCESS_CHIP), "Could not read parameter");
672 
673  uves_string_toupper((char*)PROCESS_CHIP);
674 
675  /* Load and check raw flat images and headers, identify arm (blue/red) */
676  /* On success, 'raw_headers' will be an array with the same size as 'raw_images' */
677  /* Set product tags to match input tag */
678 
679  if (cpl_frameset_find(frames, UVES_FLAT(true )) != NULL ||
680  cpl_frameset_find(frames, UVES_FLAT(false)) != NULL)
681  {
682  check( uves_load_raw_imagelist(frames,
683  flames,
684  UVES_FLAT(true), UVES_FLAT(false),
685  CPL_TYPE_DOUBLE,
686  raw_images, raw_headers, product_header,
687  &blue), "Error loading raw flat frames");
688 
689  for (chip = uves_chip_get_first(blue); chip != UVES_CHIP_INVALID;
690  chip = uves_chip_get_next(chip))
691  {
692  product_tag[uves_chip_get_index(chip)] = UVES_MASTER_FLAT(chip);
693  }
694  }
695  else if (cpl_frameset_find(frames, UVES_DFLAT(true )) != NULL ||
696  cpl_frameset_find(frames, UVES_DFLAT(false)) != NULL)
697  {
698  check( uves_load_raw_imagelist(frames,
699  flames,
700  UVES_DFLAT(true), UVES_DFLAT(false),
701  CPL_TYPE_DOUBLE,
702  raw_images, raw_headers, product_header,
703  &blue), "Error loading raw flat frames");
704  for (chip = uves_chip_get_first(blue);
705  chip != UVES_CHIP_INVALID;
706  chip = uves_chip_get_next(chip))
707  {
708  product_tag[uves_chip_get_index(chip)] = UVES_MASTER_DFLAT(chip);
709  }
710  }
711  else if (cpl_frameset_find(frames, UVES_IFLAT(true )) != NULL ||
712  cpl_frameset_find(frames, UVES_IFLAT(false)) != NULL)
713  {
714  check( uves_load_raw_imagelist(frames,
715  flames,
716  UVES_IFLAT(true), UVES_IFLAT(false),
717  CPL_TYPE_DOUBLE,
718  raw_images, raw_headers, product_header,
719  &blue), "Error loading raw flat frames");
720  for (chip = uves_chip_get_first(blue);
721  chip != UVES_CHIP_INVALID;
722  chip = uves_chip_get_next(chip))
723  {
724  product_tag[uves_chip_get_index(chip)] = UVES_MASTER_IFLAT(chip);
725  }
726  }
727  else if (cpl_frameset_find(frames, UVES_TFLAT(true )) != NULL ||
728  cpl_frameset_find(frames, UVES_TFLAT(false)) != NULL)
729  {
730  check( uves_load_raw_imagelist(frames,
731  flames,
732  UVES_TFLAT(true), UVES_TFLAT(false),
733  CPL_TYPE_DOUBLE,
734  raw_images, raw_headers, product_header,
735  &blue), "Error loading raw flat frames");
736  for (chip = uves_chip_get_first(blue);
737  chip != UVES_CHIP_INVALID;
738  chip = uves_chip_get_next(chip))
739  {
740  product_tag[uves_chip_get_index(chip)] = UVES_MASTER_TFLAT(chip);
741  }
742  }
743  else if (cpl_frameset_find(frames, UVES_SCREEN_FLAT(true )) != NULL ||
744  cpl_frameset_find(frames, UVES_SCREEN_FLAT(false)) != NULL)
745  {
746  check( uves_load_raw_imagelist(frames,
747  flames,
748  UVES_SCREEN_FLAT(true), UVES_SCREEN_FLAT(false),
749  CPL_TYPE_DOUBLE,
750  raw_images, raw_headers, product_header,
751  &blue), "Error loading raw flat frames");
752  for (chip = uves_chip_get_first(blue);
753  chip != UVES_CHIP_INVALID;
754  chip = uves_chip_get_next(chip))
755  {
756  product_tag[uves_chip_get_index(chip)] = UVES_MASTER_SCREEN_FLAT(chip);
757  }
758  }
759  else if (cpl_frameset_find(frames, UVES_SFLAT(true )) != NULL ||
760  cpl_frameset_find(frames, UVES_SFLAT(false)) != NULL)
761  {
762  check( uves_load_raw_imagelist(frames,
763  flames,
764  UVES_SFLAT(true), UVES_SFLAT(false),
765  CPL_TYPE_DOUBLE,
766  raw_images, raw_headers, product_header,
767  &blue), "Error loading raw flat frames");
768  for (chip = uves_chip_get_first(blue);
769  chip != UVES_CHIP_INVALID;
770  chip = uves_chip_get_next(chip))
771  {
772  product_tag[uves_chip_get_index(chip)] = UVES_MASTER_SFLAT(chip);
773  }
774  }
775  else
776  {
777  assure(false, CPL_ERROR_DATA_NOT_FOUND,
778  "Missing input flat frame: "
779  "%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s or %s expected",
780  UVES_FLAT(true) , UVES_FLAT(false),
781  UVES_DFLAT(true), UVES_DFLAT(false),
782  UVES_IFLAT(true), UVES_IFLAT(false),
783  UVES_TFLAT(true), UVES_TFLAT(false),
784  UVES_SCREEN_FLAT(true), UVES_SCREEN_FLAT(false),
785  UVES_SFLAT(true), UVES_SFLAT(false));
786  }
787 
788  /* Loop over one or two chips */
789  for (chip = uves_chip_get_first(blue);
790  chip != UVES_CHIP_INVALID;
791  chip = uves_chip_get_next(chip))
792  {
793 
794  if(strcmp(PROCESS_CHIP,"REDU") == 0) {
795  chip = uves_chip_get_next(chip);
796  }
797 
798  raw_index = uves_chip_get_index(chip);
799 
800  uves_msg("Processing %s chip", uves_chip_tostring_upper(chip));
801 
802  /* Chip name of first input frame */
803  check_nomsg( chip_name = uves_pfits_get_chipid(raw_headers[raw_index][0], chip));
804 
805  /* Load master bias, set pointer to NULL if not present */
806  uves_free_image(&master_bias);
807  uves_free_propertylist(&master_bias_header);
808  if (cpl_frameset_find(frames, UVES_MASTER_BIAS(chip)) != NULL)
809  {
810  uves_free_image(&master_bias);
811  uves_free_propertylist(&master_bias_header);
812  check( uves_load_mbias(frames,
813  chip_name,
814  &master_bias_filename, &master_bias,
815  &master_bias_header, chip),
816  "Error loading master bias");
817 
818  uves_msg_low("Using master bias in '%s'", master_bias_filename);
819  }
820  else
821  {
822  uves_msg_low("No master bias in SOF. Bias subtraction not done");
823  }
824 
825  /* Load master dark, set pointer to NULL if not present */
826  uves_free_image(&master_dark);
827  uves_free_propertylist(&master_dark_header);
828  if (cpl_frameset_find(frames, UVES_MASTER_DARK(chip)) != NULL ||
829  cpl_frameset_find(frames, UVES_MASTER_PDARK(chip)) != NULL)
830  {
831  uves_free_image(&master_dark);
832  uves_free_propertylist(&master_dark_header);
833  check( uves_load_mdark(frames, chip_name,
834  &master_dark_filename, &master_dark,
835  &master_dark_header, chip),
836  "Error loading master dark");
837 
838  uves_msg_low("Using master dark in '%s'", master_dark_filename);
839  }
840  else
841  {
842  uves_msg_low("No master dark in SOF. Dark subtraction not done");
843  }
844 
845  /* Load the order table for this chip */
846  if (flames)
847  /* FLAMES does not do background subtraction (here)
848  and therefore does not need an ordertable */
849  {
850  if (cpl_frameset_find(frames, UVES_ORDER_TABLE(flames, chip)) != NULL)
851  {
852  uves_msg_warning("Order table (%s) is not used in FLAMES reduction",
853  UVES_ORDER_TABLE(flames, chip));
854  }
855  }
856  else
857  {
858  uves_free_table (&ordertable);
859  uves_free_propertylist(&ordertable_header);
860  uves_polynomial_delete(&order_locations);
861  uves_free_table (&traces);
862 
863  check( uves_load_ordertable(frames,
864  flames,
865  chip_name,
866  &ordertable_filename,
867  &ordertable,
868  &ordertable_header,
869  NULL,
870  &order_locations,
871  &traces, NULL, NULL,
872  NULL, NULL, /* fibre_pos,fibre_mask */
873  chip,
874  false),
875  "Could not load order table");
876  uves_msg("Using order table in '%s'", ordertable_filename);
877  }
878 
879  /* Compute QC parameters and save */
880  uves_msg("Computing QC parameters");
881  uves_qclog_delete(&qclog[0]);
882  qclog[0] = uves_qclog_init(raw_headers[raw_index][0], chip);
883 
884  check(uves_mflat_qclog(raw_images[raw_index],
885  qclog[0]),"error computing qclog");
886 
887 
888 
889  /* Process chip */
890  uves_free_image(&master_flat);
891  uves_free_image(&background);
892  check( master_flat = uves_mflat_process_chip(
893  raw_images[raw_index], raw_headers[raw_index],
894  product_header[raw_index],
895  master_bias,
896  master_dark, master_dark_header,
897  ordertable, order_locations,
898  flames,
899  parameters,
900  chip,
901  recipe_id,
902  debug_mode,
903  &background),
904  "Error processing chip");
905 
906  /* Finished. Save */
907  uves_msg("Saving products");
908 
909  cpl_free(product_filename);
910  check( product_filename = uves_masterflat_filename(chip),
911  "Error getting filename");
912  strcpy(pro_filename,prefix);
913  strcat(pro_filename,product_filename);
914  check( uves_frameset_insert(
915  frames,
916  master_flat,
917  CPL_FRAME_GROUP_PRODUCT,
918  CPL_FRAME_TYPE_IMAGE,
919  CPL_FRAME_LEVEL_INTERMEDIATE,
920  pro_filename,
921  product_tag[raw_index],
922  raw_headers[raw_index][0],
923  product_header[raw_index],
924  NULL,
925  parameters,
926  recipe_id,
927  PACKAGE "/" PACKAGE_VERSION, qclog,
928  starttime, true, UVES_ALL_STATS),
929  "Could not add master flat %s %s to frameset",
930  product_filename, product_tag[raw_index]);
931  uves_msg("Master flat %s %s added to frameset",
932  pro_filename, product_tag[raw_index]);
933 
934  /* Save background image */
935  if (!flames)
936  {
937  cpl_free(product_filename);
938  check( product_filename = uves_masterflat_bkg_filename(chip),
939  "Error getting filename");
940  strcpy(pro_filename,prefix);
941  strcat(pro_filename,product_filename);
942 
943  check( uves_frameset_insert(frames,
944  background,
945  CPL_FRAME_GROUP_PRODUCT,
946  CPL_FRAME_TYPE_IMAGE,
947  CPL_FRAME_LEVEL_INTERMEDIATE,
948  pro_filename,
949  UVES_BKG_FLAT(chip),
950  raw_headers[raw_index][0],
951  product_header[raw_index],
952  NULL,
953  parameters,
954  recipe_id,
955  PACKAGE "/" PACKAGE_VERSION, NULL,
956  starttime, false,
957  CPL_STATS_MIN | CPL_STATS_MAX),
958  "Could not add background image '%s' to frameset",
959  product_filename);
960  uves_msg("Master flat background '%s' added to frameset",
961  product_filename);
962  }
963 
964  /* Compute and save ratio MASTER_TFLAT / REF_TFLAT */
965  if (strcmp(recipe_id, make_str(UVES_TFLAT_ID)) == 0)
966  {
967 
968  uves_free_image(&ref_flat);
969  uves_free_propertylist(&ref_flat_header);
970 
971  check( uves_load_ref_flat(frames, chip_name, &ref_flat_filename,
972  &ref_flat, &ref_flat_header,
973  chip),
974  "Error loading reference flat field");
975 
976  uves_msg("Using reference flat field in '%s'", ref_flat_filename);
977 
978  check( ratio = cpl_image_divide_create(master_flat, ref_flat),
979  "Error computing ratio of master and reference flat");
980 
981  cpl_free(product_filename);
982  check( product_filename = uves_flat_ratio_filename(chip),
983  "Error getting filename");
984 
985  check( uves_frameset_insert(frames,
986  ratio,
987  CPL_FRAME_GROUP_PRODUCT,
988  CPL_FRAME_TYPE_IMAGE,
989  CPL_FRAME_LEVEL_INTERMEDIATE,
990  product_filename,
991  UVES_RATIO_TFLAT(chip),
992  raw_headers[raw_index][0],
993  product_header[raw_index],
994  NULL,
995  parameters,
996  recipe_id,
997  PACKAGE "/" PACKAGE_VERSION,
998  qclog,
999  starttime, false,
1000  UVES_ALL_STATS),
1001  "Could not add ratio image '%s' to frameset", product_filename);
1002 
1003  uves_msg("Master flat ratio '%s' added to frameset", product_filename);
1004  }
1005 
1006 
1007  if(strcmp(PROCESS_CHIP,"REDL") == 0) {
1008  chip = uves_chip_get_next(chip);
1009  }
1010 
1011 
1012  } /* For each chip */
1013 
1014  cleanup:
1015  /* Input */
1016  if (raw_images[0] != NULL)
1017  {
1018  int i;
1019  for (i = 0; i < cpl_imagelist_get_size(raw_images[0]); i++)
1020  {
1021  if (raw_headers[0] != NULL) uves_free_propertylist(&raw_headers[0][i]);
1022  if (raw_headers[1] != NULL) uves_free_propertylist(&raw_headers[1][i]);
1023  }
1024  cpl_free(raw_headers[0]); raw_headers[0] = NULL;
1025  cpl_free(raw_headers[1]); raw_headers[1] = NULL;
1026  }
1027 
1028  uves_free_imagelist(&raw_images[0]);
1029  uves_free_imagelist(&raw_images[1]);
1030 
1031  /* Master bias */
1032  uves_free_image(&master_bias);
1033  uves_free_propertylist(&master_bias_header);
1034 
1035  /* Master dark */
1036  uves_free_image(&master_dark);
1037  uves_free_propertylist(&master_dark_header);
1038 
1039  /* Order table */
1040  uves_free_table(&ordertable);
1041  uves_free_propertylist(&ordertable_header);
1042  uves_polynomial_delete(&order_locations);
1043  uves_free_table(&traces);
1044 
1045  /* Reference master flat */
1046  uves_free_image(&ref_flat);
1047  uves_free_propertylist(&ref_flat_header);
1048 
1049  /* Output */
1050  uves_qclog_delete(&qclog[0]);
1051  uves_free_image(&master_flat);
1052  uves_free_image(&background);
1053  uves_free_image(&ratio);
1054  uves_free_propertylist(&product_header[0]);
1055  uves_free_propertylist(&product_header[1]);
1056  cpl_free(product_filename);
1057 
1058  return;
1059 }
1060 
1061 
1062 /*----------------------------------------------------------------------------*/
1068 /*----------------------------------------------------------------------------*/
1069 
1070 static void
1071 uves_mflat_qclog(const cpl_imagelist* raw_images,
1072  cpl_table* qclog)
1073 {
1074  int nraw=0;
1075 
1077  "QC TEST1 ID",
1078  "Test-on-Master-Flat",
1079  "Name of QC test",
1080  "%s"));
1081  check_nomsg(nraw=cpl_imagelist_get_size(raw_images));
1082 
1084  "PRO DATANCOM",
1085  nraw,
1086  "Number of frames combined",
1087  "%d"));
1088  cleanup:
1089  return;
1090 }