UVES Pipeline Reference Manual  5.4.0
uves_mdark_impl.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 02110-1301 USA *
18  */
19 
20 /*
21  * $Author: amodigli $
22  * $Date: 2011-01-03 08:39:09 $
23  * $Revision: 1.53 $
24  * $Name: not supported by cvs2svn $
25  * $Log: not supported by cvs2svn $
26  * Revision 1.52 2010/12/16 16:57:40 amodigli
27  * fixed compiler warnings
28  *
29  * Revision 1.51 2010/09/27 06:32:41 amodigli
30  * fixed mem leaks
31  *
32  * Revision 1.50 2010/09/24 09:32:03 amodigli
33  * put back QFITS dependency to fix problem spot by NRI on FIBER mode (with MIDAS calibs) data
34  *
35  * Revision 1.48 2010/06/11 11:40:00 amodigli
36  * add uves_qcdark_define_parameters_body(), uves_mdark_define_qc_parameters()
37  *
38  * Revision 1.47 2010/06/08 13:51:55 amodigli
39  * cleaned output
40  *
41  * Revision 1.46 2010/05/14 12:47:40 amodigli
42  * set range on several params that control QC
43  *
44  * Revision 1.45 2010/05/11 05:49:02 amodigli
45  * clarified recipe help
46  *
47  * Revision 1.44 2010/03/24 14:56:30 amodigli
48  * fixed compiler warning
49  *
50  * Revision 1.43 2010/03/22 15:57:43 amodigli
51  * added params and possibility to compute master as mean stack
52  *
53  * Revision 1.42 2010/03/01 18:00:22 amodigli
54  * fixed several bugs in computing QC parameters
55  *
56  * Revision 1.41 2008/11/06 14:36:27 amodigli
57  * fixed mem leaks
58  *
59  * Revision 1.40 2008/09/29 06:57:03 amodigli
60  * add #include <string.h>
61  *
62  * Revision 1.39 2008/03/28 08:53:50 amodigli
63  * IRPLIB_CONCAT2X-->UVES_CONCAT2X
64  *
65  * Revision 1.38 2008/02/15 12:43:49 amodigli
66  * allow lower/upper chip for parameter process_chip
67  *
68  * Revision 1.37 2007/10/05 16:01:45 amodigli
69  * using proces_chip parameter to process or not a given RED chip
70  *
71  * Revision 1.36 2007/08/31 06:27:02 amodigli
72  * include uves_globals.h
73  *
74  * Revision 1.35 2007/08/24 08:28:36 amodigli
75  * clearer parm doc
76  *
77  * Revision 1.34 2007/08/24 06:55:36 amodigli
78  * fixed parameter io for qc
79  *
80  * Revision 1.33 2007/08/21 13:08:26 jmlarsen
81  * Removed irplib_access module, largely deprecated by CPL-4
82  *
83  * Revision 1.32 2007/08/17 10:07:02 amodigli
84  * added QC params asked by DFS04195
85  *
86  * Revision 1.31 2007/06/11 13:28:26 jmlarsen
87  * Changed recipe contact address to cpl at eso.org
88  *
89  * Revision 1.30 2007/06/08 13:06:16 jmlarsen
90  * Send bug reports to Andrea
91  *
92  * Revision 1.29 2007/06/06 08:17:33 amodigli
93  * replace tab with 4 spaces
94  *
95  * Revision 1.28 2007/05/16 09:50:40 jmlarsen
96  * Do not threshold to zero after bias subtraction
97  *
98  * Revision 1.27 2007/04/24 12:50:29 jmlarsen
99  * Replaced cpl_propertylist -> uves_propertylist which is much faster
100  *
101  * Revision 1.26 2007/02/09 13:37:47 jmlarsen
102  * Enable calling from uves_cal_mkmaster
103  *
104  * Revision 1.25 2007/02/09 08:57:44 jmlarsen
105  * Include <float.h>
106  *
107  * Revision 1.24 2007/02/09 08:14:16 jmlarsen
108  * Do not use CPL_PIXEL_MAXVAL which works only for integer images
109  *
110  * Revision 1.23 2006/12/07 08:23:23 jmlarsen
111  * uves_load_raw_imagelist: support FLAMES
112  *
113  * Revision 1.22 2006/11/15 15:02:14 jmlarsen
114  * Implemented const safe workarounds for CPL functions
115  *
116  * Revision 1.20 2006/11/15 14:04:08 jmlarsen
117  * Removed non-const version of parameterlist_get_first/last/next which is
118  * already in CPL, added const-safe wrapper, unwrapper and deallocator functions
119  *
120  * Revision 1.19 2006/11/06 15:19:41 jmlarsen
121  * Removed unused include directives
122  *
123  * Revision 1.18 2006/10/17 12:33:02 jmlarsen
124  * Added semicolon at UVES_RECIPE_DEFINE invocation
125  *
126  * Revision 1.17 2006/10/09 13:01:13 jmlarsen
127  * Use macro to define recipe interface functions
128  *
129  * Revision 1.16 2006/09/19 14:31:17 jmlarsen
130  * uves_insert_frame(): use bitmap to specify which image statistics keywords must be computed
131  *
132  * Revision 1.15 2006/09/19 06:55:55 jmlarsen
133  * Changed interface of uves_frameset to optionally write image statistics kewwords
134  *
135  * Revision 1.14 2006/08/24 11:36:37 jmlarsen
136  * Write recipe start/stop time to header
137  *
138  * Revision 1.13 2006/08/17 13:56:53 jmlarsen
139  * Reduced max line length
140  *
141  * Revision 1.12 2006/08/11 14:56:05 amodigli
142  * removed Doxygen warnings
143  *
144  * Revision 1.11 2006/07/14 12:19:28 jmlarsen
145  * Support multiple QC tests per product
146  *
147  * Revision 1.10 2006/07/03 13:02:18 jmlarsen
148  * Threshold to zero after bias subtraction
149  *
150  * Revision 1.9 2006/06/28 13:29:06 amodigli
151  * removed TEST ID from QC log
152  *
153  * Revision 1.8 2006/06/16 08:25:45 jmlarsen
154  * Manually propagate ESO.DET. keywords from 1st/2nd input header
155  *
156  * Revision 1.7 2006/06/13 11:57:02 jmlarsen
157  * Check that calibration frames are from the same chip ID
158  *
159  * Revision 1.6 2006/06/01 14:43:17 jmlarsen
160  * Added missing documentation
161  *
162  * Revision 1.5 2006/05/09 07:42:18 amodigli
163  * added QC-LOG
164  *
165  * Revision 1.4 2006/04/06 12:57:22 jmlarsen
166  * Added support for PDARK, MASTER_PDARK frames
167  *
168  * Revision 1.3 2006/04/06 09:48:15 amodigli
169  * changed uves_frameset_insert interface to have QC log
170  *
171  * Revision 1.2 2006/04/06 08:37:33 jmlarsen
172  * Removed memory leak
173  *
174  * Revision 1.1 2006/02/03 07:46:30 jmlarsen
175  * Moved recipe implementations to ./uves directory
176  *
177  * Revision 1.27 2006/01/19 08:47:24 jmlarsen
178  * Insertedv missing doxygen end tag
179  *
180  * Revision 1.26 2005/12/19 16:17:55 jmlarsen
181  * Replaced bool -> int
182  *
183  */
184 
185 #ifdef HAVE_CONFIG_H
186 # include <config.h>
187 #endif
188 
189 /*----------------------------------------------------------------------------*/
196 /*----------------------------------------------------------------------------*/
197 
198 /*-----------------------------------------------------------------------------
199  Includes
200  -----------------------------------------------------------------------------*/
201 #include <uves_mdark_impl.h>
202 
203 #include <uves_parameters.h>
204 #include <uves_utils.h>
205 #include <uves.h>
206 #include <uves_dfs.h>
207 #include <uves_pfits.h>
208 #include <uves_qclog.h>
209 #include <uves_recipe.h>
210 #include <uves_utils_wrappers.h>
211 #include <uves_error.h>
212 #include <uves_globals.h>
213 
214 #include <cpl.h>
215 #include <float.h>
216 #include <string.h>
217 /*-----------------------------------------------------------------------------
218  Functions prototypes
219  -----------------------------------------------------------------------------*/
220 /*
221 static int
222 uves_qcdark_define_parameters_body(cpl_parameterlist *parameters,
223  const char *recipe_id);
224 */
225 static int
226 uves_mdark_define_parameters(cpl_parameterlist *parameters);
227 
228 static void uves_mdark_region_qc(cpl_image* img,
229  const cpl_parameterlist* p,
230  const cpl_imagelist* raw_images,
231  const char* recipe_id,
232  cpl_table* qclog);
233 static cpl_image *
234 uves_mdark_process_chip(const cpl_imagelist *raw_images,
235  uves_propertylist **raw_headers,
236  const cpl_image *master_bias,
237  uves_propertylist *mdark_header,
238  const cpl_parameterlist *parameters,
239  const char* recipe_id,
240  cpl_table* qclog, const int do_qc);
241 
242 
243 /*-----------------------------------------------------------------------------
244  Recipe standard code
245  -----------------------------------------------------------------------------*/
246 #define cpl_plugin_get_info uves_mdark_get_info
247 UVES_RECIPE_DEFINE(
248  UVES_MDARK_ID, UVES_MDARK_DOM,
249  /* Warning: if more parameters are added to this recipe, they
250  need to be propagated to uves_cal_mkmaster! */
251  uves_mdark_define_parameters,
252  "Jonas M. Larsen", "cpl@eso.org",
253  "Creates the master dark frame",
254  "This recipe creates a master dark frame by taking the median of all\n"
255  "input frames which should have identical exposure times. Symbolically,\n"
256  " masterdark = median( dark_i ) - masterbias\n"
257  "\n"
258  "The input dark frames must have same tag and size and must be either\n"
259  "(P)DARK_BLUE or (P)DARK_RED. Also, a master bias (MASTER_BIAS_xxxx) must\n"
260  "be provided for each chip (xxxx = BLUE, REDL, REDU).\n"
261  "\n"
262  "On blue input the recipe computes one master dark frame; on red input the\n"
263  "recipe produces a master dark frame for each chip (MASTER_(P)DARK_xxxx).\n");
264 
266 /*-----------------------------------------------------------------------------
267  Functions code
268  -----------------------------------------------------------------------------*/
269 
270 
271 
272 /*----------------------------------------------------------------------------*/
278 /*----------------------------------------------------------------------------*/
279 static cpl_error_code
280 uves_extract_basic_parameters_for_qc(const cpl_parameterlist* p,
281  const char* recipe_id,
282  int * pr_num_x,
283  int* pr_num_y,
284  int* pr_box_sx,
285  int* pr_box_sy)
286 {
287 
288  char name[MAX_NAME_SIZE];
289  char pname[MAX_NAME_SIZE];
290 
291  sprintf(name,"reg.num_x");
292  sprintf(pname,"%s.%s", UVES_QCDARK_ID, name);
293  uves_msg("pname=%s",pname);
294  check(uves_get_parameter(p,NULL,recipe_id,pname,CPL_TYPE_INT,pr_num_x),
295  "Could not read parameter");
296 
297  sprintf(name,"reg.num_y");
298  sprintf(pname,"%s.%s", UVES_QCDARK_ID, name);
299  check(uves_get_parameter(p,NULL,recipe_id,pname,CPL_TYPE_INT,pr_num_y),
300  "Could not read parameter");
301 
302  sprintf(name,"reg.box_sx");
303  sprintf(pname,"%s.%s", UVES_QCDARK_ID, name);
304  check(uves_get_parameter(p,NULL,recipe_id,pname,CPL_TYPE_INT,pr_box_sx),
305  "Could not read parameter");
306 
307  sprintf(name,"reg.box_sy");
308  sprintf(pname,"%s.%s", UVES_QCDARK_ID, name);
309  check(uves_get_parameter(p,NULL,recipe_id,pname,CPL_TYPE_INT,pr_box_sy),
310  "Could not read parameter");
311 
312  cleanup:
313  return cpl_error_get_code();
314 
315 }
316 
317 
318 
319 
320 
321 
322 /*----------------------------------------------------------------------------*/
328 /*----------------------------------------------------------------------------*/
329 static int
330 uves_mdark_define_parameters(cpl_parameterlist *parameters)
331 {
332  if (uves_master_stack_define_parameters(parameters,
333  make_str(UVES_MDARK_ID))
334  != CPL_ERROR_NONE)
335  {
336  return -1;
337  }
338 
339  return uves_qcdark_define_parameters_body(parameters,
340  make_str(UVES_MDARK_ID));
341 }
342 
343 /*----------------------------------------------------------------------------*/
350 /*----------------------------------------------------------------------------*/
351 int
352 uves_qcdark_define_parameters_body(cpl_parameterlist *parameters,
353  const char *recipe_id)
354 {
355  /*****************
356  * General *
357  *****************/
358  if (uves_define_global_parameters(parameters) != CPL_ERROR_NONE)
359  {
360  return -1;
361  }
362 
363  if (uves_master_stack_define_parameters(parameters,recipe_id)
364  != CPL_ERROR_NONE)
365  {
366  return -1;
367  }
368 
369 
370  /****************************
371  * Spline back.sub. *
372  ****************************/
373 
374  if (uves_propagate_parameters_step(UVES_QCDARK_ID, parameters,
375  recipe_id, NULL) != 0)
376  {
377  return -1;
378  }
379 
380  return (cpl_error_get_code() != CPL_ERROR_NONE);
381 }
382 
383 
384 
385 /*----------------------------------------------------------------------------*/
394 /*----------------------------------------------------------------------------*/
395 cpl_error_code
396 uves_mdark_define_qc_parameters(cpl_parameterlist* parameters)
397 {
398 
399  const char *name = "";
400  char *full_name = NULL;
401  cpl_parameter *p = NULL;
402 
403  {
404 
405  name = "reg.num_x";
406  full_name = uves_sprintf("%s.%s", UVES_QCDARK_ID, name);
407  uves_parameter_new_range(p, full_name,
408  CPL_TYPE_INT,
409  "Number of regions along the X axis "
410  "(where mean/med/rms are computed). ",
411  UVES_QCDARK_ID,
412  4,0,INT_MAX);
413 
414  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name );
415  cpl_parameterlist_append(parameters, p);
416  cpl_free(full_name);
417 
418 
419 
420  name = "reg.num_y";
421  full_name = uves_sprintf("%s.%s", UVES_QCDARK_ID,name);
422  uves_parameter_new_range(p, full_name,
423  CPL_TYPE_INT,
424  "Number of regions along the Y axis"
425  "(where mean/med/rms are computed). ",
426  UVES_QCDARK_ID,
427  4,0,INT_MAX);
428 
429  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
430  cpl_parameterlist_append(parameters, p);
431  cpl_free(full_name);
432 
433 
434 
435  name = "reg.box_sx";
436  full_name = uves_sprintf("%s.%s", UVES_QCDARK_ID,name);
437  uves_parameter_new_range(p, full_name,
438  CPL_TYPE_INT,
439  "Region X size [pix]",
440  UVES_QCDARK_ID,
441  100,0,INT_MAX);
442  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
443  cpl_parameterlist_append(parameters, p);
444  cpl_free(full_name);
445 
446 
447  name = "reg.box_sy";
448  full_name = uves_sprintf("%s.%s", UVES_QCDARK_ID,name);
449  uves_parameter_new_range(p, full_name,
450  CPL_TYPE_INT,
451  "Region Y size [pix]",
452  UVES_QCDARK_ID,
453  100,0,INT_MAX);
454  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
455  cpl_parameterlist_append(parameters, p);
456  cpl_free(full_name);
457 
458  name = "reg.border_x";
459  full_name = uves_sprintf("%s.%s", UVES_QCDARK_ID,name);
460  uves_parameter_new_range(p, full_name,
461  CPL_TYPE_INT,
462  "X distance between the left hand side "
463  "of the detector and the left hand side "
464  "of the region [pix]",
465  UVES_QCDARK_ID,
466  100,0,INT_MAX);
467  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
468  cpl_parameterlist_append(parameters, p);
469  cpl_free(full_name);
470 
471 
472  name = "reg.border_y";
473  full_name = uves_sprintf("%s.%s", UVES_QCDARK_ID,name);
474  uves_parameter_new_range(p, full_name,
475  CPL_TYPE_INT,
476  "X distance between the left hand side "
477  "of the detector and the left hand side "
478  "of the region [pix]",
479  UVES_QCDARK_ID,
480  100,0,INT_MAX);
481  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
482  cpl_parameterlist_append(parameters, p);
483  cpl_free(full_name);
484 
485 
486 
487  name = "reg.when";
488  full_name = uves_sprintf("%s.%s", UVES_QCDARK_ID,name);
489  uves_parameter_new_enum(p, full_name,
490  CPL_TYPE_INT,
491  "When QC analysis is performed. "
492  "0: on each raw frame or "
493  "1: on the master frame",
494  UVES_QCDARK_ID,
495  0,2,0,1);
496  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
497  cpl_parameterlist_append(parameters, p);
498  cpl_free(full_name);
499 
500 
501  }
502 
503  if (cpl_error_get_code() != CPL_ERROR_NONE)
504  {
505  cpl_msg_error(__func__, "Creation of mdark parameters failed: '%s'",
506  cpl_error_get_where());
507  cpl_parameterlist_delete(parameters);
508  }
509  return cpl_error_get_code();
510 }
511 
512 
513 /*----------------------------------------------------------------------------*/
521 /*----------------------------------------------------------------------------*/
522 cpl_parameterlist *
523 uves_qcdark_define_parameters(void)
524 {
525 
526  cpl_parameterlist *parameters = NULL;
527 
528  parameters = cpl_parameterlist_new();
529 
530  check(uves_mdark_define_qc_parameters(parameters),
531  "Error defining mdark qc parameters");
532 
533 
534  cleanup:
535  if (cpl_error_get_code() != CPL_ERROR_NONE)
536  {
537  cpl_msg_error(__func__, "Creation of mdark parameters failed: '%s'",
538  cpl_error_get_where());
539  cpl_parameterlist_delete(parameters);
540  return NULL;
541  } else {
542  return parameters;
543  }
544 }
545 
546 
547 
548 
549 
550 /*----------------------------------------------------------------------------*/
570 /*----------------------------------------------------------------------------*/
571 static cpl_image *
572 uves_mdark_process_chip(const cpl_imagelist *raw_images,
573  uves_propertylist **raw_headers,
574  const cpl_image *master_bias,
575  uves_propertylist *mdark_header,
576  const cpl_parameterlist *parameters,
577  const char* recipe_id,
578  cpl_table* qclog,const int do_qc)
579 {
580  cpl_image *master_dark = NULL; /* Result */
581  cpl_image *current_dark = NULL;
582  cpl_imagelist *preproc_images = NULL;
583  double min_exptime = 0;
584  double max_exptime = 0;
585  int i;
586  //char name[MAX_NAME_SIZE];
587  //char pname[MAX_NAME_SIZE];
588 
589  int pr_num_x=4;
590  int pr_num_y=4;
591  int pr_box_sx=100;
592  int pr_box_sy=100;
593  const char* STACK_METHOD=NULL;
594  double STACK_KLOW=0;
595  double STACK_KHIGH=0;
596  int STACK_NITER=0;
597 
598 /* check critical QC parameters to see if QC need to be computed or not */
599 
600  check_nomsg(uves_extract_basic_parameters_for_qc(parameters,recipe_id,
601  &pr_num_x,&pr_num_y,
602  &pr_box_sx,&pr_box_sy));
603 
604 /* parameters for stacking */
605  check( uves_get_parameter(parameters, NULL, recipe_id, "stack_method", CPL_TYPE_STRING, &STACK_METHOD),
606  "Could not read parameter");
607 
608  uves_string_toupper((char*)STACK_METHOD);
609 
610  check( uves_get_parameter(parameters, NULL, recipe_id, "klow", CPL_TYPE_DOUBLE, &STACK_KLOW),
611  "Could not read parameter");
612  check( uves_get_parameter(parameters, NULL, recipe_id, "khigh", CPL_TYPE_DOUBLE, &STACK_KHIGH),
613  "Could not read parameter");
614  check( uves_get_parameter(parameters, NULL, recipe_id, "niter", CPL_TYPE_INT, &STACK_NITER),
615  "Could not read parameter");
616 
617 
618 
619  /* First process each input image and store the results in a
620  new image list */
621 
622  preproc_images = cpl_imagelist_new();
623  for (i = 0; i < cpl_imagelist_get_size(raw_images); i++)
624  {
625  double exposure_time = 0.0;
626  const uves_propertylist *current_header;
627 
628  current_dark = cpl_image_duplicate(cpl_imagelist_get_const(raw_images, i));
629  current_header = raw_headers[i];
630 
631  /* Subtract master bias */
632  if (master_bias != NULL)
633  {
634  uves_msg("Subtracting master bias");
635  check( uves_subtract_bias(current_dark, master_bias),
636  "Error subtracting master bias");
637 
638  if (false) {
639  uves_msg_debug("Thresholding to non-negative values");
640  check( cpl_image_threshold(current_dark,
641  0, DBL_MAX, /* Interval */
642  0, DBL_MAX), /* New values */
643  "Error thresholding image");
644  }
645  }
646  else
647  {
648  uves_msg("Skipping bias subtraction");
649  }
650 
651  check( exposure_time = uves_pfits_get_exptime(current_header),
652  "Error reading exposure time");
653 
654  if(pr_num_x != 0 && pr_num_y != 0 && pr_box_sx != 0 && pr_box_sy !=0 ) {
655  if(do_qc == 0) {
656  uves_msg("Calculating QC parameters on raw dark frame %d",i);
657  uves_mdark_region_qc(current_dark,parameters,raw_images,recipe_id,qclog);
658  }
659 
660  }
661  /* Initialize/update min/max exposure time*/
662  if (i == 0 || exposure_time < min_exptime)
663  {
664  min_exptime = exposure_time;
665  }
666  if (i == 0 || exposure_time > max_exptime)
667  {
668  max_exptime = exposure_time;
669  }
670 
671  /* Do not normalize to unit exposure time */
672 /* If this is uncommented, then remember to also calculate the
673  correct master dark exposure time below.
674  uves_msg("Normalizing from %f s to unit exposure time", exposure_time);
675  check( cpl_image_divide_scalar(current_dark, exposure_time),
676  "Error normalizing dark frame"); */
677 
678  /* Append to imagelist */
679  check( cpl_imagelist_set(preproc_images,
680  current_dark,
681  i), /* Position (number_of_images=>append) */
682  "Could not insert image into image list");
683 
684  /* Don't deallocate the image. It will be deallocated when
685  the image list is deallocated */
686  current_dark = NULL;
687  }
688 
689  /* Check exposure times */
690  uves_msg("Exposure times range from %e s to %e s (%e %% variation)",
691  min_exptime,
692  max_exptime,
693  100 * (max_exptime - min_exptime) / min_exptime);
694 
695  if ((max_exptime - min_exptime) / min_exptime > .001)
696  {
697  uves_msg_warning("Exposure times differ by %e %%",
698  100 * (max_exptime - min_exptime) / min_exptime);
699  }
700 
701  /* Get median stack of input darks */
702  if(strcmp(STACK_METHOD,"MEDIAN")==0) {
703  uves_msg("Calculating stack median");
704  check( master_dark = cpl_imagelist_collapse_median_create(preproc_images),
705  "Error computing median");
706  } else {
707  uves_msg("Calculating stack mean");
708  check( master_dark = uves_ksigma_stack(preproc_images,STACK_KLOW,
709  STACK_KHIGH,STACK_NITER),
710  "Error computing master dark");
711 
712  }
713  check( uves_pfits_set_exptime(mdark_header, (max_exptime + min_exptime)/2),
714  "Error setting master dark exposure time");
715 
716  cleanup:
717  uves_free_image(&current_dark);
718  uves_free_imagelist(&preproc_images);
719  if (cpl_error_get_code() != CPL_ERROR_NONE)
720  {
721  uves_free_image(&master_dark);
722  }
723 
724  return master_dark;
725 }
726 
727 
728 /*----------------------------------------------------------------------------*/
735 /*----------------------------------------------------------------------------*/
736 static void
737 UVES_CONCAT2X(UVES_MDARK_ID,exe)(cpl_frameset *frames,
738  const cpl_parameterlist *parameters,
739  const char *starttime)
740 {
741  uves_mdark_exe_body(frames, parameters, starttime, make_str(UVES_MDARK_ID));
742  return;
743 }
744 
745 /*----------------------------------------------------------------------------*/
757 /*----------------------------------------------------------------------------*/
758 void
759 uves_mdark_exe_body(cpl_frameset *frames,
760  const cpl_parameterlist *parameters,
761  const char *starttime,
762  const char *recipe_id)
763 {
764  /* Function id */
765  /*
766  * Variables that will contain the values of the recipe parameters
767  */
768  /* None */
769 
770  /* CPL objects */
771  /* Input */
772  cpl_imagelist *raw_images[2] = {NULL, NULL};
773  uves_propertylist **raw_headers[2] = {NULL, NULL}; /* Two arrays of pointers */
774 
775  /* Master bias */
776  cpl_image *master_bias = NULL;
777  uves_propertylist *master_bias_header = NULL;
778 
779  /* Output */
780  cpl_table* qclog[2] = {NULL, NULL};
781  cpl_image *master_dark = NULL;
782  uves_propertylist *product_header[2] = {NULL, NULL};
783 
784  /* Local variables */
785  char *product_filename = NULL;
786  const char *product_tag[2] = {NULL, NULL};
787  bool blue;
788  enum uves_chip chip;
789 
790  const char* pname=NULL;
791 
792 
793  int pr_when=0;
794  const char* PROCESS_CHIP=NULL;
795  int pr_num_x=0;
796  int pr_num_y=0;
797  int pr_box_sx=0;
798  int pr_box_sy=0;
799  bool dump_qc=true;
800 
801  /* Load and check raw dark images and headers, identify arm (blue/red) */
802  /* On success, 'raw_headers' will be an array with the same size as 'raw_images' */
803  if (cpl_frameset_find(frames, UVES_DARK(true )) != NULL ||
804  cpl_frameset_find(frames, UVES_DARK(false)) != NULL)
805  {
806  check( uves_load_raw_imagelist(frames,
807  false, /* FLAMES format? */
808  UVES_DARK(true), UVES_DARK(false),
809  CPL_TYPE_DOUBLE,
810  raw_images, raw_headers, product_header,
811  &blue), "Error loading raw dark frames");
812 
813  for (chip = uves_chip_get_first(blue);
814  chip != UVES_CHIP_INVALID;
815  chip = uves_chip_get_next(chip))
816  {
817  product_tag[uves_chip_get_index(chip)] = UVES_MASTER_DARK(chip);
818  }
819  }
820  else if (cpl_frameset_find(frames, UVES_PDARK(true )) != NULL ||
821  cpl_frameset_find(frames, UVES_PDARK(false)) != NULL)
822  {
823  check( uves_load_raw_imagelist(frames,
824  false, /* FLAMES format? */
825  UVES_PDARK(true), UVES_PDARK(false),
826  CPL_TYPE_DOUBLE,
827  raw_images, raw_headers, product_header,
828  &blue), "Error loading raw dark frames");
829 
830  for (chip = uves_chip_get_first(blue);
831  chip != UVES_CHIP_INVALID;
832  chip = uves_chip_get_next(chip))
833  {
834  product_tag[uves_chip_get_index(chip)] = UVES_MASTER_PDARK(chip);
835  }
836  }
837  else
838  {
839  assure(false, CPL_ERROR_DATA_NOT_FOUND,
840  "Missing input dark frame: %s, %s, %s or %s expected",
841  UVES_DARK(true) , UVES_DARK(false),
842  UVES_PDARK(true), UVES_PDARK(false));
843  }
844 
845 
846 
847  check_nomsg(uves_extract_basic_parameters_for_qc(parameters,recipe_id,
848  &pr_num_x,&pr_num_y,
849  &pr_box_sx,&pr_box_sy));
850 
851  if(pr_num_x <=0 || pr_num_y <= 0 || pr_box_sx <=0 || pr_box_sy <= 0) {
852  dump_qc=false;
853  }
854  pname = uves_sprintf("%s.%s", UVES_QCDARK_ID, "reg.when");
855  check(uves_get_parameter(parameters,NULL,recipe_id,pname,CPL_TYPE_INT,&pr_when),
856  "Could not read parameter");
857 
858  check( uves_get_parameter(parameters, NULL, "uves", "process_chip", CPL_TYPE_STRING, &PROCESS_CHIP),
859  "Could not read parameter");
860  uves_string_toupper((char*)PROCESS_CHIP);
861 
862 
863  /* Loop over one or two chips */
864  for (chip = uves_chip_get_first(blue);
865  chip != UVES_CHIP_INVALID;
866  chip = uves_chip_get_next(chip))
867  {
868 
869  if(strcmp(PROCESS_CHIP,"REDU") == 0) {
870  chip = uves_chip_get_next(chip);
871  }
872 
873  const char *master_bias_filename = "";
874  const char *chip_name = "";
875 
876  int raw_index = uves_chip_get_index(chip);
877 
878  uves_msg("Processing %s chip",
880 
881  /* Get chip name of first input frame */
882  check_nomsg( chip_name = uves_pfits_get_chipid(raw_headers[raw_index][0], chip));
883 
884  /* Load master bias, set pointer to NULL if not present */
885  uves_free_image(&master_bias);
886  uves_free_propertylist(&master_bias_header);
887  if (cpl_frameset_find(frames, UVES_MASTER_BIAS(chip)) != NULL)
888  {
889  check( uves_load_mbias(frames, chip_name,
890  &master_bias_filename, &master_bias,
891  &master_bias_header, chip),
892  "Error loading master bias");
893 
894  uves_msg_low("Using master bias in '%s'", master_bias_filename);
895  }
896  else
897  {
898  uves_msg_low("No master bias in SOF. Bias subtraction not done");
899  }
900 
901  /* Process chip */
902 
903 
904 
905  uves_free_image(&master_dark);
906  uves_qclog_delete(&qclog[0]);
907  qclog[0] = uves_qclog_init(raw_headers[raw_index][0], chip);
908  check( master_dark = uves_mdark_process_chip(raw_images[raw_index],
909  raw_headers[raw_index],
910  master_bias,
911  product_header[raw_index],
912  parameters,recipe_id,
913  qclog[0],pr_when),
914  "Error processing chip");
915 
916 
917  /* Finished. Save */
918  /* Finished. Calculate QC parameters and save */
919  if(pr_when==1) {
920  uves_msg("Calculating QC parameters on master dark frame");
921  uves_mdark_region_qc(master_dark,parameters,
922  raw_images[raw_index],recipe_id,qclog[0]);
923 
924  }
925 
926  /* Insert into frame set */
927  uves_msg("Saving product");
928 
929  cpl_free(product_filename);
930  check( product_filename = uves_masterdark_filename(chip), "Error getting filename");
931 
932 
933  check( uves_frameset_insert(frames,
934  master_dark,
935  CPL_FRAME_GROUP_PRODUCT,
936  CPL_FRAME_TYPE_IMAGE,
937  CPL_FRAME_LEVEL_INTERMEDIATE,
938  product_filename,
939  product_tag[raw_index],
940  raw_headers[raw_index][0],
941  product_header[raw_index],
942  NULL,
943  parameters,
944  recipe_id,
945  PACKAGE "/" PACKAGE_VERSION,qclog,
946  starttime, dump_qc,
947  UVES_ALL_STATS),
948  "Could not add master dark %s to frameset", product_filename);
949  uves_msg("Master dark %s added to frameset", product_filename);
950  uves_qclog_delete(&qclog[0]);
951 
952  if(strcmp(PROCESS_CHIP,"REDL") == 0) {
953  chip = uves_chip_get_next(chip);
954  }
955 
956 
957  }/* For each chip */
958 
959  cleanup:
960  /* Input */
961  if (raw_images[0] != NULL)
962  {
963  int i;
964  for (i = 0; i < cpl_imagelist_get_size(raw_images[0]); i++)
965  {
966  if (raw_headers[0] != NULL) uves_free_propertylist(&raw_headers[0][i]);
967  if (raw_headers[1] != NULL) uves_free_propertylist(&raw_headers[1][i]);
968  }
969 
970  cpl_free(raw_headers[0]); raw_headers[0] = NULL;
971  cpl_free(raw_headers[1]); raw_headers[1] = NULL;
972  }
973 
974  uves_free_imagelist(&raw_images[0]);
975  uves_free_imagelist(&raw_images[1]);
976 
977  /* Master bias */
978  uves_free_image(&master_bias);
979  uves_free_propertylist(&master_bias_header);
980 
981  /* Output */
982  uves_qclog_delete(&qclog[0]);
983  uves_free_image(&master_dark);
984  uves_free_propertylist(&product_header[0]);
985  uves_free_propertylist(&product_header[1]);
986  cpl_free(product_filename);
987  uves_free(pname);
988  return;
989 }
990 
991 
992 static void
993 uves_mdark_region_qc(cpl_image* img,
994  const cpl_parameterlist* p,
995  const cpl_imagelist* raw_images,
996  const char* recipe_id,
997  cpl_table* qclog)
998 {
999 
1000  int pr_num_x=4;
1001  int pr_num_y=4;
1002  int pr_box_sx=100;
1003  int pr_box_sy=100;
1004  int pr_border_x=100;
1005  int pr_border_y=100;
1006 
1007 
1008  int i=0;
1009  int j=0;
1010  int llx=0;
1011  int lly=0;
1012  int urx=0;
1013  int ury=0;
1014  int space_x=0;
1015  int space_y=0;
1016  int sx=0;
1017  int sy=0;
1018  int nraw=0;
1019  int raw=0;
1020  char name[MAX_NAME_SIZE];
1021  char pname[MAX_NAME_SIZE];
1022  char qc_key[MAX_NAME_SIZE];
1023  char qc_com[MAX_NAME_SIZE];
1024  double qc_avg=0;
1025  double qc_med=0;
1026  double qc_rms=0;
1027  double qc_min=0;
1028  double qc_max=0;
1029  cpl_table* qc_sto=NULL;
1030 
1031  check_nomsg(uves_extract_basic_parameters_for_qc(p,recipe_id,
1032  &pr_num_x,&pr_num_y,
1033  &pr_box_sx,&pr_box_sy));
1034 
1035  uves_msg("pr_num_x=%d pr_num_y=%d pr_box_sx=%d pr_box_sy=%d",
1036  pr_num_x,pr_num_y,pr_box_sx,pr_box_sy);
1037 
1038  if(pr_num_x <= 0 || pr_num_y <= 0 || pr_box_sx <= 0 || pr_box_sy <= 0) {
1039  return;
1040  }
1041 
1042  sprintf(name,"reg.border_x");
1043  sprintf(pname,"%s.%s", UVES_QCDARK_ID, name);
1044  check(uves_get_parameter(p,NULL,recipe_id,pname,CPL_TYPE_INT,&pr_border_x),
1045  "Could not read parameter");
1046 
1047  sprintf(name,"reg.border_y");
1048  sprintf(pname,"%s.%s", UVES_QCDARK_ID, name);
1049  check(uves_get_parameter(p,NULL,recipe_id,pname,CPL_TYPE_INT,&pr_border_y),
1050  "Could not read parameter");
1051 
1052 
1053  check_nomsg(nraw=cpl_imagelist_get_size(raw_images));
1055  "PRO DATANCOM",
1056  nraw,
1057  "Number of frames combined",
1058  "%d"));
1059 
1060  sx=cpl_image_get_size_x(img);
1061  sy=cpl_image_get_size_y(img);
1062  space_x=(int)((sx-2*pr_border_x)/pr_num_x);
1063  space_y=(int)((sy-2*pr_border_y)/pr_num_y);
1064  qc_sto=cpl_table_new(pr_num_x*pr_num_y);
1065  cpl_table_new_column(qc_sto,"MIN",CPL_TYPE_DOUBLE);
1066  cpl_table_new_column(qc_sto,"MAX",CPL_TYPE_DOUBLE);
1067  cpl_table_new_column(qc_sto,"AVG",CPL_TYPE_DOUBLE);
1068  cpl_table_new_column(qc_sto,"MED",CPL_TYPE_DOUBLE);
1069  cpl_table_new_column(qc_sto,"RMS",CPL_TYPE_DOUBLE);
1070 
1071  for(i=0;i<pr_num_x;i++) {
1072  llx=pr_border_x+i*space_x;
1073  urx=llx+pr_box_sx;
1074 
1075  llx=(llx>0) ? llx:1;
1076  urx=(urx<=sx) ? urx:sx;
1077 
1078  for(j=0;j<pr_num_y;j++) {
1079  lly=pr_border_y+j*space_y;
1080  ury=lly+pr_box_sy;
1081 
1082  lly=(lly>0) ? lly:1;
1083  ury=(ury<=sy) ? ury:sy;
1084 
1085  raw=i*pr_num_y+j;
1086  check_nomsg(qc_min=cpl_image_get_min_window(img,llx,lly,urx,ury));
1087  qc_max=cpl_image_get_min_window(img,llx,lly,urx,ury);
1088  qc_avg=cpl_image_get_mean_window(img,llx,lly,urx,ury);
1089  qc_med=cpl_image_get_median_window(img,llx,lly,urx,ury);
1090  qc_rms=cpl_image_get_stdev_window(img,llx,lly,urx,ury);
1091  uves_msg_debug("QC on area [%d,%d:%d,%d]. Min %g Max %g Avg %g Med %g Rms %g",
1092  llx,lly,urx,ury,qc_min,qc_max,qc_avg,qc_med,qc_rms);
1093 
1094  sprintf(qc_key,"%s%d%d%s","QC REG",i,j," MIN");
1095  sprintf(qc_com,"%s%d%d","Min of region [%d,%d]",i,j);
1096  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_min,qc_com,"%g"));
1097  check_nomsg(cpl_table_set_double(qc_sto,"MIN",raw,qc_min));
1098 
1099  sprintf(qc_key,"%s%d%d%s","QC REG",i,j," MAX");
1100  sprintf(qc_com,"%s%d%d","Max of region [%d,%d]",i,j);
1101  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_max,qc_com,"%g"));
1102  check_nomsg(cpl_table_set_double(qc_sto,"MAX",raw,qc_max));
1103 
1104  sprintf(qc_key,"%s%d%d%s","QC REG",i,j," AVG");
1105  sprintf(qc_com,"%s%d%d","Mean of region [%d,%d]",i,j);
1106  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_avg,qc_com,"%g"));
1107  check_nomsg(cpl_table_set_double(qc_sto,"AVG",raw,qc_avg));
1108 
1109  sprintf(qc_key,"%s%d%d%s","QC REG",i,j," MED");
1110  sprintf(qc_com,"%s%d%d","Median of region [%d,%d]",i,j);
1111  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_med,qc_com,"%g"));
1112  check_nomsg(cpl_table_set_double(qc_sto,"MED",raw,qc_med));
1113 
1114  sprintf(qc_key,"%s%d%d%s","QC REG",i,j," RMS");
1115  sprintf(qc_com,"%s%d%d","Rms of region [%d,%d]",i,j);
1116  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_rms,qc_com,"%g"));
1117  check_nomsg(cpl_table_set_double(qc_sto,"RMS",raw,qc_rms));
1118 
1119 
1120  }
1121  }
1122 
1123 
1124  check_nomsg(qc_min=cpl_table_get_column_min(qc_sto,"MIN"));
1125  check_nomsg(qc_max=cpl_table_get_column_max(qc_sto,"MIN"));
1126  check_nomsg(qc_avg=cpl_table_get_column_mean(qc_sto,"MIN"));
1127  check_nomsg(qc_med=cpl_table_get_column_median(qc_sto,"MIN"));
1128  check_nomsg(qc_rms=cpl_table_get_column_stdev(qc_sto,"MIN"));
1129 
1130  sprintf(qc_key,"%s","QC REG MIN MIN");
1131  sprintf(qc_com,"%s","Min of all Mins");
1132  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_min,qc_com,"%g"));
1133 
1134  sprintf(qc_key,"%s","QC REG MIN MAX");
1135  sprintf(qc_com,"%s","Max of all Mins");
1136  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_max,qc_com,"%g"));
1137 
1138  sprintf(qc_key,"%s","QC REG MIN AVG");
1139  sprintf(qc_com,"%s","Mean of all Mins");
1140  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_avg,qc_com,"%g"));
1141 
1142  sprintf(qc_key,"%s","QC REG MIN MED");
1143  sprintf(qc_com,"%s","Median of all Mins");
1144  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_med,qc_com,"%g"));
1145 
1146  sprintf(qc_key,"%s","QC REG MIN RMS");
1147  sprintf(qc_com,"%s","Rms of all Mins");
1148  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_rms,qc_com,"%g"));
1149 
1150 
1151 
1152  check_nomsg(qc_min=cpl_table_get_column_min(qc_sto,"MAX"));
1153  check_nomsg(qc_max=cpl_table_get_column_max(qc_sto,"MAX"));
1154  check_nomsg(qc_avg=cpl_table_get_column_mean(qc_sto,"MAX"));
1155  check_nomsg(qc_med=cpl_table_get_column_median(qc_sto,"MAX"));
1156  check_nomsg(qc_rms=cpl_table_get_column_stdev(qc_sto,"MAX"));
1157 
1158  sprintf(qc_key,"%s","QC REG MAX MIN");
1159  sprintf(qc_com,"%s","Min of all Maxs");
1160  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_min,qc_com,"%g"));
1161 
1162  sprintf(qc_key,"%s","QC REG MAX MAX");
1163  sprintf(qc_com,"%s","Max of all Maxs");
1164  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_max,qc_com,"%g"));
1165 
1166  sprintf(qc_key,"%s","QC REG MAX AVG");
1167  sprintf(qc_com,"%s","Mean of all Maxs");
1168  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_avg,qc_com,"%g"));
1169 
1170  sprintf(qc_key,"%s","QC REG MAX MED");
1171  sprintf(qc_com,"%s","Median of all Maxs");
1172  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_med,qc_com,"%g"));
1173 
1174  sprintf(qc_key,"%s","QC REG MAX RMS");
1175  sprintf(qc_com,"%s","Rms of all Maxs");
1176  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_rms,qc_com,"%g"));
1177 
1178 
1179  check_nomsg(qc_min=cpl_table_get_column_min(qc_sto,"AVG"));
1180  check_nomsg(qc_max=cpl_table_get_column_max(qc_sto,"AVG"));
1181  check_nomsg(qc_avg=cpl_table_get_column_mean(qc_sto,"AVG"));
1182  check_nomsg(qc_med=cpl_table_get_column_median(qc_sto,"AVG"));
1183  check_nomsg(qc_rms=cpl_table_get_column_stdev(qc_sto,"AVG"));
1184 
1185  sprintf(qc_key,"%s","QC REG AVG MIN");
1186  sprintf(qc_com,"%s","Min of all Means");
1187  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_min,qc_com,"%g"));
1188 
1189  sprintf(qc_key,"%s","QC REG AVG MAX");
1190  sprintf(qc_com,"%s","Max of all Means");
1191  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_max,qc_com,"%g"));
1192 
1193  sprintf(qc_key,"%s","QC REG AVG AVG");
1194  sprintf(qc_com,"%s","Mean of all Means");
1195  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_avg,qc_com,"%g"));
1196 
1197  sprintf(qc_key,"%s","QC REG AVG MED");
1198  sprintf(qc_com,"%s","Median of all Means");
1199  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_med,qc_com,"%g"));
1200 
1201  sprintf(qc_key,"%s","QC REG AVG RMS");
1202  sprintf(qc_com,"%s","Rms of all Means");
1203  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_rms,qc_com,"%g"));
1204 
1205 
1206  check_nomsg(qc_min=cpl_table_get_column_min(qc_sto,"MED"));
1207  check_nomsg(qc_max=cpl_table_get_column_max(qc_sto,"MED"));
1208  check_nomsg(qc_avg=cpl_table_get_column_mean(qc_sto,"MED"));
1209  check_nomsg(qc_med=cpl_table_get_column_median(qc_sto,"MED"));
1210  check_nomsg(qc_rms=cpl_table_get_column_stdev(qc_sto,"MED"));
1211 
1212  sprintf(qc_key,"%s","QC REG MED MIN");
1213  sprintf(qc_com,"%s","Min of all Medians");
1214  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_min,qc_com,"%g"));
1215 
1216  sprintf(qc_key,"%s","QC REG MED MAX");
1217  sprintf(qc_com,"%s","Max of all Medians");
1218  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_max,qc_com,"%g"));
1219 
1220  sprintf(qc_key,"%s","QC REG MED AVG");
1221  sprintf(qc_com,"%s","Mean of all Medians");
1222  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_avg,qc_com,"%g"));
1223 
1224  sprintf(qc_key,"%s","QC REG MED MED");
1225  sprintf(qc_com,"%s","Median of all Medians");
1226  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_med,qc_com,"%g"));
1227 
1228  sprintf(qc_key,"%s","QC REG MED RMS");
1229  sprintf(qc_com,"%s","Rms of all Medians");
1230  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_rms,qc_com,"%g"));
1231 
1232 
1233  check_nomsg(qc_min=cpl_table_get_column_min(qc_sto,"RMS"));
1234  check_nomsg(qc_max=cpl_table_get_column_max(qc_sto,"RMS"));
1235  check_nomsg(qc_avg=cpl_table_get_column_mean(qc_sto,"RMS"));
1236  check_nomsg(qc_med=cpl_table_get_column_median(qc_sto,"RMS"));
1237  check_nomsg(qc_rms=cpl_table_get_column_stdev(qc_sto,"RMS"));
1238 
1239 
1240  sprintf(qc_key,"%s","QC REG RMS MIN");
1241  sprintf(qc_com,"%s","Min of all Rms");
1242  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_min,qc_com,"%g"));
1243 
1244  sprintf(qc_key,"%s","QC REG RMS MAX");
1245  sprintf(qc_com,"%s","Max of all Rms");
1246  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_max,qc_com,"%g"));
1247 
1248  sprintf(qc_key,"%s","QC REG RMS AVG");
1249  sprintf(qc_com,"%s","Mean of all Rms");
1250  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_avg,qc_com,"%g"));
1251 
1252  sprintf(qc_key,"%s","QC REG RMS MED");
1253  sprintf(qc_com,"%s","Median of all Rms");
1254  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_med,qc_com,"%g"));
1255 
1256  sprintf(qc_key,"%s","QC REG RMS RMS");
1257  sprintf(qc_com,"%s","Rms of all Rms");
1258  check_nomsg(uves_qclog_add_double(qclog,qc_key,qc_rms,qc_com,"%g"));
1259 
1260 
1261 
1262 
1263  cleanup:
1264  uves_free_table(&qc_sto);
1265 
1266  return;
1267 
1268 }
1269 
1270