UVES Pipeline Reference Manual  5.4.0
uves_reduce_scired.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.70 $
24  * $Name: not supported by cvs2svn $
25  *
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
31 
32 /*----------------------------------------------------------------------------*/
37 /*----------------------------------------------------------------------------*/
41 /*-----------------------------------------------------------------------------
42  Includes
43  -----------------------------------------------------------------------------*/
44 #include <uves_reduce_scired.h>
45 
46 #include <uves_reduce.h>
47 #include <uves_reduce_utils.h>
48 #include <uves_corrbadpix.h>
49 
50 #include <uves_chip.h>
51 #include <uves_plot.h>
52 #include <uves_dfs.h>
53 #include <uves_pfits.h>
54 #include <uves_parameters.h>
55 #include <uves_msg.h>
56 #include <uves_utils.h>
57 #include <uves_utils_wrappers.h>
58 #include <uves_qclog.h>
59 #include <uves_error.h>
60 #include <uves_merge.h>
61 #include <uves.h>
62 #include <uves_dump.h>
63 
64 #include <cpl.h>
65 #include <string.h>
66 /*-----------------------------------------------------------------------------
67  Functions prototypes
68  -----------------------------------------------------------------------------*/
69 
70 static void
71 scired_qclog(const cpl_table* info_tbl,
72  const uves_propertylist *raw_header,
73  const cpl_image *raw_image,
74  double slit,
75  cpl_table* qclog);
76 
77 static void
78 tflat_qclog(const cpl_image* ima,
79  const uves_propertylist *raw_header,
80  cpl_table* qclog);
81 
82 
83 /*-----------------------------------------------------------------------------
84  Implementation
85  -----------------------------------------------------------------------------*/
86 const char * const uves_scired_desc_short = "Reduces a science frame";
87 const char * const uves_scired_desc =
88 "This recipe reduces a science frame (SCIENCE_BLUE or SCIENCE_RED, or\n"
89 "UVES_SCI_POINT_BLUE or UVES_SCI_POINT_RED, or \n"
90 "UVES_SCI_EXTND_BLUE or UVES_SCI_EXTND_RED or \n"
91 "UVES_SCI_SLICER_BLUE or UVES_SCI_SLICER_RED) using "
92 "a combination (depending on recipe parameters and provided input frames) of "
93 "the steps:\n"
94 " - bias subtraction,\n"
95 " - dark subtraction,\n"
96 " - background subtraction,\n"
97 " - extraction/cosmic ray removal,\n"
98 " - flat field correction,\n"
99 " - wavelength rebinning,\n"
100 " - sky subtraction,\n"
101 " - order merging,\n"
102 " - response correction (if response curve is provided).\n"
103 "\n"
104 "Additional input for this recipe are: \n"
105 "order table(s) for each chip, ORDER_TABLE_xxxx (where xxxx=BLUE, REDL, REDU),\n"
106 "line table(s) for each chip, LINE_TABLE_xxxx, a master bias frame,\n"
107 "MASTER_BIAS_xxxx, a master flat, MASTER_FLAT_xxxx, \n"
108 "optionally an instrument response table, INSTR_RESPONSE_xxx\n"
109 "optionally a table describing the atmospheric extintion,\n"
110 "EXTCOEFF_TABLE. \n"
111 "For each chip (xxxx = BLUE, REDL, REDU) the recipe produces a combination of "
112 "the products:\n"
113 " 'RED_SCIENCE_xxxx' Reduced science spectrum\n"
114 " 'MERGED_SCIENCE_xxxx' Merged spectrum, no sky subtraction\n"
115 " 'WCALIB_SCIENCE_xxxx' Extracted, wavelength calibrated frame in\n"
116 " (wavelength, order) space\n"
117 " 'WCALIB_FF_SCIENCE_xxxx' Extracted, flat-fielded, wave.cal. frame in\n"
118 " (wavelength, order) space\n"
119 " (Only if flatfielding done)\n"
120 " 'WCALIB_FLAT_OBJ_xxxx' Extracted, wavelength calibrated flat field\n"
121 " in (wavelength, order) space\n"
122 " (Only if flatfielding done)\n"
123 " 'ERRORBAR_SCIENCE_xxxx' Error bars of 'RED_SCIENCE_xxxx'\n"
124 " 'VARIANCE_SCIENCE_xxxx' Variance of extracted, flatfielded object in\n"
125 " (pixel, order) space\n"
126 " 'ORDER_TRACE_xxxx' Table describing the spatial profile\n"
127 " 'FLUXCAL_SCIENCE_xxxx' Flux-calibrated science spectrum\n"
128 " 'FLUXCAL_ERROR_xxxx' Error bars of 'FLUXCAL_SCIENCE_xxxx'\n"
129 " 'BKG_SCI_xxxx' The subtracted background image\n"
130 " 'CRMASK_xxxx' List of cosmic ray hits\n"
131 " 'MERGED_SKY_xxxx' The merged sky spectrum\n"
132 " 'EXT_2D_SCIENCE_xxxx' The 2d extracted spectrum\n"
133 " 'FF2D_SCIENCE_xxxx' The 2d extracted, flat-fielded spectrum\n"
134 " 'WCAL2D_SCIENCE_xxxx' The 2d extracted, flat-fielded, wave.cal. spectrum\n"
135 " 'MER2D_SCIENCE_xxxx' The 2d reduced, flux-calibrated (if possible) \n"
136 " science spectrum\n";
137 
138 
139 
140 
141 
142 static uves_propertylist*
143 uves_paste_wave_accuracy(const uves_propertylist* header_from)
144 {
145  uves_propertylist* header_add=NULL;
146  double waverms=0;
147  double wavenlin=0;
148  double waveerr=0;
149  double wavesys=0;
150  const char* key_comm=NULL;
151  char key_name_i[40];
152  char key_name_o[40];
153  uves_msg("paste wave accuracy");
154  header_add=uves_propertylist_new();
155 
156  sprintf(key_name_o,"CUNIT1");
157  key_comm="Wavelength units";
158  uves_propertylist_append_c_string(header_add,key_name_o,"Angstrom",key_comm);
159 
160  sprintf(key_name_i,"ESO QC LINE RESIDRMS WLU");
161  sprintf(key_name_o,"LAMRMS");
162  key_comm="RMS of wavelength solution [CUNIT1]";
163 
164  if(uves_propertylist_has(header_from,key_name_i)) {
165  waverms=uves_propertylist_get_double(header_from,key_name_i);
166  uves_propertylist_append_c_double(header_add,key_name_o,waverms,key_comm);
167 
168  }
169 
170 
171  sprintf(key_name_i,"ESO QC NLINSOL");
172  sprintf(key_name_o,"LAMNLIN");
173  key_comm="No. of lines used in wavelength solution";
174 
175  if(uves_propertylist_has(header_from,key_name_i)) {
176  wavenlin=uves_propertylist_get_int(header_from,key_name_i);
177  uves_propertylist_append_c_int(header_add,key_name_o,wavenlin,key_comm);
178 
179  }
180 
181 
182  sprintf(key_name_i,"ESO QC LINE WAVEERR");
183  sprintf(key_name_o,"CRDER1");
184  key_comm="Wavelength uncertainty [CUNIT1]";
185  if(uves_propertylist_has(header_from,key_name_i)) {
186  waveerr=uves_propertylist_get_double(header_from,key_name_i);
187  uves_propertylist_append_c_double(header_add,key_name_o,waveerr,key_comm);
188 
189  }
190 
191 
192  sprintf(key_name_i,"ESO QC LINE SYSERR");
193  sprintf(key_name_o,"CSYER1");
194  key_comm="Typical systematic wavelength error [CUNIT1]";
195  if(uves_propertylist_has(header_from,key_name_i)) {
196  wavesys=uves_propertylist_get_double(header_from,key_name_i);
197  uves_propertylist_append_c_double(header_add,key_name_o,wavesys,key_comm);
198 
199  }
200 
201  return header_add;
202 
203 }
204 
205 
206 
207 
208 /*----------------------------------------------------------------------------*/
215 /*----------------------------------------------------------------------------*/
216 int uves_scired_define_parameters_body(cpl_parameterlist *parameters,
217  const char *recipe_id)
218 {
219 
220  /*****************
221  * General *
222  *****************/
223  if (uves_define_global_parameters(parameters) != CPL_ERROR_NONE)
224  {
225  return -1;
226  }
227 
228  /**************************************
229  * detector's trap correction *
230  **************************************/
231 
232  if (uves_corr_traps_define_parameters(parameters,recipe_id)
233  != CPL_ERROR_NONE)
234  {
235  return -1;
236  }
237 
238  /*******************
239  * Reduce. *
240  ******************/
241  if (uves_propagate_parameters_step(UVES_REDUCE_ID, parameters,
242  recipe_id, NULL) != 0)
243  {
244  return -1;
245  }
246 
247  return (cpl_error_get_code() != CPL_ERROR_NONE);
248 }
249 
250 
251 const char*
252 uves_get_pro_catg_special(bool extract_is_2d, merge_method m_method) {
253  const char* result=NULL;
254  if(extract_is_2d && m_method == MERGE_NOAPPEND) {
255  result="";
256  } else if (!extract_is_2d &&
257  m_method == MERGE_NOAPPEND) {
258  result="_NONMERGED";
259  } else {
260  result="";
261  }
262 
263  return result;
264 }
265 
266 /*----------------------------------------------------------------------------*/
272 /*----------------------------------------------------------------------------*/
273 static cpl_frame **
274 set_all_raw_none(cpl_frameset *frames)
275 {
276  cpl_frame **result = NULL;
277  cpl_frame *f;
278  int i;
279 
280  result = cpl_calloc( cpl_frameset_get_size(frames) + 1,
281  sizeof(*result) );
282 
283  for (f = cpl_frameset_get_first(frames), i = 0;
284  f != NULL;
285  f = cpl_frameset_get_next(frames))
286  {
287  if (cpl_frame_get_group(f) == CPL_FRAME_GROUP_RAW)
288  {
289  /* Change + remember this frame */
290  cpl_frame_set_group(f, CPL_FRAME_GROUP_NONE);
291  result[i] = f;
292  i++;
293  }
294  }
295 
296  /* 'result' is now a NULL-terminated array of the frames that were changed */
297 
298  return result;
299 }
300 
301 /*----------------------------------------------------------------------------*/
371 /*----------------------------------------------------------------------------*/
372 
373 static cpl_error_code
374 uves_scired_process_chip(const cpl_image *raw_image,
375  const uves_propertylist *raw_header,
376  const uves_propertylist *rotated_header,
377  const cpl_image *master_bias,
378  const uves_propertylist *mbias_header,
379  const cpl_image *master_dark,
380  const uves_propertylist *mdark_header,
381  const cpl_image *master_flat,
382  const uves_propertylist *mflat_header,
383  const cpl_table *ordertable,
384  const polynomial *order_locations,
385  const cpl_table *linetable[3],
386  const uves_propertylist *linetable_header[3],
387  const polynomial *dispersion_relation[3],
388  const cpl_image *response_curve,
389  const cpl_table *master_response,
390  const uves_propertylist *response_curve_header,
391  const cpl_table *atm_extinction,
392  enum uves_chip chip,
393  /* General */
394  bool debug_mode,
395  /* Backsub */
396  /* Flat fielding */
397  /* Extraction */
398  /* Rebinning */
399  const cpl_parameterlist *parameters,
400  const char *recipe_id,
401  /* Output */
402  cpl_image **x2d, uves_propertylist **x2d_header,
403  cpl_image **fx2d,
404  cpl_image **background,
405  cpl_image **flatfielded_variance,
406  uves_propertylist **flatfielded_variance_header,
407  cpl_image **resampled_science,
408  cpl_image **resampled_mf,
409  cpl_image **rebinned_science,
410  uves_propertylist **rebinned_header,
411  cpl_image **merged_sky,
412  cpl_image **merged_science,
413  uves_propertylist **merged_header,
414  cpl_image **reduced_science,
415  cpl_image **reduced_science_error,
416  cpl_table **cosmic_mask,
417  cpl_image **wave_map,
418  cpl_image **fluxcal_science,
419  cpl_image **fluxcal_error,
420  uves_propertylist **fluxcal_header,
421  cpl_table **info_tbl,
422  double *extraction_slit,
423  cpl_table **order_trace)
424 {
425  cpl_image *rebinned_noise = NULL;
426  cpl_image *merged_noise = NULL;
427 
428  cpl_image *reduced_rebinned = NULL;
429  cpl_image *reduced_rebinned_noise = NULL;
430 
431  cpl_table *response_table = NULL;
432 
433  /* Do the science reduction. Produces wave.cal. spectra. */
434  uves_msg("Reducing science object");
435 
436  check( uves_reduce(raw_image,
437  raw_header,
438  rotated_header,
439  master_bias,
440  mbias_header,
441  master_dark,
442  mdark_header,
443  master_flat,
444  mflat_header,
445  ordertable,
446  order_locations,
447  linetable,
448  linetable_header,
449  dispersion_relation,
450  chip,
451  debug_mode,
452  parameters,
453  recipe_id,
454  "",
455  /* Output */
456  x2d,
457  x2d_header,
458  fx2d,
459  cosmic_mask,
460  wave_map,
461  background,
462  flatfielded_variance,
463  flatfielded_variance_header,
464  resampled_science,
465  resampled_mf,
466  merged_sky,
467  rebinned_science,
468  &rebinned_noise,
469  rebinned_header,
470  merged_science,
471  &merged_noise,
472  merged_header,
473  &reduced_rebinned,
474  &reduced_rebinned_noise,
475  reduced_science,
476  reduced_science_error,
477  info_tbl,
478  extraction_slit,
479  order_trace),
480  "Could not reduce frame");
481 
482  /* Plot middle row */
483  check( uves_plot_image_rows(*reduced_science,
484  1 + cpl_image_get_size_y(*reduced_science)/2,
485  1 + cpl_image_get_size_y(*reduced_science)/2, 1,
486  "Wavelength (arbitrary units)", "Relative flux",
487  "Reduced science spectrum"),
488  "Plotting failed");
489 
490 
491  /*
492  * Flux calibrate the reduced spectrum
493  * (which is an image of height 1, or more if extract.method=2d)
494  */
495 
496  if (response_curve != NULL || master_response != NULL)
497  {
498  double lambda_start;
499  double dlambda;
500  int bin;
501 
502  /* Number of spatial traces (> 1 for 2d extraction) */
503  int n_traces = cpl_image_get_size_y(*reduced_science);
504 
505  uves_msg("Flux calibrating spectrum");
506 
507  /* We cannot be certain that the formats (wavelength start, bin width)
508  of the science spectrum and the response curve are identical.
509  Therefore we interpolate the response curve at the wavelengths
510  defined by the bins of the science spectrum. */
511 
512 
513 
514  /* If the response curve is an image, convert to table.
515  This is needed for the interpolation */
516  if (response_curve != NULL) {
517  response_table = cpl_table_new(cpl_image_get_size_x(response_curve));
518  cpl_table_new_column(response_table, "LAMBDA", CPL_TYPE_DOUBLE);
519  cpl_table_new_column(response_table, "FLUX_CONV", CPL_TYPE_DOUBLE);
520 
521  check( lambda_start = uves_pfits_get_crval1(response_curve_header),
522  "Error reading response curve start wavelength from header");
523 
524  check( dlambda = uves_pfits_get_cdelt1(response_curve_header),
525  "Error reading bin width from header");
526 
527  for (bin = 1; bin <= cpl_image_get_size_x(response_curve); bin++) {
528  double lambda;
529  double response;
530  int pis_rejected;
531 
532  lambda = lambda_start + (bin-1) * dlambda;
533 
534  check( response = cpl_image_get(response_curve, bin, 1, &pis_rejected),
535  "Error reading response curve bin = %d", bin);
536 
537  check((cpl_table_set_double(response_table, "LAMBDA", bin - 1, lambda),
538  cpl_table_set_double(response_table, "FLUX_CONV", bin - 1, response)),
539  "Error updating response table at row %d", bin - 1);
540  }
541  }
542  else {
543  response_table = cpl_table_duplicate( master_response );
544  } /* Response table created */
545 
546  /*
547  * Correct for exposure time, gain, binning, atm. ext.
548  */
549 
550  check( *fluxcal_science = uves_normalize_spectrum(*reduced_science,
551  *reduced_science_error,
552  *merged_header,
553  raw_header,
554  n_traces,
555  chip,
556  atm_extinction,
557  true, /* Divide by binning? */
558  fluxcal_error),
559  "Error normalizing reduced spectrum");
560 
561  /*
562  * Flux calibrate reduced spectrum
563  * flux := flux * response
564  */
565  uves_msg("Multiplying by response function");
566  {
567  int nbins = cpl_image_get_size_x(*fluxcal_science);
568  int ntraces = cpl_image_get_size_y(*fluxcal_science);
569  double *fluxcal_science_data = cpl_image_get_data_double(*fluxcal_science);
570  double *fluxcal_science_noise = cpl_image_get_data_double(*fluxcal_error);
571 
572  check( lambda_start = uves_pfits_get_crval1(*merged_header),
573  "Error reading start wavelength from reduced science header");
574 
575  check( dlambda = uves_pfits_get_cdelt1(*merged_header),
576  "Error reading bin width from header");
577 
578  for (bin = 1; bin <= nbins; bin++)
579  {
580  double lambda;
581  double response;
582  int trace; /* Spatial traces (for 2d extracted spectra) */
583  int istart = 0;
584 
585  lambda = lambda_start + (bin-1) * dlambda;
586 
587  check( response =
588  uves_spline_hermite_table(lambda, response_table,
589  "LAMBDA", "FLUX_CONV", &istart),
590  "Error interpolating response curve at lambda = %f wlu", lambda);
591 
592  for (trace = 1; trace <= ntraces; trace++)
593  {
594  /* Don't check for bad pixels here, also correct those.
595  * The fluxcal image has the same bad pixels as the reduced_science
596  * image */
597 
598  fluxcal_science_data [(bin-1) + (trace-1)*nbins] *= response;
599  fluxcal_science_noise[(bin-1) + (trace-1)*nbins] *= response;
600 
601  /* Do not propagate the error of the response
602  curve which is negligibly small (and unknown at this point!).
603  */
604  }
605  }
606 
607  /* Plot middle row */
608  check( uves_plot_image_rows(*fluxcal_science,
609  1 + cpl_image_get_size_y(*fluxcal_science)/2,
610  1 + cpl_image_get_size_y(*fluxcal_science)/2, 1,
611  "Wavelength (arbitrary units)",
612  "Flux (10^-16 erg/cm^2/Angstrom/s)",
613  "Flux calibrated science spectrum"),
614  "Plotting failed");
615 
616  check( *fluxcal_header = uves_initialize_image_header("AWAV", " ",
617  "Angstrom", NULL,
618  "10^-16 erg/cm^2/Angstrom/s",
619  1,
620  lambda_start, 1.0,
621  1.0, 1.0,
622  dlambda, 1.0),
623  "Error initializing flux calibrated spectrum header");
624  } /* Done multiplying by response curve */
625  }
626  else
627  {
628  uves_msg("Skipping absolute flux calibration");
629  }
630 
631  cleanup:
632  uves_free_image(&rebinned_noise);
633  uves_free_image(&merged_noise);
634  uves_free_image(&reduced_rebinned_noise);
635  uves_free_image(&reduced_rebinned);
636  uves_free_table(&response_table);
637 
638  if (cpl_error_get_code() != CPL_ERROR_NONE)
639  {
640  }
641 
642  return cpl_error_get_code();
643 }
644 
645 
646 /*----------------------------------------------------------------------------*/
655 /*----------------------------------------------------------------------------*/
656 void uves_reduce_scired(cpl_frameset *frames, const cpl_parameterlist *parameters,
657  const char *recipe_id, const char *starttime)
658 {
659  /* Recipe parameters */
660  bool debug_mode;
661  bool CLEAN_TRAPS;
662  bool extract_is_2d = false; /* Are we doing a 2d reduction? */
663 
664  /* Input, raw */
665  cpl_image *raw_image[2] = {NULL, NULL};
666  uves_propertylist *raw_header[2] = {NULL, NULL};
667  uves_propertylist *rotated_header[2] = {NULL, NULL};
668 
669  /* Input, calib */
670  cpl_image *master_bias = NULL;
671  uves_propertylist *master_bias_header = NULL;
672 
673  cpl_image *master_flat = NULL;
674  uves_propertylist *master_flat_header = NULL;
675 
676  cpl_image *master_dark = NULL;
677  uves_propertylist *master_dark_header = NULL;
678 
679  cpl_table *ordertable = NULL;
680  uves_propertylist *ordertable_header= NULL;
681  polynomial *order_locations = NULL;
682  cpl_table *traces = NULL;
683 
684  /* Line tables for sky, object, sky (UVES specific) */
685  const cpl_table *linetable[3] = {NULL, NULL, NULL};
686  const uves_propertylist *linetable_header[3] = {NULL, NULL, NULL};
687  const polynomial *dispersion_relation[3] = {NULL, NULL, NULL};
688 
689  cpl_image *response_curve = NULL;
690  uves_propertylist *response_curve_header = NULL;
691  cpl_table *master_response = NULL;
692 
693  cpl_table *atm_extinction = NULL;
694 
695  /* Output */
696  /* BKG_SCI */
697  cpl_image *background = NULL;
698 
699  /* VARIANCE_SCIENCE */
700  cpl_image *flatfielded_variance = NULL;
701  uves_propertylist *flatfielded_variance_header = NULL;
702 
703  /* WCALIB_SCIENCE */
704  cpl_image *resampled_science = NULL; /* extracted -> rebinned */
705  /* WCALIB_FLAT_OBJ */
706  cpl_image *resampled_mf = NULL;
707  /* WCALIB_FF_SCIENCE */
708  cpl_image *rebinned_science = NULL; /* extracted -> ff -> rebinned */
709 
710  uves_propertylist *rebinned_header = NULL;
711 
712  /* MERGED_SKY */
713  cpl_image *merged_sky = NULL;
714 
715  /* MERGED_SCIENCE / MER2D_SCIENCE */
716  /* RED_SCIENCE */
717  /* ERRORBAR_SCIENCE */
718  cpl_image *merged_science = NULL;
719  uves_propertylist *merged_header = NULL;
720  cpl_image *reduced_science = NULL;
721  cpl_image *reduced_science_error = NULL;
722 
723 
724  /* FLUXCAL_SCIENCE / FLUXCAL_ERROR */
725  cpl_image *fluxcal_science = NULL;
726  cpl_image *fluxcal_error = NULL;
727  uves_propertylist *fluxcal_header = NULL;
728 
729  /* ORDER_TRACE */
730  cpl_table *order_trace = NULL;
731  uves_propertylist *order_trace_header = NULL;
732 
733 
734  /* EXT_2D_SCIENCE */
735  cpl_image *x2d = NULL;
736  uves_propertylist *x2d_header = NULL;
737  /* FF2D_SCIENCE */
738  cpl_image *fx2d = NULL;
739 
740  /* CRMASK */
741  cpl_table *cosmic_mask = NULL;
742  uves_propertylist *cosmic_mask_header = NULL;
743 
744  /* QC */
745  cpl_table* qclog[2] = {NULL, NULL};
746  cpl_table *qclog_tflat = NULL;
747 
748  /* Local variables */
749  const char *raw_filename = "";
750  const char *atm_ext_filename = "";
751  const char *sci_type = "";
752  cpl_frame **raw_frames = NULL; /* Array of cpl_frame pointers */
753  char *product_tag = NULL;
754  char *product_filename = NULL;
755  char *context = NULL;
756  double extraction_slit;
757 
758  bool blue = false;
759  enum uves_chip chip;
760  int binx = 0;
761  int biny = 0;
762 
763  cpl_table* info_tbl = NULL;
764  const char* PROCESS_CHIP=NULL;
765  bool red_ccd_is_new=0;
766  merge_method m_method;
767  const char* catg_is_noappend=NULL;
768  cpl_image* wave_map=NULL;
769  uves_propertylist* wave_map_header=NULL;
770  uves_propertylist* wave_acc_header=NULL;
771 
772  /* Read recipe parameters */
773  {
774  const char *ex_method = "";
775 
776  /* General */
777  check( uves_get_parameter(parameters, NULL, "uves", "debug", CPL_TYPE_BOOL, &debug_mode),
778  "Could not read parameter");
779 
780 
781 
782  check( uves_get_parameter(parameters, NULL, "uves", "debug", CPL_TYPE_BOOL, &debug_mode),
783  "Could not read parameter");
784 
785 
786 
787  check( uves_get_parameter(parameters, NULL, "uves", "process_chip", CPL_TYPE_STRING, &PROCESS_CHIP),
788  "Could not read parameter");
789  uves_string_toupper((char*)PROCESS_CHIP);
790 
791 
792  check( uves_get_parameter(parameters,NULL,recipe_id, "clean_traps", CPL_TYPE_BOOL, &CLEAN_TRAPS),
793  "Could not read parameter");
794 
795 
796 
797  /* Reduction method */
798  context = uves_sprintf("%s.%s.%s", recipe_id, UVES_REDUCE_ID, UVES_EXTRACT_ID);
799 
800  check( uves_get_parameter(parameters, NULL,
801  context, "method",
802  CPL_TYPE_STRING, &ex_method),
803  "Could not read parameter");
804 
805  extract_is_2d = (strcmp(ex_method, "2d") == 0);
806 
807  /* Load raw image and header, and identify input frame as red or blue */
808  check( uves_load_science(frames, &raw_filename, raw_image, raw_header, rotated_header,
809  &blue, &sci_type),
810  "Error loading raw frame");
811 
812  if ((strcmp(sci_type, "SCI_SLICER") == 0 ||
813  strcmp(sci_type, "SCI_EXTND" ) == 0) &&
814  strcmp(ex_method, "optimal") == 0)
815  {
816  uves_msg_warning("Going to optimally extract an extended object (%s). "
817  "This may not work because the sky cannot be "
818  "reliably determined",
819  sci_type);
820  }
821  }
822 
823  /* Load atmospheric extinction table if present */
824  if (cpl_frameset_find(frames, UVES_EXTCOEFF_TABLE) != NULL)
825  {
826  check( uves_load_atmo_ext(frames, &atm_ext_filename, &atm_extinction),
827  "Error loading atm. extinction coefficients");
828 
829  uves_msg_low("Using atmospheric extinction table in '%s'", atm_ext_filename);
830  }
831  else
832  {
833  uves_msg_low("No atmospheric extinction table. Flux calibration not done");
834  }
835 
836  check( m_method = uves_get_merge_method(parameters, recipe_id, "reduce"),
837  "Could not get merging method");
838 
839  /* Adjust parameters according to binning
840  * (note that x- and y-directions are swapped later by uves_crop_and_rotate())
841  */
842  check (binx = uves_pfits_get_binx(raw_header[0]),
843  "Could not read x binning factor from input header");
844  check (biny = uves_pfits_get_biny(raw_header[0]),
845  "Could not read y binning factor from input header");
846 
847  check_nomsg(red_ccd_is_new=uves_ccd_is_new(raw_header[0]));
848  /* Loop over one or two chips, over traces and
849  over extraction windows */
850  for (chip = uves_chip_get_first(blue);
851  chip != UVES_CHIP_INVALID;
852  chip = uves_chip_get_next(chip))
853  {
854 
855 
856 
857  if(strcmp(PROCESS_CHIP,"REDU") == 0) {
858  chip = uves_chip_get_next(chip);
859  }
860 
861  cpl_frame *mflat_frame = NULL;
862  const char *ordertable_filename = "";
863  const char *linetable_filename = "";
864  const char *master_bias_filename = "";
865  const char *master_dark_filename = "";
866  const char *master_flat_filename = "";
867  const char *response_curve_filename = "";
868  const char *chip_name = "";
869  /* const char *drs_filename = ""; not used */
870  /* Do this to skip REDL chip: chip = uves_chip_get_next(chip); */
871  int raw_index = uves_chip_get_index(chip);
872  int tracerow; /* Index of table row */
873 
874  uves_msg("Processing %s chip in '%s'",
875  uves_chip_tostring_upper(chip), raw_filename);
876 
877  check_nomsg( chip_name = uves_pfits_get_chipid(raw_header[raw_index], chip));
878 
879  uves_msg_debug("Binning = %dx%d", binx, biny);
880 
881 
882  /* Load master bias, set pointer to NULL if not present */
883  uves_free_image(&master_bias);
884  uves_free_propertylist(&master_bias_header);
885  if (cpl_frameset_find(frames, UVES_MASTER_BIAS(chip)) != NULL)
886  {
887  uves_free_image(&master_bias);
888  uves_free_propertylist(&master_bias_header);
889 
890  check( uves_load_mbias(frames, chip_name, &master_bias_filename,
891  &master_bias, &master_bias_header,
892  chip),
893  "Error loading master bias");
894 
895  uves_msg_low("Using master bias in '%s'", master_bias_filename);
896  }
897  else
898  {
899  uves_msg_low("No master bias in SOF. Bias subtraction not done");
900  }
901 
902  /* Load master dark, set pointer to NULL if not present */
903  uves_free_image(&master_dark);
904  uves_free_propertylist(&master_dark_header);
905  if (cpl_frameset_find(frames, UVES_MASTER_DARK(chip)) != NULL ||
906  cpl_frameset_find(frames, UVES_MASTER_PDARK(chip)) != NULL)
907 
908  {
909  check( uves_load_mdark(frames, chip_name, &master_dark_filename,
910  &master_dark, &master_dark_header, chip),
911  "Error loading master dark");
912 
913  uves_msg_low("Using master dark in '%s'", master_dark_filename);
914  }
915  else
916  {
917  uves_msg_low("No master dark in SOF. Dark subtraction not done");
918  }
919 
920  /* Load master flat */
921  uves_free_image(&master_flat);
922  uves_free_propertylist(&master_flat_header);
923  check( uves_load_mflat(frames, chip_name, &master_flat_filename, &master_flat,
924  &master_flat_header, chip, &mflat_frame),
925  "Error loading master flat");
926 
927  uves_msg_low("Using master flat in '%s'", master_flat_filename);
928 
929 
930  /* Load the order table for this chip */
931  uves_free_table (&ordertable);
932  uves_free_propertylist(&ordertable_header);
933  uves_polynomial_delete(&order_locations);
934  uves_free_table (&traces);
935 
936  check( uves_load_ordertable(frames,
937  false, /* FLAMES? */
938  chip_name,
939  &ordertable_filename,
940  &ordertable,
941  &ordertable_header,
942  NULL,
943  &order_locations,
944  &traces,
945  NULL, NULL,
946  NULL, NULL, /* fibre_pos,fibre_mask */
947  chip, false),
948  "Could not load order table");
949  uves_msg_low("Using order table in '%s'", ordertable_filename);
950 
951  /* Load response curve, if present.
952  Only if atm. extinction table was present. */
953  if (atm_extinction != NULL)
954  {
955  if (cpl_frameset_find(frames, UVES_INSTR_RESPONSE(chip)) != NULL ||
956  cpl_frameset_find(frames, UVES_MASTER_RESPONSE(chip)) != NULL)
957  {
958  uves_free_image(&response_curve);
959  uves_free_table(&master_response);
960  uves_free_propertylist(&response_curve_header);
961  check( uves_load_response_curve(frames, chip_name,
962  &response_curve_filename,
963  &response_curve,
964  &master_response,
965  &response_curve_header,
966  chip),
967  "Error loading response curve");
968 
969  uves_msg_low("Using %sresponse curve in '%s'",
970  master_response != NULL ? "master " : "",
971  response_curve_filename);
972  }
973  else
974  {
975  uves_msg_low("No response curve in SOF. "
976  "Flux calibration not done");
977  }
978  }
979  else
980  {
981  uves_msg_debug("There is no atmospheric extinction table. "
982  "Do not look for response curve");
983  }
984 
985  /* Loop over all traces (1 trace for UVES) */
986  for(tracerow = 0; tracerow < cpl_table_get_nrow(traces); tracerow++)
987  {
988  double trace_offset;
989  int trace_number;
990  int trace_enabled;
991  int badpixels_cleaned;
992  trace_offset = cpl_table_get_double(traces, "Offset" , tracerow, NULL);
993  trace_number = cpl_table_get_int (traces, "TraceID" , tracerow, NULL);
994  trace_enabled = cpl_table_get_int (traces, "Tracemask" , tracerow, NULL);
995 
996  if (trace_enabled != 0)
997  {
998  int window; /* window number */
999 
1000  if (cpl_table_get_nrow(traces) > 1) {
1001  uves_msg("Processing trace %d", trace_number);
1002  }
1003 
1004  /* This is UVES specific. Load linetable for the
1005  two sky windows (number 1, 3) and for the object
1006  window (number 2) */
1007 
1008  for (window = 1; window <= 3; window ++) {
1009  uves_free_table_const ( &(linetable[window-1]) );
1010  uves_free_propertylist_const( &(linetable_header[window-1]) );
1011  uves_polynomial_delete_const( &(dispersion_relation[window-1]) );
1012  check( uves_load_linetable_const(frames,
1013  false, /* FLAMES? */
1014  chip_name,
1015  order_locations,
1016  cpl_table_get_column_min(
1017  ordertable, "Order"),
1018  cpl_table_get_column_max(
1019  ordertable, "Order"),
1020  &linetable_filename,
1021  &(linetable [window-1]),
1022  &(linetable_header [window-1]),
1023  &(dispersion_relation[window-1]),
1024  NULL,
1025  chip,
1026  trace_number,
1027  window),
1028  "Could not load line table, window #%d", window);
1029 
1030  uves_msg_low("Using line table(s) in '%s'", linetable_filename);
1031 
1032  }
1033  uves_propertylist* plist=uves_propertylist_load(linetable_filename,0);
1034  uves_free_propertylist(&wave_acc_header);
1035  wave_acc_header=uves_paste_wave_accuracy(plist);
1036  uves_free_propertylist(&plist);
1037  /* end, UVES specific */
1038 
1039  /* Do the science reduction + flux calibration */
1040  uves_free_image(&x2d);
1041  uves_free_image(&fx2d);
1042  uves_free_propertylist(&x2d_header);
1043  uves_free_image(&background);
1044  uves_free_image(&flatfielded_variance);
1045  uves_free_propertylist(&flatfielded_variance_header);
1046  uves_free_image(&resampled_science);
1047  uves_free_image(&resampled_mf);
1048  uves_free_image(&rebinned_science);
1049  uves_free_propertylist(&rebinned_header);
1050  uves_free_image(&merged_sky);
1051  uves_free_image(&merged_science);
1052  uves_free_propertylist(&merged_header);
1053  uves_free_image(&reduced_science);
1054  uves_free_image(&reduced_science_error);
1055  uves_free_table(&cosmic_mask);
1056  uves_free_image(&fluxcal_science);
1057  uves_free_image(&fluxcal_error);
1058  uves_free_propertylist(&fluxcal_header);
1059  uves_free_table(&info_tbl);
1060  uves_free_table(&order_trace);
1061 
1062  if(CLEAN_TRAPS) {
1063 
1064  check( badpixels_cleaned =
1065  uves_correct_badpix_all(raw_image[raw_index],
1066  raw_header[raw_index],
1067  chip, binx, biny,
1068  false,red_ccd_is_new),
1069  "Error replacing bad pixels");
1070 
1071  uves_msg("%d bad pixels replaced",
1072  badpixels_cleaned);
1073  }
1074 
1076  raw_image[raw_index],
1077  raw_header[raw_index], /* Raw */
1078  rotated_header[raw_index],
1079  master_bias, /* Calibration */
1080  master_bias_header,
1081  master_dark,
1082  master_dark_header,
1083  master_flat,
1084  master_flat_header,
1085  ordertable,
1086  order_locations,
1087  linetable,
1088  linetable_header,
1089  dispersion_relation,
1090  response_curve,
1091  master_response,
1092  response_curve_header,
1093  atm_extinction,
1094  chip,
1095  debug_mode,
1096  parameters,
1097  recipe_id,
1098  &x2d,
1099  &x2d_header,
1100  &fx2d, /* Products */
1101  &background,
1102  &flatfielded_variance,
1103  &flatfielded_variance_header,
1104  &resampled_science,
1105  &resampled_mf,
1106  &rebinned_science,
1107  &rebinned_header,
1108  &merged_sky,
1109  &merged_science,
1110  &merged_header,
1111  &reduced_science,
1112  &reduced_science_error,
1113  &cosmic_mask,
1114  &wave_map,
1115  &fluxcal_science,
1116  &fluxcal_error,
1117  &fluxcal_header,
1118  &info_tbl,
1119  &extraction_slit,
1120  &order_trace),
1121  "Science reduction failed");
1122 
1123  if (!extract_is_2d)
1124  {
1125  uves_qclog_delete(&qclog[0]);
1126  qclog[0] = uves_qclog_init(raw_header[raw_index], chip);
1127 
1128  check( scired_qclog(info_tbl,
1129  raw_header[raw_index],
1130  raw_image[raw_index],
1131  extraction_slit,
1132  qclog[0]),
1133  "Could not compute QC parameters");
1134  }
1135 
1136  uves_msg("Saving products...");
1137  /* It is important to save products in the correct
1138  * order, because users want to identify products depending on
1139  * their number rather than the PRO-CATG (which would perhaps
1140  * make more sense).
1141  */
1142 
1143  /* Save RED_SCIENCE / RED2D_SCIENCE =
1144  (reduced_science, merged_header) */
1145  cpl_free(product_filename);
1146  check( product_filename =
1147  (extract_is_2d) ?
1148  uves_scired_red_2d_science_filename(chip) :
1149  ((m_method == MERGE_NOAPPEND) ?
1150  uves_scired_red_noappend_science_filename(chip): uves_scired_red_science_filename(chip)),
1151  "Error getting filename");
1152 
1153  cpl_free(product_tag);
1154  catg_is_noappend=uves_get_pro_catg_special(extract_is_2d,m_method);
1155  product_tag = uves_sprintf(
1156  "RED%s%s_%s_%s",
1157  catg_is_noappend,
1158  (extract_is_2d) ? "_2D" : "",
1159  sci_type, uves_chip_tostring_upper(chip));
1160 
1161  uves_propertylist_append(merged_header,wave_acc_header);
1162 
1163  check( uves_frameset_insert(frames,
1164  reduced_science,
1165  CPL_FRAME_GROUP_PRODUCT,
1166  CPL_FRAME_TYPE_IMAGE,
1167  CPL_FRAME_LEVEL_FINAL,
1168  product_filename,
1169  product_tag,
1170  raw_header[raw_index],
1171  merged_header,
1172  NULL,
1173  parameters,
1174  recipe_id,
1175  PACKAGE "/" PACKAGE_VERSION,
1176  qclog,
1177  starttime,
1178  false, /* Do not create QC log */
1179  UVES_ALL_STATS),
1180  "Could not add reduced science spectrum '%s' (%s) to frameset",
1181  product_filename, product_tag);
1182 
1183  uves_msg("Reduced science spectrum '%s' (%s) added to frameset",
1184  product_filename, product_tag);
1185 
1186  if (extract_is_2d)
1187  {
1188  /* Save EXT_2D_SCIENCE_xxxx = (x2d, x2d_header) */
1189  cpl_free(product_filename);
1190  check( product_filename = uves_scired_ext2d_filename(chip),
1191  "Error getting filename");
1192 
1193  cpl_free(product_tag);
1194  product_tag =
1195  uves_sprintf("EXT_2D_%s_%s", sci_type,
1196  uves_chip_tostring_upper(chip));
1197 
1198 
1199 
1200  check( uves_frameset_insert(frames,
1201  x2d,
1202  CPL_FRAME_GROUP_PRODUCT,
1203  CPL_FRAME_TYPE_IMAGE,
1204  CPL_FRAME_LEVEL_FINAL,
1205  product_filename,
1206  product_tag,
1207  raw_header[raw_index],
1208  x2d_header,
1209  NULL,
1210  parameters,
1211  recipe_id,
1212  PACKAGE "/" PACKAGE_VERSION,
1213  qclog,
1214  starttime, false,
1215  UVES_ALL_STATS),
1216  "Could not add 2d extracted "
1217  "spectrum '%s' (%s) to frameset",
1218  product_filename, product_tag);
1219 
1220  uves_msg("2d extracted spectrum '%s' (%s) added to frameset",
1221  product_filename, product_tag);
1222 
1223  }
1224 
1225  /* Save MERGED_SCIENCE / MER2D_SCIENCE =
1226  (merged_science, merged_header) */
1227  cpl_free(product_filename);
1228  check( product_filename = (extract_is_2d) ?
1229  uves_scired_merged_2d_science_filename(chip) :
1230  uves_scired_merged_science_filename(chip),
1231  "Error getting filename");
1232  cpl_free(product_tag);
1233  product_tag = uves_sprintf(
1234  "%s_%s_%s",
1235  (extract_is_2d) ? "MER_2D" : "MERGED",
1236  sci_type, uves_chip_tostring_upper(chip));
1237 
1238  uves_propertylist_append(merged_header,wave_acc_header);
1239 
1240  check( uves_frameset_insert(frames,
1241  merged_science,
1242  CPL_FRAME_GROUP_PRODUCT,
1243  CPL_FRAME_TYPE_IMAGE,
1244  CPL_FRAME_LEVEL_FINAL,
1245  product_filename,
1246  product_tag,
1247  raw_header[raw_index],
1248  merged_header,
1249  NULL,
1250  parameters,
1251  recipe_id,
1252  PACKAGE "/" PACKAGE_VERSION,
1253  qclog,
1254  starttime, false,
1255  UVES_ALL_STATS),
1256  "Could not add merged science spectrum '%s' (%s) to frameset",
1257  product_filename, product_tag);
1258 
1259  uves_msg("Merged science spectrum '%s' (%s) added to frameset",
1260  product_filename, product_tag);
1261 
1262  if (!extract_is_2d)
1263  {
1264  /* Save WCALIB_SCIENCE = (resampled_science, rebinned_header)
1265  * If ff_method = extract, this product was not flat-fielded
1266  */
1267  cpl_free(product_filename);
1268  check( product_filename = (extract_is_2d) ?
1269  uves_scired_resampled_2d_filename(chip) :
1270  uves_scired_resampled_filename(chip),
1271  "Error getting filename");
1272 
1273  cpl_free(product_tag);
1274  product_tag =
1275  uves_sprintf("WCALIB_%s_%s", sci_type,
1276  uves_chip_tostring_upper(chip));
1277 
1278  uves_propertylist_append(rebinned_header,wave_acc_header);
1279 
1280  check( uves_frameset_insert(frames,
1281  resampled_science,
1282  CPL_FRAME_GROUP_PRODUCT,
1283  CPL_FRAME_TYPE_IMAGE,
1284  CPL_FRAME_LEVEL_FINAL,
1285  product_filename,
1286  product_tag,
1287  raw_header[raw_index],
1288  rebinned_header,
1289  NULL,
1290  parameters,
1291  recipe_id,
1292  PACKAGE "/" PACKAGE_VERSION,
1293  qclog,
1294  starttime, false,
1295  UVES_ALL_STATS),
1296  "Could not add wavelength calibrated science "
1297  "spectrum '%s' (%s) to frameset", product_filename,
1298  product_tag);
1299 
1300  uves_msg("Wavelength calibrated science spectrum '%s' "
1301  "(%s) added to frameset", product_filename,
1302  product_tag);
1303 
1304 
1305  cpl_free(product_filename);
1306 
1307  check( product_filename =
1308  uves_order_extract_qc_standard_filename(chip),
1309  "Error getting filename");
1310 
1311 
1312  check( uves_frameset_insert(frames,
1313  info_tbl,
1314  CPL_FRAME_GROUP_PRODUCT,
1315  CPL_FRAME_TYPE_TABLE,
1316  CPL_FRAME_LEVEL_INTERMEDIATE,
1317  product_filename,
1318  UVES_ORDER_EXTRACT_QC(chip),
1319  raw_header[raw_index],
1320  rotated_header[raw_index],
1321  NULL,
1322  parameters,
1323  recipe_id,
1324  PACKAGE "/" PACKAGE_VERSION,
1325  NULL,
1326  starttime, true,
1327  0),
1328  "Could not add extraction quality table %s (%s)"
1329  , product_filename,
1330  UVES_ORDER_EXTRACT_QC(chip));
1331 
1332  uves_msg("Extraction quality table '%s' "
1333  "(%s) added to frameset", product_filename,
1334  UVES_ORDER_EXTRACT_QC(chip));
1335 
1336 
1337  } /* if not 2d extracted */
1338 
1339 
1340  {
1341  const char *ff = "";
1342 
1343  /* Read uves_scired.reduce.ffmethd */
1344  cpl_free(context);
1345  context = uves_sprintf("%s.%s", recipe_id, UVES_REDUCE_ID);
1346  check( uves_get_parameter(parameters, NULL,
1347  context,
1348  "ffmethod",
1349  CPL_TYPE_STRING, &ff),
1350  "Could not read parameter");
1351 
1352  /* If flat-fielding was done */
1353  if (strcmp(ff, "no") != 0)
1354  {
1355  /* Save WCALIB_FF_SCIENCE / WCAL2D_SCIENCE =
1356  (rebinned_science, rebinned_header) */
1357  cpl_table *qc_tabs[] = {NULL, NULL, NULL};
1358 
1359  /* QC consists of usual science QC and
1360  optionally TFLAT QC
1361  */
1362 
1363  if ( strcmp(recipe_id, make_str(UVES_TFLAT_ID)) == 0 )
1364  {
1365  uves_qclog_delete(&qclog_tflat);
1366  qclog_tflat =
1367  uves_qclog_init(raw_header[raw_index], chip);
1368 
1369  check( tflat_qclog(resampled_science,
1370  raw_header[raw_index],
1371  qclog_tflat),
1372  "Could not compute QC parameters");
1373 
1374  qc_tabs[0] = qclog_tflat;
1375  qc_tabs[1] = qclog[0];
1376  }
1377  else
1378  {
1379  qc_tabs[0] = qclog[0];
1380  qc_tabs[1] = NULL;
1381  }
1382 
1383  cpl_free(product_filename);
1384  check( product_filename =
1385  (extract_is_2d) ?
1386  uves_scired_rebinned_2d_filename(chip) :
1387  uves_scired_rebinned_filename(chip),
1388  "Error getting filename");
1389 
1390  cpl_free(product_tag);
1391  product_tag = uves_sprintf(
1392  "%s_%s_%s",
1393  (extract_is_2d) ? "WCAL_2D" : "WCALIB_FF",
1394  sci_type, uves_chip_tostring_upper(chip));
1395 
1396  uves_propertylist_append(rebinned_header,wave_acc_header);
1397 
1398  check( uves_frameset_insert(frames,
1399  rebinned_science,
1400  CPL_FRAME_GROUP_PRODUCT,
1401  CPL_FRAME_TYPE_IMAGE,
1402  CPL_FRAME_LEVEL_FINAL,
1403  product_filename,
1404  product_tag,
1405  raw_header[raw_index],
1406  rebinned_header,
1407  NULL,
1408  parameters,
1409  recipe_id,
1410  PACKAGE "/"
1411  PACKAGE_VERSION,
1412  qc_tabs,
1413  starttime, true,
1414  UVES_ALL_STATS),
1415  "Could not add wavelength calibrated flat-fielded "
1416  "science spectrum '%s' (%s) to frameset",
1417  product_filename, product_tag);
1418 
1419  uves_msg("Wavelength calibrated flat-fielded science "
1420  "spectrum '%s' (%s) added to frameset",
1421  product_filename, product_tag);
1422 
1423  if (!extract_is_2d)
1424  {
1425  /* Save WCALIB_FLAT_OBJ_xxxx =
1426  (resampled_mf, rebinned_header) */
1427  cpl_free(product_filename);
1428  check( product_filename =
1429  uves_scired_resampledmf_filename(chip),
1430  "Error getting filename");
1431 
1432  cpl_free(product_tag);
1433  product_tag =
1434  uves_sprintf(
1435  "WCALIB_FLAT_OBJ_%s",
1436  uves_chip_tostring_upper(chip));
1437  /* Independent of sci_type */
1438 
1439 
1440  /* !!!Exception!!!
1441  *
1442  * For this reduced master flat frame we
1443  * want to propagate the keywords *not*
1444  * from the first raw input frame but
1445  * from the master flat field itself.
1446  *
1447  * For that to work we temporarily set
1448  *
1449  * all raw frames := NONE
1450  * master.flat frame := RAW
1451  *
1452  * This will make cpl_dfs_setup_product_header()
1453  * find the proper "raw" frame (i.e. the mf)
1454  * Also the required 'raw_header' must be
1455  * that of the master flat frame, not science.
1456  * After propagating keywords, we change back
1457  * to normal:
1458  *
1459  * all raw frames := RAW
1460  * master.flat frame := CALIB
1461  *
1462  * (Since there could be more than 1 raw frame,
1463  * simply changing the first raw frame would
1464  * not work)
1465  */
1466 
1467  cpl_free(raw_frames);
1468  check_nomsg( raw_frames =
1469  set_all_raw_none(frames) );
1470 
1471  cpl_frame_set_group(mflat_frame,
1472  CPL_FRAME_GROUP_RAW);
1473 
1474  uves_propertylist_append(rebinned_header,wave_acc_header);
1475 
1476  check( uves_frameset_insert(
1477  frames,
1478  resampled_mf,
1479  CPL_FRAME_GROUP_PRODUCT,
1480  CPL_FRAME_TYPE_IMAGE,
1481  CPL_FRAME_LEVEL_FINAL,
1482  product_filename,
1483  product_tag,
1484  master_flat_header, /* Note! */
1485  rebinned_header,
1486  NULL,
1487  parameters,
1488  recipe_id,
1489  PACKAGE "/"
1490  PACKAGE_VERSION,
1491  NULL, /* No QC: qclog */
1492  starttime, false,
1493  CPL_STATS_MIN | CPL_STATS_MAX),
1494  "Could not add wavelength calibrated "
1495  "flat-field '%s' (%s) to frameset",
1496  product_filename, product_tag);
1497 
1498  uves_msg("Wavelength calibrated flat-field "
1499  "spectrum '%s' (%s) added to frameset",
1500  product_filename, product_tag);
1501 
1502  /* Change frames groups back to normal */
1503  {
1504  int i;
1505  for (i = 0;
1506  raw_frames[i] != NULL;
1507  i++)
1508  {
1509  cpl_frame_set_group(
1510  raw_frames[i],
1511  CPL_FRAME_GROUP_RAW);
1512  }
1513  }
1514  cpl_frame_set_group(mflat_frame,
1515  CPL_FRAME_GROUP_CALIB);
1516  }
1517 
1518  if (extract_is_2d)
1519  {
1520  /* Save FF2D_SCIENCE_xxxx = (fx2d, x2d_header) */
1521  cpl_free(product_filename);
1522  check( product_filename =
1523  uves_scired_ff2d_filename(chip),
1524  "Error getting filename");
1525 
1526  cpl_free(product_tag);
1527  product_tag =
1528  uves_sprintf(
1529  "FF_2D_%s_%s", sci_type,
1530  uves_chip_tostring_upper(chip));
1531 
1532 
1533  check( uves_frameset_insert(
1534  frames,
1535  fx2d,
1536  CPL_FRAME_GROUP_PRODUCT,
1537  CPL_FRAME_TYPE_IMAGE,
1538  CPL_FRAME_LEVEL_FINAL,
1539  product_filename,
1540  product_tag,
1541  raw_header[raw_index],
1542  x2d_header,
1543  NULL,
1544  parameters,
1545  recipe_id,
1546  PACKAGE "/"
1547  PACKAGE_VERSION,
1548  qclog,
1549  starttime, false,
1550  UVES_ALL_STATS),
1551  "Could not add 2d extracted, flat-fielded "
1552  "spectrum '%s' (%s) to frameset",
1553  product_filename, product_tag);
1554 
1555  uves_msg("2d extracted, flat-fielded spectrum "
1556  "'%s' (%s) added to frameset",
1557  product_filename, product_tag);
1558 
1559  }
1560 
1561  }/* If flat-fielding != no */
1562 
1563  check( uves_pfits_set_bunit(merged_header, "ADU"),
1564  "Error writing error spectrum header");
1565 
1566  /* Save ERRORBAR_SCIENCE_xxxx =
1567  (reduced_science_error, merged_header) */
1568  cpl_free(product_filename);
1569 
1570  check( product_filename =
1571  (extract_is_2d) ?
1572  uves_scired_red_2d_error_filename(chip) :
1573  ((m_method == MERGE_NOAPPEND) ?
1574  uves_scired_red_noappend_error_filename(chip): uves_scired_red_error_filename(chip)),
1575  "Error getting filename");
1576 
1577 
1578  cpl_free(product_tag);
1579  catg_is_noappend=uves_get_pro_catg_special(extract_is_2d,m_method);
1580  product_tag = uves_sprintf("%s%s_%s_%s",
1581  (extract_is_2d) ? "ERR_2D" : "ERRORBAR",catg_is_noappend,
1582  sci_type, uves_chip_tostring_upper(chip));
1583 
1584 /*
1585  product_tag = uves_sprintf(
1586  "%s%s_%s_%s",
1587  (m_method == MERGE_NOAPPEND) ? "ERRORBAR_NONMERGED" : "ERRORBAR",
1588  (extract_is_2d) ? "_2D" : "",
1589  sci_type, uves_chip_tostring_upper(chip));
1590 
1591 */
1592  uves_propertylist_append(merged_header,wave_acc_header);
1593 
1594  check( uves_frameset_insert(
1595  frames,
1596  reduced_science_error,
1597  CPL_FRAME_GROUP_PRODUCT,
1598  CPL_FRAME_TYPE_IMAGE,
1599  CPL_FRAME_LEVEL_FINAL,
1600  product_filename,
1601  product_tag,
1602  raw_header[raw_index],
1603  merged_header,
1604  NULL,
1605  parameters,
1606  recipe_id,
1607  PACKAGE "/" PACKAGE_VERSION,
1608  qclog,
1609  starttime, false,
1610  CPL_STATS_MIN | CPL_STATS_MAX),
1611  "Could not add error bars '%s' (%s) to frameset",
1612  product_filename, product_tag);
1613 
1614  uves_msg("Science spectrum error '%s' (%s) "
1615  "added to frameset",
1616  product_filename, product_tag);
1617 
1618 
1619  if (!extract_is_2d)
1620  {
1621 
1622 
1623  /* Save VARIANCE_SCIENCE_xxxx =
1624  (flatfielded_variance, flatfielded_variance_header) */
1625  cpl_free(product_filename);
1626  check( product_filename =
1627  uves_scired_ff_variance_filename(chip),
1628  "Error getting filename");
1629 
1630  cpl_free(product_tag);
1631  product_tag =
1632  uves_sprintf("VARIANCE_%s_%s", sci_type,
1633  uves_chip_tostring_upper(chip));
1634 
1635 
1636 
1637 
1638  check( uves_frameset_insert(frames,
1639  flatfielded_variance,
1640  CPL_FRAME_GROUP_PRODUCT,
1641  CPL_FRAME_TYPE_IMAGE,
1642  CPL_FRAME_LEVEL_FINAL,
1643  product_filename,
1644  product_tag,
1645  raw_header[raw_index],
1646  flatfielded_variance_header,
1647  NULL,
1648  parameters,
1649  recipe_id,
1650  PACKAGE "/" PACKAGE_VERSION,
1651  qclog,
1652  starttime, false,
1653  CPL_STATS_MIN | CPL_STATS_MAX),
1654  "Could not add flat-fielded spectrum variance "
1655  "'%s' (%s) to frameset",
1656  product_filename, product_tag);
1657 
1658  uves_msg("Flat-fielded spectrum variance '%s' (%s) "
1659  "added to frameset",
1660  product_filename, product_tag);
1661 
1662  } /* if not 2d extraction */
1663  }
1664 
1665  if (!extract_is_2d)
1666  {
1667  /* Save BKG_SCI_xxxx = (background, rotated_header) */
1668  cpl_free(product_filename);
1669  check( product_filename =
1670  uves_scired_background_filename(chip),
1671  "Error getting filename");
1672 
1673  cpl_free(product_tag);
1674  product_tag =
1675  uves_sprintf("BKG_SCI_%s",
1676  uves_chip_tostring_upper(chip));
1677 
1678 
1679  check( uves_frameset_insert(frames,
1680  background,
1681  CPL_FRAME_GROUP_PRODUCT,
1682  CPL_FRAME_TYPE_IMAGE,
1683  CPL_FRAME_LEVEL_FINAL,
1684  product_filename,
1685  product_tag,
1686  raw_header[raw_index],
1687  rotated_header[raw_index],
1688  NULL,
1689  parameters,
1690  recipe_id,
1691  PACKAGE "/" PACKAGE_VERSION,
1692  NULL, /* QC */
1693  starttime, false,
1694  CPL_STATS_MIN | CPL_STATS_MAX),
1695  "Could not add background image '%s' (%s) "
1696  "to frameset", product_filename, product_tag);
1697 
1698  uves_msg("Background image '%s' (%s) added to frameset",
1699  product_filename, product_tag);
1700 
1701  /* If optimal extraction, also save
1702  cosmic_mask, order_trace */
1703  if (order_trace != NULL)
1704  {
1705  /* Save ORDER_TRACE_xxxx */
1706  uves_free_propertylist(&order_trace_header);
1707  order_trace_header = uves_propertylist_new();
1708 
1709 
1710  /* !WARNING!: Duplicate code follows, be careful if/when
1711  changing. These parameters should be calculated
1712  the same way as in uves_qclog_add_sci().
1713 
1714  The MIDAS pipeline wrote these parameters only
1715  in this product, and for backwards compatibility
1716  do the same here.
1717  */
1718 
1720  order_trace_header, "ESO QC OPTEX NORD",
1721  uves_round_double(
1722  cpl_table_get_column_max(ordertable, "Order")-
1723  cpl_table_get_column_min(ordertable, "Order")+1));
1724 
1726  order_trace_header, "ESO QC OPTEX XSIZE",
1727  cpl_image_get_size_x(raw_image[raw_index]));
1728 
1730  order_trace_header, "ESO QC OPTEX YSIZE",
1731  uves_round_double(extraction_slit));
1732 
1733 
1734  cpl_free(product_filename);
1735  check( product_filename =
1736  uves_scired_ordertrace_filename(chip),
1737  "Error getting filename");
1738 
1739  cpl_free(product_tag);
1740  product_tag =
1741  uves_sprintf("ORDER_TRACE_%s",
1742  uves_chip_tostring_upper(chip));
1743 
1744 
1745  check( uves_frameset_insert(frames,
1746  order_trace,
1747  CPL_FRAME_GROUP_PRODUCT,
1748  CPL_FRAME_TYPE_TABLE,
1749  CPL_FRAME_LEVEL_FINAL,
1750  product_filename,
1751  product_tag,
1752  raw_header[raw_index],
1753  order_trace_header,
1754  NULL,
1755  parameters,
1756  recipe_id,
1757  PACKAGE "/"
1758  PACKAGE_VERSION,
1759  qclog,
1760  starttime, false,
1761  0),
1762  "Could not add sky spectrum '%s' (%s) "
1763  "to frameset",
1764  product_filename, product_tag);
1765 
1766  uves_msg("Order trace table '%s' (%s) "
1767  "added to frameset",
1768  product_filename, product_tag);
1769  }
1770 
1771 
1772 
1773  if (cosmic_mask != NULL)
1774  {
1775  /* Save CRMASK_xxxx */
1776  uves_free_propertylist(&cosmic_mask_header);
1777  cosmic_mask_header = uves_propertylist_new();
1778 
1779  cpl_free(product_filename);
1780  check( product_filename =
1781  uves_scired_crmask_filename(chip),
1782  "Error getting filename");
1783 
1784  cpl_free(product_tag);
1785  product_tag =
1786  uves_sprintf("CRMASK_%s",
1787  uves_chip_tostring_upper(chip));
1788 
1789 
1790  check( uves_frameset_insert(frames,
1791  cosmic_mask,
1792  CPL_FRAME_GROUP_PRODUCT,
1793  CPL_FRAME_TYPE_TABLE,
1794  CPL_FRAME_LEVEL_FINAL,
1795  product_filename,
1796  product_tag,
1797  raw_header[raw_index],
1798  cosmic_mask_header,
1799  NULL,
1800  parameters,
1801  recipe_id,
1802  PACKAGE "/"
1803  PACKAGE_VERSION,
1804  NULL, /* qc */
1805  starttime, false,
1806  0),
1807  "Could not add cosmic ray table "
1808  "'%s' (%s) to frameset",
1809  product_filename, product_tag);
1810 
1811  uves_msg("Cosmic ray table '%s' (%s) "
1812  "added to frameset",
1813  product_filename, product_tag);
1814  }
1815 
1816 
1817 
1818 
1819 
1820 
1821 
1822 
1823  if (wave_map != NULL)
1824  {
1825  /* Save WAVE_MAP_xxxx */
1826  uves_free_propertylist(&wave_map_header);
1827  wave_map_header = uves_propertylist_new();
1828 
1829  cpl_free(product_filename);
1830  check( product_filename =
1831  uves_scired_wmap_filename(chip),
1832  "Error getting filename");
1833 
1834  cpl_free(product_tag);
1835  product_tag =
1836  uves_sprintf("WAVE_MAP_%s",
1837  uves_chip_tostring_upper(chip));
1838  uves_pfits_set_ctype1(wave_map_header,"PIXEL");
1839  uves_pfits_set_ctype2(wave_map_header,"PIXEL");
1840  check( uves_frameset_insert(frames,
1841  wave_map,
1842  CPL_FRAME_GROUP_PRODUCT,
1843  CPL_FRAME_TYPE_IMAGE,
1844  CPL_FRAME_LEVEL_FINAL,
1845  product_filename,
1846  product_tag,
1847  raw_header[raw_index],
1848  wave_map_header,
1849  NULL,
1850  parameters,
1851  recipe_id,
1852  PACKAGE "/"
1853  PACKAGE_VERSION,
1854  NULL, /* qc */
1855  starttime, false,
1856  0),
1857  "Could not add wave map "
1858  "'%s' (%s) to frameset",
1859  product_filename, product_tag);
1860 
1861  uves_msg("Wave map '%s' (%s) "
1862  "added to frameset",
1863  product_filename, product_tag);
1864  } else {
1865  uves_msg("no wave map!!!!!!!!!");
1866  }
1867  uves_free_image(&wave_map);
1868 
1869 
1870  if (merged_sky != NULL)
1871  /* In slicer mode / 2d mode, no sky
1872  spectrum is extracted */
1873  {
1874  /* Save MERGED_SKY_xxxx =
1875  (merged_sky, merged_header) */
1876  cpl_free(product_filename);
1877  check( product_filename =
1878  uves_scired_merged_sky_filename(chip),
1879  "Error getting filename");
1880 
1881  cpl_free(product_tag);
1882  product_tag =
1883  uves_sprintf("MERGED_SKY_%s",
1884  uves_chip_tostring_upper(chip));
1885 
1886  uves_propertylist_append(merged_header,wave_acc_header);
1887 
1888 
1889  check( uves_frameset_insert(
1890  frames,
1891  merged_sky,
1892  CPL_FRAME_GROUP_PRODUCT,
1893  CPL_FRAME_TYPE_IMAGE,
1894  CPL_FRAME_LEVEL_FINAL,
1895  product_filename,
1896  product_tag,
1897  raw_header[raw_index],
1898  merged_header,
1899  NULL,
1900  parameters,
1901  recipe_id,
1902  PACKAGE "/"
1903  PACKAGE_VERSION,
1904  NULL, /* QC */
1905  starttime, false,
1906  CPL_STATS_MIN | CPL_STATS_MAX),
1907  "Could not add sky spectrum "
1908  "'%s' (%s) to frameset",
1909  product_filename, product_tag);
1910 
1911  uves_msg("Sky spectrum '%s' (%s) added to frameset",
1912  product_filename, product_tag);
1913  }
1914  else
1915  {
1916  uves_msg_low("No sky spectrum to save");
1917  }
1918 
1919  }/* if extract is 2d */
1920 
1921  if (fluxcal_science != NULL)
1922  {
1923  /* Save FLUXCAL_SCIENCE =
1924  (fluxcal_science, fluxcal_header) */
1925  cpl_free(product_filename);
1926 
1927  check( product_filename =
1928  (extract_is_2d) ?
1929  uves_scired_fluxcal_science_2d_filename(chip) :
1930  ((m_method == MERGE_NOAPPEND) ?
1931  uves_scired_fluxcal_science_noappend_filename(chip): uves_scired_fluxcal_science_filename(chip)),
1932  "Error getting filename");
1933 
1934 
1935  cpl_free(product_tag);
1936 
1937 
1938 
1939  catg_is_noappend=uves_get_pro_catg_special(extract_is_2d,m_method);
1940  product_tag = uves_sprintf("FLUXCAL%s%s_%s_%s",
1941  (extract_is_2d) ? "_2D" : "",catg_is_noappend,
1942  sci_type, uves_chip_tostring_upper(chip));
1943 
1944 
1945  /* Always _SCIENCE_, independent of sci_type */
1946 
1947  uves_propertylist_append(fluxcal_header,wave_acc_header);
1948 
1949  check( uves_frameset_insert(frames,
1950  fluxcal_science,
1951  CPL_FRAME_GROUP_PRODUCT,
1952  CPL_FRAME_TYPE_IMAGE,
1953  CPL_FRAME_LEVEL_FINAL,
1954  product_filename,
1955  product_tag,
1956  raw_header[raw_index],
1957  fluxcal_header,
1958  NULL,
1959  parameters,
1960  recipe_id,
1961  PACKAGE "/"
1962  PACKAGE_VERSION,
1963  qclog,
1964  starttime, false,
1965  CPL_STATS_MIN | CPL_STATS_MAX),
1966  "Could not add flux-calibrated science "
1967  "spectrum '%s' (%s) to frameset",
1968  product_filename, product_tag);
1969 
1970  uves_msg("Flux-calibrated science spectrum "
1971  "'%s' (%s) added to frameset",
1972  product_filename, product_tag);
1973 
1974  /* Save FLUXCAL_ERRORBAR = (fluxcal_error, fluxcal_header) */
1975  check( uves_pfits_set_bunit(fluxcal_header,
1976  "10^-16 erg/cm^2/Angstrom/s"),
1977  "Error writing error spectrum header");
1978 
1979  cpl_free(product_filename);
1980 
1981  check( product_filename =
1982  (extract_is_2d) ?
1983  uves_scired_fluxcal_error_2d_filename(chip) :
1984  ((m_method == MERGE_NOAPPEND) ?
1985  uves_scired_fluxcal_error_noappend_filename(chip): uves_scired_fluxcal_error_filename(chip)),
1986  "Error getting filename");
1987 
1988 
1989  cpl_free(product_tag);
1990 
1991 
1992  catg_is_noappend=uves_get_pro_catg_special(extract_is_2d,m_method);
1993  product_tag = uves_sprintf("FLUXCAL_ERRORBAR%s%s_%s_%s",
1994  (extract_is_2d) ? "_2D" : "",catg_is_noappend,
1995  sci_type, uves_chip_tostring_upper(chip));
1996 
1997  uves_propertylist_append(fluxcal_header,wave_acc_header);
1998 
1999  check( uves_frameset_insert(frames,
2000  fluxcal_error,
2001  CPL_FRAME_GROUP_PRODUCT,
2002  CPL_FRAME_TYPE_IMAGE,
2003  CPL_FRAME_LEVEL_FINAL,
2004  product_filename,
2005  product_tag,
2006  raw_header[raw_index],
2007  fluxcal_header,
2008  NULL,
2009  parameters,
2010  recipe_id,
2011  PACKAGE "/"
2012  PACKAGE_VERSION,
2013  qclog,
2014  starttime, false,
2015  CPL_STATS_MIN | CPL_STATS_MAX),
2016  "Could not add flux-calibrated science "
2017  "spectrum error '%s' (%s) to frameset",
2018  product_filename, product_tag);
2019 
2020  uves_msg("Flux-calibrated science spectrum error "
2021  "'%s' (%s) added to frameset",
2022  product_filename, product_tag);
2023 
2024  } /* If flux calibration done */
2025 
2026  }/* if trace is enabled */
2027  else
2028  {
2029  uves_msg("Skipping trace number %d", trace_number);
2030  }
2031 
2032 
2033  }/* for each trace */
2034 
2035 
2036  if(strcmp(PROCESS_CHIP,"REDL") == 0) {
2037  chip = uves_chip_get_next(chip);
2038  }
2039 
2040 
2041  }/* For each chip */
2042 
2043  cleanup:
2044  /* Input */
2045  uves_free_table(&info_tbl);
2046  uves_free_image(&raw_image[0]);
2047  uves_free_image(&raw_image[1]);
2048  uves_free_propertylist(&raw_header[0]);
2049  uves_free_propertylist(&raw_header[1]);
2050  uves_free_propertylist(&rotated_header[0]);
2051  uves_free_propertylist(&rotated_header[1]);
2052  uves_free_propertylist(&wave_map_header);
2053  uves_free_propertylist(&wave_acc_header);
2054 
2055  /* Input, calib */
2056  uves_free_image(&master_bias);
2057  uves_free_propertylist(&master_bias_header);
2058 
2059  uves_free_image(&master_dark);
2060  uves_free_propertylist(&master_dark_header);
2061 
2062  uves_free_image(&master_flat);
2063  uves_free_propertylist(&master_flat_header);
2064 
2065  uves_free_table(&ordertable);
2066  uves_free_propertylist(&ordertable_header);
2067  uves_polynomial_delete(&order_locations);
2068  uves_free_table(&traces);
2069 
2070  uves_free_table_const( &(linetable[0]) );
2071  uves_free_table_const( &(linetable[1]) );
2072  uves_free_table_const( &(linetable[2]) );
2073  uves_free_propertylist_const( &(linetable_header[0]) );
2074  uves_free_propertylist_const( &(linetable_header[1]) );
2075  uves_free_propertylist_const( &(linetable_header[2]) );
2076  uves_polynomial_delete_const( &(dispersion_relation[0]) );
2077  uves_polynomial_delete_const( &(dispersion_relation[1]) );
2078  uves_polynomial_delete_const( &(dispersion_relation[2]) );
2079 
2080  uves_free_image(&response_curve);
2081  uves_free_propertylist(&response_curve_header);
2082  uves_free_table(&master_response);
2083 
2084  uves_free_table(&atm_extinction);
2085 
2086  /* Output */
2087  uves_qclog_delete(&qclog[0]);
2088  uves_qclog_delete(&qclog_tflat);
2089  uves_free_image(&background);
2090  uves_free_image(&flatfielded_variance);
2091  uves_free_propertylist(&flatfielded_variance_header);
2092  uves_free_image(&rebinned_science);
2093  uves_free_propertylist(&rebinned_header);
2094  uves_free_image(&resampled_science);
2095  uves_free_image(&resampled_mf);
2096  uves_free_image(&merged_sky);
2097 
2098  uves_free_image(&merged_science);
2099  uves_free_propertylist(&merged_header);
2100  uves_free_image(&reduced_science);
2101  uves_free_image(&reduced_science_error);
2102  uves_free_image(&fluxcal_science);
2103  uves_free_image(&fluxcal_error);
2104  uves_free_propertylist(&fluxcal_header);
2105  uves_free_table(&cosmic_mask);
2106  uves_free_propertylist(&cosmic_mask_header);
2107 
2108  uves_free_table(&order_trace);
2109  uves_free_propertylist(&order_trace_header);
2110 
2111  uves_free_image(&x2d);
2112  uves_free_image(&fx2d);
2113  uves_free_propertylist(&x2d_header);
2114 
2115  cpl_free(raw_frames);
2116  cpl_free(product_filename);
2117  cpl_free(context);
2118  cpl_free(product_tag);
2119 
2120  return;
2121 }
2122 
2123 /*----------------------------------------------------------------------------*/
2132 /*----------------------------------------------------------------------------*/
2133 static void
2134 scired_qclog(const cpl_table* info_tbl,
2135  const uves_propertylist *raw_header,
2136  const cpl_image *raw_image,
2137  double slit,
2138  cpl_table* qclog)
2139 {
2140  /* This test does not exist as an official QC-TEST in the MIDAS pipeline. But
2141  the QC parameters are written to the product header */
2142 
2144  "QC TEST1 ID",
2145  "Science-Reduction-Test-Results",
2146  "Name of QC test",
2147  "%s"));
2148 
2150  raw_header,
2151  raw_image,
2152  slit,
2153  info_tbl) );
2154 
2155  cleanup:
2156  return;
2157 
2158 }
2159 
2160 /*----------------------------------------------------------------------------*/
2167 /*----------------------------------------------------------------------------*/
2168 static void
2169 tflat_qclog(const cpl_image* ima,
2170  const uves_propertylist *raw_header,
2171  cpl_table* qclog)
2172 {
2173  char key_name[80];
2174  cpl_image *window = NULL;
2175 
2176  double exptime;
2177  int nx;
2178  int ny;
2179  int i;
2180 
2182  "QC TEST1 ID",
2183  "TFLAT-QC",
2184  "Name of QC test",
2185  "%s"));
2186 
2187 
2189  uves_remove_string_prefix(UVES_INSMODE, "ESO "),
2190  uves_pfits_get_insmode(raw_header),
2191  "Instrument mode used.",
2192  "%s"));
2193 
2195  uves_remove_string_prefix(UVES_INSPATH, "ESO "),
2196  uves_pfits_get_inspath(raw_header),
2197  "Optical path used.",
2198  "%s"));
2199 
2201  uves_remove_string_prefix(UVES_SLIT1NAME, "ESO "),
2202  uves_pfits_get_slit1_name(raw_header),
2203  "Slit common name.",
2204  "%s"));
2205 
2206  check( exptime = uves_pfits_get_exptime(raw_header),
2207  "Error reading exposure time");
2208 
2209  nx = cpl_image_get_size_x(ima);
2210  ny = cpl_image_get_size_y(ima);
2211 
2212  for (i = 1; i <= ny; i++)
2213  /* Always count order numbers from 1, like MIDAS */
2214  {
2215  int size = 100;
2216  int xlo = uves_max_int(1 , (nx+1)/2 - size);
2217  int xhi = uves_min_int(nx, (nx+1)/2 + size);
2218 
2219  double min, max, avg, rms, med;
2220 
2221  uves_free_image(&window);
2222  window = cpl_image_extract(ima, xlo, i, xhi, i);
2223  assure_mem( window );
2224 
2225  if (cpl_image_count_rejected(window) >= cpl_image_get_size_x(window) - 2)
2226  {
2227  min = max = avg = rms = med = 0;
2228  }
2229  else
2230  {
2231  min = cpl_image_get_min (window) / exptime;
2232  max = cpl_image_get_max (window) / exptime;
2233  avg = cpl_image_get_mean (window) / exptime;
2234  rms = cpl_image_get_stdev (window) / exptime;
2235  med = cpl_image_get_median(window) / exptime;
2236  }
2237 
2238  sprintf(key_name, "QC ORD%d DATAMIN", i);
2240  key_name,
2241  min,
2242  "extracted order datamin",
2243  "%f"));
2244 
2245  sprintf(key_name, "QC ORD%d DATAMAX", i);
2247  key_name,
2248  max,
2249  "extracted order datamax",
2250  "%f"));
2251 
2252  sprintf(key_name, "QC ORD%d DATAAVG", i);
2254  key_name,
2255  avg,
2256  "extracted order datamean",
2257  "%f"));
2258 
2259  sprintf(key_name, "QC ORD%d DATARMS", i);
2261  key_name,
2262  rms,
2263  "extracted order datarms",
2264  "%f"));
2265 
2266  sprintf(key_name, "QC ORD%d DATAMED", i);
2268  key_name,
2269  med,
2270  "extracted order datamed",
2271  "%f"));
2272  }
2273 
2274  cleanup:
2275  uves_free_image(&window);
2276  return;
2277 
2278 }
2279