UVES Pipeline Reference Manual  5.4.6
uves_dfs.c
1 /*
2  * This file is part of the UVES Pipeline
3  * Copyright (C) 2002, 2003, 2004, 2005 European Southern Observatory
4  *
5  * This program 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-04-16 15:48:48 $
23  * $Revision: 1.272 $
24  * $Name: not supported by cvs2svn $
25  *
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 /*----------------------------------------------------------------------------*/
39 /*----------------------------------------------------------------------------*/
40 
41 /*-----------------------------------------------------------------------------
42  Includes
43  -----------------------------------------------------------------------------*/
44 
45 #include <uves_dfs.h>
46 
47 #include <uves_utils.h>
48 #include <uves_wavecal_utils.h>
49 #include <uves_pfits.h>
50 #include <uves_dump.h>
51 #include <uves_qclog.h>
52 #include <uves.h>
53 #include <uves_utils_wrappers.h>
54 #include <uves_error.h>
55 #include <uves_msg.h>
56 
57 #include <irplib_utils.h>
58 
59 #include <cpl.h>
60 
61 #include <uves_time.h> /* iso time */
62 
63 #include <float.h>
64 #include <string.h>
65 /*-----------------------------------------------------------------------------
66  Defines
67  -----------------------------------------------------------------------------*/
68 #define FITS_MAGIC_SZ 6
69 
70 /*-----------------------------------------------------------------------------
71  Prototypes
72  -----------------------------------------------------------------------------*/
73 
74 static polynomial *load_polynomial(const char* filename, int extension);
75 static char *int_to_string(int i);
76 
77 static cpl_error_code
78 load_raw_image(const char *filename,
79  cpl_type type, bool flames, bool blue,
80  cpl_image *raw_image[2],
81  uves_propertylist *raw_header[2],
82  uves_propertylist *rotated_header[2]);
83 
84 static int uves_is_fits_file(const char *filename);
92 int uves_check_rec_status(const int val) {
93  if(cpl_error_get_code() != CPL_ERROR_NONE) {
94  uves_msg_error("error before %d",val);
95  uves_msg_error("%s", (char* ) cpl_error_get_message());
96  uves_msg_error("%s", (char* ) cpl_error_get_where());
97  return -1;
98  }
99  return 0;
100 }
101 
102 /*-------------------------------------------------------------------------*/
113 /*--------------------------------------------------------------------------*/
114 
115 static int uves_is_fits_file(const char *filename)
116 {
117  FILE *fp ;
118  char *magic ;
119  int isfits ;
120 
121  if ((fp = fopen(filename, "r"))==NULL) {
122  uves_msg_error("cannot open file [%s]", filename) ;
123  return -1 ;
124  }
125 
126  magic = cpl_calloc(FITS_MAGIC_SZ+1, sizeof(char)) ;
127  (void)fread(magic, 1, FITS_MAGIC_SZ, fp) ;
128  (void)fclose(fp) ;
129  magic[FITS_MAGIC_SZ] = (char)0 ;
130  if (strstr(magic, "SIMPLE")!=NULL)
131  isfits = 1 ;
132  else
133  isfits = 0 ;
134  cpl_free(magic) ;
135  return isfits ;
136 }
137 
138 /*----------------------------------------------------------------------------*/
148 /*----------------------------------------------------------------------------*/
149 static int
150 uves_dfs_files_dont_exist(cpl_frameset *frameset)
151 {
152  const char *func = "dfs_files_dont_exist";
153 
154  if (frameset == NULL) {
155  cpl_error_set(func, CPL_ERROR_NULL_INPUT);
156  return 1;
157  }
158 
159  if (cpl_frameset_is_empty(frameset)) {
160  return 0;
161  }
162 
163  cpl_frameset_iterator* it = cpl_frameset_iterator_new(frameset);
164  cpl_frame* frame = cpl_frameset_iterator_get(it);
165 
166  while (frame) {
167  if (access(cpl_frame_get_filename(frame), F_OK)) {
168  cpl_msg_error(func, "File %s (%s) was not found",
169  cpl_frame_get_filename(frame),
170  cpl_frame_get_tag(frame));
171  cpl_error_set(func, CPL_ERROR_FILE_NOT_FOUND);
172  }
173 
174  cpl_frameset_iterator_advance(it, 1);
175  frame = cpl_frameset_iterator_get(it);
176 
177  }
178  cpl_frameset_iterator_delete(it);
179  if (cpl_error_get_code())
180  return 1;
181 
182  return 0;
183 }
184 
185 
186 
187 /*----------------------------------------------------------------------------*/
196 /*----------------------------------------------------------------------------*/
197 
198 int
199 uves_contains_frames_kind(cpl_frameset * sof,
200  cpl_frameset* raw,
201  const char* type)
202 {
203  char* tag=NULL;
204  char* name=NULL;
205  cpl_frame* frame = NULL;
206  cpl_frame* frame_dup = NULL;
207 
208  int nsof=0;
209  int i=0;
210  nsof = cpl_frameset_get_size(sof);
211  for (i=0 ; i<nsof ; i++) {
212  frame = cpl_frameset_get_frame(sof,i);
213  name= (char*) cpl_frame_get_filename(frame);
214  if(uves_is_fits_file(name) == 1) {
215  /* to go on the file must exist */
216  if(cpl_frame_get_tag(frame) != NULL) {
217  /* If the frame has a tag we process it. Else it is an object */
218  tag= (char*) cpl_frame_get_tag(frame);
219  /* uves_msg("name=%s tag=%s type=%s\n",name,tag,type); */
220  if(strstr(tag,type) != NULL) {
221  /* uves_msg("Match name=%s tag=%s type=%s\n",name,tag,type); */
222  frame_dup = cpl_frame_duplicate(frame);
223  cpl_frameset_insert(raw,frame_dup);
224  /* uves_msg("inserted\n"); */
225  }
226  }
227  }
228  }
229  return 0;
230 }
231 
232 /*----------------------------------------------------------------------------*/
249 /*----------------------------------------------------------------------------*/
250 polynomial *
251 uves_polynomial_convert_from_plist_midas(const uves_propertylist *plist,
252  const char *regression_name,
253  const int index)
254 {
255  polynomial *result = NULL;
256  cpl_polynomial *pol = NULL;
257  int N = strlen(regression_name);
258  const char *coeffi_name = NULL;
259  cpl_type type;
260  int length;
261  int *coeffi = NULL;
262  int degree1 = -1;
263  int degree2 = -1;
264  bool found = false;
265  const long int plist_size = uves_propertylist_get_size(plist);
266  int i;
267 
268  char cind=' ';
269 
270  if (index == -1) {
271  coeffi_name = cpl_sprintf("%sI", regression_name);
272  }
273  else {
274 
275  switch(index) {
276 
277  case 1: cind='1'; break;
278  case 2: cind='2'; break;
279  case 3: cind='3'; break;
280  case 4: cind='4'; break;
281  case 5: cind='5'; break;
282  case 6: cind='6'; break;
283  case 7: cind='7'; break;
284  case 8: cind='8'; break;
285  case 9: cind='9'; break;
286  default:
287  assure( false, CPL_ERROR_ILLEGAL_INPUT,
288  "Illegal index %d, 1-9 expected", index);
289  break;
290  }
291 
292 
293  coeffi_name = cpl_sprintf("%sI%d", regression_name, index);
294  }
295 
296  check_nomsg( coeffi = uves_read_midas_array(plist, coeffi_name, &length, &type, NULL));
297 
298 
299  assure( type == CPL_TYPE_INT, CPL_ERROR_TYPE_MISMATCH,
300  "Type of array %s is %s, integer expected",
301  coeffi_name, uves_tostring_cpl_type(type));
302  /*
303  assure( length == 7, CPL_ERROR_ILLEGAL_INPUT,
304  "Wrong array length = %d, 7 expected",
305  length);
306  */
307  /* ignore OUTPUTI(1)- N,no.of data, */
308 
309  /* OUTPUTI(2)- M,no.of ind.var. */
310 
311  assure( coeffi[1] == 2, CPL_ERROR_UNSUPPORTED_MODE,
312  "Regressions is %d-dimensional (2D expected)",
313  coeffi[1]);
314 
315  /* ignore OUTPUTI(3-5) (column number of variables)
316  (3)- col.no. of dep.var.
317  (4)- col.no. of indep.var.
318  (5)-
319  */
320 
321  /* Read degree of first and second variable
322  (6)- degree (ND) */
323 
324  degree1 = coeffi[5];
325  degree2 = coeffi[6];
326 
327  uves_msg_debug("Degree of 2D regression %s is (%d, %d)",
328  regression_name, degree1, degree2);
329 
330  /* The degree of the regression is now known. Next, read the coefficients */
331 
332  pol = cpl_polynomial_new(2);
333 
334  /* Search for <regression_name>D */
335  found = false;
336  for (i = 0; !found && i < plist_size; i++){
337  const cpl_property *p = uves_propertylist_get_const(plist, i);
338  const char *name = cpl_property_get_name(p);
339 
340  if (strcmp(name, "HISTORY") == 0) {
341  const char *value;
342  check( value = cpl_property_get_string(p),
343  "Error reading property value");
344 
345  /* match the string "'<regression_name>D'" */
346 
347  if (
348 
349  (((index < 0) &&
350  (int)strlen(value) >= 1+N+2 &&
351  value[0] == '\'' &&
352  value[1+N] == 'D' &&
353  value[1+N+1] == '\'')
354 
355  ||
356 
357  ((index > 0) &&
358  (int)strlen(value) >= 1+N+3 &&
359  value[0] == '\'' &&
360  value[1+N] == 'D' &&
361  value[1+N+1] == cind &&
362  value[1+N+2] == '\'') )
363 
364  &&
365 
366  strncmp(value+1, regression_name, N) == 0
367  ) {
368  double coeff;
369  char *next;
370  cpl_size power[2];
371  int j = i; /* points to the property currently being read */
372 
373  power[0] = 0; /* Current degree */
374  power[1] = 0;
375 
376  found = true;
377  value = "dummy"; /* This will make strtod fail the first time */
378 
379  while (power[1] <= degree2){
380  /* Read coefficient */
381  coeff = strtod(value, &next);
382 
383  if (next != value) {
384  /* A prefix of the string was successfully converted to double */
385  cpl_polynomial_set_coeff(pol, power, coeff);
386  uves_msg_debug("Polynomial coefficient of order (%" CPL_SIZE_FORMAT ", %" CPL_SIZE_FORMAT ") is %e",
387  power[0], power[1], coeff);
388 
389  power[0]++;
390  if (power[0] > degree1){
391  power[0] = 0;
392  power[1]++;
393  }
394  value = next;
395  }
396  else {
397  /* No more doubles could be read from the string,
398  so move to the next property in the plist */
399  j = j + 1;
400 
401  assure(j < plist_size, CPL_ERROR_ILLEGAL_INPUT,
402  "Missing header data");
403 
404  p = uves_propertylist_get_const(plist, j);
405  assure( cpl_property_get_type(p) == CPL_TYPE_STRING &&
406  strcmp(cpl_property_get_name(p), "HISTORY") == 0,
407  CPL_ERROR_ILLEGAL_INPUT, "Error parsing polynomial");
408 
409  value = cpl_property_get_string(p);
410 
411 
412  uves_msg_debug("Parsing string '%s'", value);
413  }
414  } /* Read coefficients */
415  } /* string was "'...D'" */
416  } /* Keyword was HISTORY */
417  }/* for i... */
418 
419  assure( found, CPL_ERROR_ILLEGAL_INPUT, "Could not find '%sD' in property list",
420  regression_name);
421 
422  /* Create a new polynomial from the cpl_polynomial */
423  result = uves_polynomial_new(pol);
424 
425  cleanup:
426  uves_free_int(&coeffi);
427  uves_free_string_const(&coeffi_name);
428  uves_free_polynomial(&pol);
429  if (cpl_error_get_code() != CPL_ERROR_NONE)
430  {
431  uves_polynomial_delete(&result);
432  }
433 
434  return result;
435 }
436 
437 
438 /*----------------------------------------------------------------------------*/
445 /*----------------------------------------------------------------------------*/
446 cpl_error_code
447 uves_frameset_merge(cpl_frameset * set1, const cpl_frameset* set2)
448 {
449 
450  const cpl_frame* frm_tmp=NULL;
451  cpl_frame* frm_dup=NULL;
452  int i=0;
453  int nfrm;
454  passure(set1 != NULL, "Wrong input set");
455  passure(set2 != NULL, "Wrong input set");
456  nfrm=cpl_frameset_get_size(set2);
457  for (i = 0; i < nfrm; i++ ) {
458  frm_tmp=cpl_frameset_get_frame(set2,i);
459  frm_dup = cpl_frame_duplicate(frm_tmp);
460  cpl_frameset_insert(set1, frm_dup);
461  }
462 
463  cleanup:
464  return cpl_error_get_code();
465 }
466 
467 /*----------------------------------------------------------------------------*/
475 /*----------------------------------------------------------------------------*/
476 
477 cpl_error_code
478 uves_extract_frames_group_type(const cpl_frameset * set, cpl_frameset** ext, cpl_frame_group type)
479 {
480 
481  cpl_frame* frm_dup=NULL;
482  cpl_frame_group g;
483 
484  check_nomsg(*ext = cpl_frameset_new());
485  cpl_frameset_iterator* it = cpl_frameset_iterator_new(set);
486  const cpl_frame *frm_tmp = cpl_frameset_iterator_get_const(it);
487 
488  while (frm_tmp != NULL)
489  {
490  g=cpl_frame_get_group(frm_tmp);
491  if(g == type) {
492  frm_dup=cpl_frame_duplicate(frm_tmp);
493  cpl_frameset_insert(*ext,frm_dup);
494  uves_msg_debug("group %d insert file %s ",type,cpl_frame_get_filename(frm_dup));
495  }
496  cpl_frameset_iterator_advance(it, 1);
497  frm_tmp = cpl_frameset_iterator_get_const(it);
498  }
499  cpl_frameset_iterator_delete(it);
500  cleanup:
501  return cpl_error_get_code();
502 }
503 
504 /*----------------------------------------------------------------------------*/
512 /*----------------------------------------------------------------------------*/
513 cpl_error_code
514 uves_sflats_get_encoder_steps(const cpl_frameset * set, cpl_table** enc, int* nset)
515 {
516  /* Input */
517  const cpl_frame* frm=NULL;
518  int x1enc=0;
519  int x2enc=0;
520  int ref_x1enc=0;
521  int ref_x2enc=0;
522  int i=0;
523  int ndata=0;
524  const int threshold=5;
525  int status=0;
526  uves_propertylist* plist=NULL;
527  cpl_table* encoder_tbl=NULL;
528  ndata = cpl_frameset_get_size(set);
529  encoder_tbl=cpl_table_new(ndata);
530  cpl_table_new_column(encoder_tbl,"x1enc",CPL_TYPE_INT);
531  cpl_table_new_column(encoder_tbl,"x2enc",CPL_TYPE_INT);
532  cpl_table_new_column(encoder_tbl,"flag",CPL_TYPE_INT);
533 
534  for(i=0;i<cpl_frameset_get_size(set);i++)
535  {
536  check_nomsg(frm=cpl_frameset_get_frame_const(set,i));
537  check_nomsg(plist=uves_propertylist_load(cpl_frame_get_filename(frm),0));
540  check_nomsg(cpl_table_set_int(encoder_tbl,"x1enc",i,x1enc));
541  check_nomsg(cpl_table_set_int(encoder_tbl,"x2enc",i,x2enc));
542  uves_free_propertylist(&plist);
543  }
544 
545  check_nomsg(uves_sort_table_2(encoder_tbl,"x1enc","x2enc",false,true));
546 
547  check_nomsg(ref_x1enc=cpl_table_get_int(encoder_tbl,"x1enc",0,&status));
548  check_nomsg(ref_x2enc=cpl_table_get_int(encoder_tbl,"x2enc",0,&status));
549  *nset=1;
550  *enc=cpl_table_new(1);
551  cpl_table_new_column(*enc,"x1enc",CPL_TYPE_INT);
552  cpl_table_new_column(*enc,"x2enc",CPL_TYPE_INT);
553  check_nomsg(cpl_table_set_int(*enc,"x1enc",0,ref_x1enc));
554  check_nomsg(cpl_table_set_int(*enc,"x2enc",0,ref_x2enc));
555 
556  for(i=1;i<cpl_table_get_nrow(encoder_tbl);i++) {
557  check_nomsg(x1enc=cpl_table_get_int(encoder_tbl,"x1enc",i,&status));
558  check_nomsg(x2enc=cpl_table_get_int(encoder_tbl,"x2enc",i,&status));
559  if( (fabs(ref_x1enc -x1enc) > threshold) ||
560  (fabs(ref_x2enc -x2enc) > threshold) ) {
561 
562  ref_x1enc = x1enc;
563  ref_x2enc = x2enc;
564  cpl_table_set_size(*enc,(*nset+1));
565  check_nomsg(cpl_table_set_int(*enc,"x1enc",*nset,ref_x1enc));
566  check_nomsg(cpl_table_set_int(*enc,"x2enc",*nset,ref_x2enc));
567  *nset=*nset+1;
568 
569  }
570  }
571  uves_msg("Number of sets = %d",*nset);
572 
573  cleanup:
574  uves_free_table(&encoder_tbl);
575  uves_free_propertylist(&plist);
576  return cpl_error_get_code();
577 }
578 
579 
580 /*----------------------------------------------------------------------------*/
586 /*----------------------------------------------------------------------------*/
587 cpl_error_code
588 uves_dfs_set_groups(cpl_frameset * set)
589 {
590  cpl_frame * cur_frame ;
591  int nframes ;
592 
593  /* Check entries */
594  assure(set != NULL, CPL_ERROR_NULL_INPUT, "Null input");
595 
596  /* Initialize */
597  check( nframes = cpl_frameset_get_size(set), "Could not read frameset size");
598 
599  /* Loop on frames */
600  int i=0;
601  for (i = 0; i< nframes;i++)
602  {
603  cur_frame=cpl_frameset_get_frame(set,i);
604  bool is_raw = false;
605  bool is_calib = false;
606  bool is_recognized = false;
607  bool blue;
608  enum uves_chip chip;
609  const char * tag = cpl_frame_get_tag(cur_frame);
610 
611  assure( tag != NULL && strcmp(tag, "") != 0, CPL_ERROR_ILLEGAL_INPUT,
612  "Frame has no tag!");
613 
614  blue = false;
615  do {
616  bool flames = false;
617  do {
618  /* RAW frames */
619  is_raw = is_raw ||
620  (strcmp(tag, UVES_ORDER_FLAT (flames,blue)) == 0 ||
621  strcmp(tag, UVES_BIAS (blue)) == 0 ||
622  strcmp(tag, UVES_DARK (blue)) == 0 ||
623  strcmp(tag, UVES_PDARK (blue)) == 0 ||
624  strcmp(tag, UVES_FLAT (blue)) == 0 ||
625  strcmp(tag, UVES_IFLAT (blue)) == 0 ||
626  strcmp(tag, UVES_DFLAT (blue)) == 0 ||
627  strcmp(tag, UVES_SFLAT (blue)) == 0 ||
628  strcmp(tag, UVES_TFLAT (blue)) == 0 ||
629  strcmp(tag, UVES_SCREEN_FLAT (blue)) == 0 ||
630  strcmp(tag, UVES_CD_ALIGN (blue)) == 0 ||
631  strcmp(tag, UVES_FORMATCHECK (flames,blue)) == 0 ||
632  strcmp(tag, UVES_STD_STAR (blue)) == 0 ||
633  strcmp(tag, UVES_SCIENCE (blue)) == 0 ||
634  strcmp(tag, UVES_SCI_EXTND (blue)) == 0 ||
635  strcmp(tag, UVES_SCI_POINT (blue)) == 0 ||
636  strcmp(tag, UVES_SCI_SLICER (blue)) == 0 ||
637  strcmp(tag, UVES_ARC_LAMP (flames,blue)) == 0 ||
638  strcmp(tag, UVES_ECH_ARC_LAMP(blue)) == 0 ||
639  strcmp(tag, RAW_IMA) == 0 ||
640  strcmp(tag, FLAMES_SCI_RED) == 0 ||
641  strcmp(tag, FLAMES_SCI_SIM_RED) == 0 ||
642  strcmp(tag, FLAMES_SCI_COM_RED) == 0 ||
643  strcmp(tag, FLAMES_FIB_FF_ODD) == 0 ||
644  strcmp(tag, FLAMES_FIB_FF_EVEN) == 0 ||
645  strcmp(tag, FLAMES_FIB_FF_ALL) == 0);
646 
647  /* CALIB frames */
648 
649  /* Loop through all (1 or 2) blue or red chips */
650  for (chip = uves_chip_get_first(blue);
651  chip != UVES_CHIP_INVALID;
652  chip = uves_chip_get_next(chip))
653  {
654  int window;
655 
656  is_calib = is_calib ||
657  (strcmp(tag, UVES_DRS_SETUP(flames, chip)) == 0 ||
658  strcmp(tag, UVES_ORDER_TABLE(flames, chip)) == 0 ||
659  strcmp(tag, UVES_GUESS_ORDER_TABLE(flames,chip)) == 0 ||
660  strcmp(tag, UVES_MASTER_BIAS (chip)) == 0 ||
661  strcmp(tag, UVES_MASTER_DARK (chip)) == 0 ||
662  strcmp(tag, UVES_MASTER_PDARK (chip)) == 0 ||
663  strcmp(tag, UVES_MASTER_FLAT (chip)) == 0 ||
664  strcmp(tag, UVES_MASTER_DFLAT (chip)) == 0 ||
665  strcmp(tag, UVES_MASTER_SFLAT (chip)) == 0 ||
666  strcmp(tag, UVES_MASTER_IFLAT (chip)) == 0 ||
667  strcmp(tag, UVES_MASTER_TFLAT (chip)) == 0 ||
668  strcmp(tag, UVES_REF_TFLAT (chip)) == 0 ||
669  strcmp(tag, UVES_ORD_TAB(flames,chip)) == 0 ||
670  strcmp(tag, UVES_MASTER_SCREEN_FLAT(chip)) == 0 ||
671  strcmp(tag, UVES_MASTER_ARC_FORM(chip)) == 0 ||
672  strcmp(tag, UVES_WEIGHTS(chip)) == 0 ||
673  strcmp(tag, UVES_LINE_TABLE(flames,chip)) == 0 ||
674  strcmp(tag, UVES_GUESS_LINE_TABLE(flames,chip)) == 0 ||
675  strcmp(tag, UVES_INSTR_RESPONSE(chip)) == 0 ||
676  strcmp(tag, UVES_MASTER_RESPONSE(chip)) == 0 ||
677  strcmp(tag, UVES_LINE_REFER_TABLE ) == 0 ||
678  strcmp(tag, UVES_LINE_INTMON_TABLE ) == 0 ||
679  strcmp(tag, UVES_FLUX_STD_TABLE ) == 0 ||
680  strcmp(tag, UVES_EXTCOEFF_TABLE ) == 0 ||
681  strcmp(tag, FLAMES_LINE_TABLE(chip)) == 0 ||
682  strcmp(tag, FLAMES_SLIT_FF_DT1(chip)) == 0 ||
683  strcmp(tag, FLAMES_SLIT_FF_DT2(chip)) == 0 ||
684  strcmp(tag, FLAMES_SLIT_FF_DT3(chip)) == 0 ||
685  strcmp(tag, FLAMES_SLIT_FF_DTC(chip)) == 0 ||
686  strcmp(tag, FLAMES_SLIT_FF_BP1(chip)) == 0 ||
687  strcmp(tag, FLAMES_SLIT_FF_BP2(chip)) == 0 ||
688  strcmp(tag, FLAMES_SLIT_FF_BP3(chip)) == 0 ||
689  strcmp(tag, FLAMES_SLIT_FF_BPC(chip)) == 0 ||
690  strcmp(tag, FLAMES_SLIT_FF_BN1(chip)) == 0 ||
691  strcmp(tag, FLAMES_SLIT_FF_BN2(chip)) == 0 ||
692  strcmp(tag, FLAMES_SLIT_FF_BN3(chip)) == 0 ||
693  strcmp(tag, FLAMES_SLIT_FF_BNC(chip)) == 0 ||
694  strcmp(tag, FLAMES_SLIT_FF_SG1(chip)) == 0 ||
695  strcmp(tag, FLAMES_SLIT_FF_SG2(chip)) == 0 ||
696  strcmp(tag, FLAMES_SLIT_FF_SG3(chip)) == 0 ||
697  strcmp(tag, FLAMES_SLIT_FF_SGC(chip)) == 0 ||
698  strcmp(tag, FLAMES_SLIT_FF_COM(chip)) == 0 ||
699  strcmp(tag, FLAMES_SLIT_FF_NOR(chip)) == 0 ||
700  strcmp(tag, FLAMES_SLIT_FF_NSG(chip)) == 0 ||
701  strcmp(tag, FLAMES_FIB_FF_DT1(chip)) == 0 ||
702  strcmp(tag, FLAMES_FIB_FF_DT2(chip)) == 0 ||
703  strcmp(tag, FLAMES_FIB_FF_DT3(chip)) == 0 ||
704  strcmp(tag, FLAMES_FIB_FF_DTC(chip)) == 0 ||
705  strcmp(tag, FLAMES_FIB_FF_BP1(chip)) == 0 ||
706  strcmp(tag, FLAMES_FIB_FF_BP2(chip)) == 0 ||
707  strcmp(tag, FLAMES_FIB_FF_BP3(chip)) == 0 ||
708  strcmp(tag, FLAMES_FIB_FF_BPC(chip)) == 0 ||
709  strcmp(tag, FLAMES_FIB_FF_BN1(chip)) == 0 ||
710  strcmp(tag, FLAMES_FIB_FF_BN2(chip)) == 0 ||
711  strcmp(tag, FLAMES_FIB_FF_BN3(chip)) == 0 ||
712  strcmp(tag, FLAMES_FIB_FF_BNC(chip)) == 0 ||
713  strcmp(tag, FLAMES_FIB_FF_SG1(chip)) == 0 ||
714  strcmp(tag, FLAMES_FIB_FF_SG2(chip)) == 0 ||
715  strcmp(tag, FLAMES_FIB_FF_SG3(chip)) == 0 ||
716  strcmp(tag, FLAMES_FIB_FF_SGC(chip)) == 0 ||
717  strcmp(tag, FLAMES_FIB_FF_COM(chip)) == 0 ||
718  strcmp(tag, FLAMES_FIB_FF_NOR(chip)) == 0 ||
719  strcmp(tag, FLAMES_FIB_FF_NSG(chip)) == 0 ||
720  strcmp(tag, FLAMES_ORDEF(flames,chip)) == 0 ||
721  strcmp(tag, FLAMES_CORVEL_MASK) == 0);
722 
723  for (window = 1; window <= 3; window++)
724  {
725  is_calib = is_calib ||
726  strcmp(tag, UVES_LINE_TABLE_MIDAS(chip, window)) == 0;
727  }
728 
729  if (!flames && strcmp(tag, UVES_BACKGR_TABLE(chip)) == 0)
730  {
731  uves_msg_warning("Background table %s has been deprecated. "
732  "Inter-order positions will be inferred "
733  "from the order table %s. "
734  "Use recipe parameters to define "
735  "measuring method ",
736  UVES_BACKGR_TABLE(chip),
737  UVES_ORDER_TABLE(flames, chip));
738 
739  is_recognized = true;
740  }
741 
742  if (strcmp(tag, UVES_DRS_SETUP(flames, chip)) == 0)
743  {
744  uves_msg_warning("DRS setup table %s has been deprecated. "
745  "Use recipe parameters "
746  "to define data reduction parameters ",
747  UVES_DRS_SETUP(flames, chip));
748 
749  is_recognized = true;
750  }
751  }
752  flames = !flames;
753  } while (flames);
754  blue = !blue;
755  }
756  while (blue);
757 
758  is_recognized = is_recognized || is_raw || is_calib;
759 
760  if (is_raw)
761  {
762  cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW) ;
763  }
764  else if (is_calib)
765  {
766  cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_CALIB) ;
767  }
768  else if (!is_recognized)
769  {
770  uves_msg_warning("Unrecognized tag %s", tag);
771  }
772  }
773 
774  uves_dfs_files_dont_exist(set);
775 
776 
777  cleanup:
778  return cpl_error_get_code();
779 }
780 
781 
782 /*----------------------------------------------------------------------------*/
791 /*----------------------------------------------------------------------------*/
792 static void
793 remove_pre_over_scan(uves_propertylist *pl)
794 {
795  bool blue, new_format;
796  enum uves_chip chip;
797 
798  new_format = false;
799  do {
800  blue = false;
801  do {
802  for (chip = uves_chip_get_first(blue);
803  chip != UVES_CHIP_INVALID;
804  chip = uves_chip_get_next(chip))
805  {
806  int n_erase_px = 0; /* Number of erased properties */
807  int n_erase_py = 0;
808  int n_erase_ox = 0;
809  int n_erase_oy = 0;
810 
811  do {
812  /* This function erases only one property at a time,
813  * therefore call it until it returns 0
814  */
815  check( n_erase_px =
816  uves_propertylist_erase(pl, UVES_PRESCANX(new_format, chip)),
817  "Error erasing keyword '%s'", UVES_PRESCANX(new_format, chip));
818 
819  check( n_erase_py =
820  uves_propertylist_erase(pl, UVES_PRESCANY(new_format, chip)),
821  "Error erasing keyword '%s'", UVES_PRESCANY(new_format, chip));
822 
823  check( n_erase_ox =
824  uves_propertylist_erase(pl, UVES_OVRSCANX(new_format, chip)),
825  "Error erasing keyword '%s'", UVES_OVRSCANX(new_format, chip));
826 
827  check( n_erase_oy =
828  uves_propertylist_erase(pl, UVES_OVRSCANY(new_format, chip)),
829  "Error erasing keyword '%s'", UVES_OVRSCANY(new_format, chip));
830  }
831  while (n_erase_px > 0 ||
832  n_erase_py > 0 ||
833  n_erase_ox > 0 ||
834  n_erase_oy > 0);
835  }
836  blue = !blue;
837  }
838  while (blue);
839 
840  new_format = !new_format;
841  }
842  while (new_format);
843 
844  cleanup:
845  return;
846 }
847 
848 
849 /*----------------------------------------------------------------------------*/
859 /*----------------------------------------------------------------------------*/
860 
861 void
862 uves_copy_if_possible(uves_propertylist *to, const uves_propertylist *from,
863  const char *name)
864 {
865  if (!uves_propertylist_contains(to, name) &&
866  uves_propertylist_contains(from, name))
867  {
868  uves_msg_debug("Propagating keyword %s", name);
869 
870  check_nomsg( uves_propertylist_copy_property(to, from, name) );
871  }
872  else
873  {
874  uves_msg_debug("Keyword %s not propagated", name);
875  }
876 
877  cleanup:
878  return;
879 }
880 
881 /*----------------------------------------------------------------------------*/
925 /*----------------------------------------------------------------------------*/
926 cpl_error_code
927 uves_frameset_insert(cpl_frameset *frames,
928  void *object,
929  cpl_frame_group group,
930  cpl_frame_type type,
931  cpl_frame_level level,
932  const char *filename,
933  const char *tag,
934  const uves_propertylist *raw_header,
935  const uves_propertylist *primary_header,
936  const uves_propertylist *table_header,
937  const cpl_parameterlist *parameters,
938  const char *recipe,
939  const char *pipeline,
940  cpl_table **qc,
941  const char *start_time,
942  bool dump_paf,
943  unsigned stats_mask)
944 {
945  cpl_frame *f = NULL;
946  uves_propertylist *pl = NULL;
947  const char *origin = "";
948 
949  passure( !(type == CPL_FRAME_TYPE_IMAGE && table_header != NULL), " ");
950  passure( raw_header != NULL, " ");
951  passure( primary_header != NULL, " ");
952 
953  assure( type == CPL_FRAME_TYPE_IMAGE || stats_mask == 0,
954  CPL_ERROR_INCOMPATIBLE_INPUT,
955  "Cannot compute image statistics on table product" );
956 
957  /* Insert the object (image or table) into frameset */
958  check(( f = cpl_frame_new(),
959  cpl_frame_set_filename(f, filename), /* local filename */
960  cpl_frame_set_tag (f, tag), /* e.g. ORDER_TABLE_BLUE */
961  cpl_frame_set_type (f, type), /* e.g. table */
962  cpl_frame_set_group (f, group), /* e.g. raw/product */
963  cpl_frame_set_level (f, level), /* e.g. temporary/final */
964  cpl_frameset_insert(frames, f)), "Could not insert frame into frameset");
965 
966  /* Pipeline id format is <PACKAGE "/" PACKAGE_VERSION>; */
967  if (strchr(pipeline, '/') == NULL)
968  {
969  uves_msg_warning("Pipeline ID '%s' is not of format: "
970  "Pipeline-name/version", pipeline);
971  }
972 
973  /* Copy provided keywords in 'primary_header' to 'pl' */
974  pl = uves_propertylist_new();
975  if(uves_propertylist_contains(primary_header,UVES_BSCALE)) {
976  uves_msg("inside has bscale");
977  }
978  if (!uves_propertylist_is_empty(primary_header))
979  {
980  if (0)
981  /* This takes (n*m) time */
982  {
983  /* The regexp "" matches any string (because any string has
984  the empty string as a sub-string),
985  except on Mac, where it is an illegal regexp (for whatever reason).
986  Therefore, use ".*" to match any string */
987 
988  check( uves_propertylist_copy_property_regexp(pl, primary_header, ".*", 0),
989  "Could not copy keywords");
990  }
991  else
992  check( uves_propertylist_append(pl, primary_header),
993  "Could not copy keywords");
994  }
995 
996  /* Propagate/create DFS keywords */
997  UVES_TIME_START("cpl_dfs_setup_product_header");
998  check( uves_dfs_setup_product_header(pl,
999  f,
1000  frames,
1001  parameters,
1002  recipe,
1003  pipeline,
1004  DICTIONARY),
1005  "Error setting up product header");
1006  UVES_TIME_END;
1007 
1008  /* Change origin to 'ESO' if it says 'ESO-MIDAS'
1009  * NOST-Definition: "The value field shall contain a character string
1010  * identifying the organization or institution responsible
1011  * for creating the FITS file."
1012  */
1013 
1014  check( uves_get_property_value(pl, "ORIGIN", CPL_TYPE_STRING, &origin),
1015  "Error reading ORIGIN from product header");
1016 
1017  if (strcmp(origin, "ESO-MIDAS") == 0)
1018  {
1019  uves_propertylist_set_string(pl, "ORIGIN", "ESO");
1020  }
1021 
1022  /* Add statistics keywords */
1023  if (type == CPL_FRAME_TYPE_IMAGE && stats_mask != 0)
1024  {
1025  check( uves_dfs_write_statistics((cpl_image *) object, pl, stats_mask),
1026  "Error adding image statistics keywords");
1027  }
1028 
1029  /* Propagate ESO.DET keywords from 'raw_header',
1030  * This is necessary because cpl_dfs_setup_product_header() copies
1031  * only from the primary extension of the first input frames
1032  */
1033  check( uves_propertylist_copy_property_regexp(pl, raw_header, "^ESO DET ", 0),
1034  "Could not propagate 'ESO DET*' keywords");
1035 
1036  /* But remove prescan, overscan keywords.
1037  (Since these areas are not present in any products.) */
1038  check( remove_pre_over_scan(pl),
1039  "Error removing pre-, overscan keywords from product header");
1040 
1041  /* Propagate certain keywords from 'raw_header'
1042  (only if available and if not already present in product header) */
1043  check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_AIRMASS) );
1044  check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_IMAGETYP) );
1045  check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_UT) );
1046  check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_ST) );
1047  check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_EXPTIME) );
1048  check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_EXTNAME) );
1049  check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_DATE) );
1050  check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_DATAMEAN) );
1051  check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_DATAMED) );
1052  check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_DATARMS) );
1053  check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_OS_EXPOI) );
1054 
1055  /* MIDAS internal(?): check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_TMSTART) ); */
1056  {
1058  pl, raw_header, "^((GRAT|FILTER|WLEN)[0-9]*)$", 0),
1059  "Could not propagate GRATi, FILTERi and WLENi keywords");
1060  }
1061 
1062  /* If RA,DEC do not exist, invent them and set to zero, like MIDAS */
1063  if ( !uves_propertylist_contains(pl, UVES_RA) )
1064  {
1065  uves_pfits_set_ra(pl, 0);
1066  }
1067  if ( !uves_propertylist_contains(pl, UVES_DEC) )
1068  {
1069  uves_pfits_set_dec(pl, 0);
1070  }
1071 
1072  /*
1073  * REDLEVEL and STATUS have been deprecated, so delete them
1074  * along with inherited MIDAS specific keywords
1075  */
1076  {
1077  bool invert = false;
1079  "ESO PRO (REDLEVEL|REC[0-9]+ STATUS)|"
1080  "TM-START|MIDASFTP|FILENAME)$", invert);
1081  }
1082 
1083  if( (strcmp(recipe,"uves_obs_scired") == 0) ||
1084  (strcmp(recipe,"uves_cal_response") == 0) ) {
1085  /* scired products have Angstrom units */
1086  if(cpl_propertylist_has(pl,"WLEN1")) {
1087  double wlen1=uves_pfits_get_wlen1(pl);
1088  wlen1 *=10.;
1089  uves_pfits_set_wlen1(pl,wlen1);
1090  }
1091  }
1092 
1093 
1094 
1095  check( uves_pfits_set_starttime(pl, start_time),
1096  "Could not write recipe start time");
1097 
1099  "Could not write recipe stop time");
1100 
1101  /* Create paf file from each QC table, and transfer
1102  all QC parameters to product header
1103  */
1104  if (qc != NULL)
1105  {
1106  int i;
1107  for (i = 0; qc[i] != NULL; i++)
1108  {
1109  uves_pfits_put_qc(pl, qc[i]);
1110 
1111  if (dump_paf)
1112  {
1113  /* Exception! This is a hack */
1114  if (strcmp(recipe, make_str(UVES_TFLAT_ID)) == 0 && i == 1)
1115  {
1116  /* Don't dump the science QC again */
1117  }
1118  else
1119  {
1120  /*
1121  uves_save_paf(filename, i, recipe, qc[i],
1122  pl, raw_header, tag);
1123  */
1124  }
1125  }
1126  }
1127  }
1128 
1129  UVES_TIME_START("save product");
1130 
1131  /* Now save with the correct header */
1132  if (type == CPL_FRAME_TYPE_IMAGE)
1133  {
1134  bool use_bitpix16_for_int = (strcmp(recipe, make_str(FLAMES_CAL_ORDERPOS)) == 0);
1135 
1136  check( uves_save_image((cpl_image *) object, filename, pl,
1137  use_bitpix16_for_int, true),
1138  "Error saving image to file %s", filename);
1139  }
1140  else if (type == CPL_FRAME_TYPE_TABLE) /* Table */
1141  {
1142  check( uves_table_save((cpl_table *) object,
1143  pl, /* Primary header */
1144  table_header, /* Table header */
1145  filename,
1146  CPL_IO_DEFAULT), /* Create new file */
1147  "Error saving table to file '%s'", filename);
1148  }
1149  else
1150  {
1151  assure(false, CPL_ERROR_UNSUPPORTED_MODE, "Unsupported frame type");
1152  }
1153 
1154  UVES_TIME_END;
1155 
1156  cleanup:
1157  uves_free_propertylist(&pl);
1158 
1159  return cpl_error_get_code();
1160 }
1161 
1162 
1163 /*----------------------------------------------------------------------------*/
1172 /*----------------------------------------------------------------------------*/
1173 void
1174 uves_dfs_write_statistics(const cpl_image *image, uves_propertylist *header,
1175  unsigned stats_mask)
1176 {
1177  cpl_stats *stats = NULL;
1178 
1179  /* Only these bits are supported, all others must be zero */
1180  assure( (stats_mask & (CPL_STATS_MEAN | CPL_STATS_STDEV | CPL_STATS_MEDIAN |
1181  CPL_STATS_MIN | CPL_STATS_MAX)) == stats_mask,
1182  CPL_ERROR_UNSUPPORTED_MODE, "Cannot compute mask %d",
1183  stats_mask );
1184 
1185  UVES_TIME_START("calculate stats");
1186 
1187  check( stats = cpl_stats_new_from_image(
1188  image, stats_mask),
1189  "Error reading image statistics");
1190 
1191  UVES_TIME_END;
1192 
1193  if (stats_mask & CPL_STATS_MEDIAN)
1194  {
1195  check( uves_pfits_set_data_median (header, cpl_stats_get_median(stats) ),
1196  "Could not write median flux");
1197  }
1198  if (stats_mask & CPL_STATS_MEAN)
1199  {
1200  check( uves_pfits_set_data_average(header, cpl_stats_get_mean (stats) ),
1201  "Could not write average flux");
1202  }
1203  if (stats_mask & CPL_STATS_STDEV)
1204  {
1205  check( uves_pfits_set_data_stddev (header, cpl_stats_get_stdev (stats) ),
1206  "Could not write flux stdev");
1207  }
1208  if (stats_mask & CPL_STATS_MIN)
1209  {
1210  check( uves_pfits_set_data_min (header, cpl_stats_get_min (stats) ),
1211  "Could not write min flux");
1212  }
1213  if (stats_mask & CPL_STATS_MIN)
1214  {
1215  check( uves_pfits_set_data_max (header, cpl_stats_get_max (stats) ),
1216  "Could not write max flux");
1217  }
1218 
1219  cleanup:
1220  uves_free_stats(&stats);
1221  return;
1222 }
1223 
1224 
1225 /*----------------------------------------------------------------------------*/
1260 /*----------------------------------------------------------------------------*/
1261 void *
1262 uves_read_midas_array(const uves_propertylist *plist, const char *name,
1263  int *length, cpl_type *type, int *ncards)
1264 {
1265  void *result = NULL;
1266  unsigned result_size;
1267  int N = strlen(name);
1268  bool found = false;
1269  const char *value;
1270  int size;
1271  int i;
1272  const long int plist_size = uves_propertylist_get_size(plist);
1273 
1274  assure_nomsg( length != NULL, CPL_ERROR_NULL_INPUT );
1275  assure_nomsg( type != NULL, CPL_ERROR_NULL_INPUT );
1276  for (i = 0; !found && i < plist_size; i++)
1277  {
1278  const cpl_property *p = uves_propertylist_get_const(plist, i);
1279  value = cpl_property_get_name(p);
1280 
1281  if (strcmp(value, "HISTORY") == 0)
1282  {
1283 
1284  check( value = cpl_property_get_string(p),
1285  "Error reading property value");
1286 
1287  /* match the string "'<name>','t" */
1288 
1289  if ((int)strlen(value) >= 1+N+4 &&
1290  value[0] == '\'' &&
1291  value[N+1] == '\'' &&
1292  value[N+2] == ',' &&
1293  value[N+3] == '\'' &&
1294  strncmp(value+1, name, N) == 0
1295  )
1296  {
1297  switch(value[N+4]) {
1298  case 'R':
1299  /* Distinguish between
1300  "'<name>','R*4'" and
1301  "'<name>','R*8'"
1302  */
1303  *type = CPL_TYPE_DOUBLE;
1304 
1305  if ((int)strlen(value) >= 1+N+4+2 && value[N+4+1] == '*')
1306  {
1307  switch(value[N+4+2]) {
1308  case '4': *type = CPL_TYPE_FLOAT; break;
1309  case '8': *type = CPL_TYPE_DOUBLE; break;
1310  default:
1311  assure( false, CPL_ERROR_ILLEGAL_INPUT,
1312  "Unrecognized MIDAS type: 'R*%c'",
1313  value[N+4+2]);
1314  break;
1315  }
1316  }
1317  break;
1318  case 'I': *type = CPL_TYPE_INT ; size = sizeof(int); break;
1319  case 'C': *type = CPL_TYPE_STRING; size = sizeof(char); break;
1320  default:
1321  assure( false, CPL_ERROR_UNSUPPORTED_MODE,
1322  "Unrecognized type '%c'", value[N+4]);
1323  break;
1324  }
1325  found = true;
1326  }
1327  }
1328  }
1329 
1330  assure( found, CPL_ERROR_ILLEGAL_INPUT, "Could not find '%s' in property list", name);
1331 
1332  /* 'i' is now the row immediately after first occurence of 'HISTORY '<name>... */
1333  result_size = sizeof(double) * 100; /* realloc when/if out of memory */
1334  result = cpl_malloc(result_size);
1335 
1336  *length = 0;
1337  if (ncards != NULL) *ncards = 2; /* First HISTORY entry + termination HISTORY entry */
1338  do {
1339  const cpl_property *p;
1340 
1341  if (ncards != NULL) *ncards += 1;
1342 
1343  assure(i < plist_size,
1344  CPL_ERROR_ILLEGAL_INPUT, "Missing header data");
1345  p = uves_propertylist_get_const(plist, i);
1346  assure( cpl_property_get_type(p) == CPL_TYPE_STRING &&
1347  strcmp(cpl_property_get_name(p), "HISTORY") == 0,
1348  CPL_ERROR_ILLEGAL_INPUT, "Error parsing array");
1349  value = cpl_property_get_string(uves_propertylist_get_const(plist, i));
1350 
1351  uves_msg_debug("Parsing '%s'", value);
1352 
1353  if (*type == CPL_TYPE_STRING)
1354  {
1355  assure( strlen(value) < 100, CPL_ERROR_UNSUPPORTED_MODE,
1356  "String too long. Max size is 100");
1357 
1358  /* Remove any blanks from the string
1359  (e.g. convert "0 1 2" to "012")
1360  */
1361  {
1362  int len = strlen(value);
1363  int j = 0;
1364  int k;
1365  for (k = 0; k <= len; k++) /* including final '\0' */
1366  {
1367  //if (value[k] != ' '){
1368  ((char*)result)[j] = value[k];
1369  j++;
1370  // }
1371  }
1372  *length = j-1;
1373  }
1374 
1375  uves_msg_debug("Converted '%s' to '%s'",
1376  value, (char*)result);
1377 
1378  /* done parsing */
1379  value = "";
1380  }
1381 
1382  else { /* numerical types */
1383  if (strcmp(value, "") != 0) {
1384  double numberd = -1; /* suppres warning */
1385  int numberi = -1;
1386  float numberf = -1;
1387  const int base = 10;
1388  char *next = (char *) value;
1389 
1390  do {
1391  /* ignore OUTPUTI(1)- N,no.of data, */
1392  switch(*type) {
1393  case CPL_TYPE_DOUBLE:
1394  numberd = strtod(value, &next);
1395  uves_msg_debug("Got %g, remaining: '%s'", numberd, next);
1396  break;
1397  case CPL_TYPE_FLOAT:
1398  numberf = strtod(value, &next); // C99: strtof(value, &next);
1399  uves_msg_debug("Got %g, remaining: '%s'", numberf, next);
1400  break;
1401  case CPL_TYPE_INT:
1402  numberi = strtol(value, &next, base);
1403  uves_msg_debug("Got %d, remaining: '%s'", numberi, next);
1404  break;
1405  default:
1406  passure(false, " ");
1407  }
1408 
1409  if (next != value)
1410  {
1411  /* A prefix of the string could be converted */
1412  (*length)++;
1413  if (*length * sizeof(double) > result_size)
1414  {
1415  result_size *= 2;
1416  result = cpl_realloc(result, result_size);
1417  }
1418 
1419  switch(*type) {
1420  case CPL_TYPE_DOUBLE:
1421  ((double *)result)[*length-1] = numberd;
1422  break;
1423  case CPL_TYPE_FLOAT:
1424  ((float *)result)[*length-1] = numberf;
1425  break;
1426  case CPL_TYPE_INT:
1427  ((int *)result)[*length-1] = numberi;
1428  break;
1429  default:
1430  passure(false, " ");
1431  }
1432 
1433  value = next;
1434 
1435  switch(*type) {
1436  case CPL_TYPE_DOUBLE:
1437  numberd = strtod(value, &next);
1438  uves_msg_debug("Got %g, remaining: '%s'", numberd, next);
1439  break;
1440  case CPL_TYPE_FLOAT:
1441  numberf = strtod(value, &next); // C99: strtof(value, &next);
1442  uves_msg_debug("Got %g, remaining: '%s'", numberf, next);
1443  break;
1444  case CPL_TYPE_INT:
1445  numberi = strtol(value, &next, base);
1446  uves_msg_debug("Got %d, remaining: '%s'", numberi, next);
1447  break;
1448  default:
1449  passure(false, " ");
1450  }
1451  }
1452  } while (next != value);
1453  }
1454  }/* if numerical type */
1455 
1456  i++;
1457 
1458  assure( strcmp(value, "") == 0, CPL_ERROR_ILLEGAL_INPUT,
1459  "Cannot parse %s descriptor %s, remaining string: '%s'",
1460  uves_tostring_cpl_type(*type), name, value);
1461 
1462  /* Find out if we can continue parsing the next HISTORY keyword */
1463  if (i < plist_size)
1464  {
1465  p = uves_propertylist_get_const(plist, i);
1466  if (cpl_property_get_type(p) == CPL_TYPE_STRING &&
1467  strcmp(cpl_property_get_name(p), "HISTORY") == 0)
1468  {
1469  value = cpl_property_get_string(
1470  uves_propertylist_get_const(plist, i));
1471 
1472  if (*type == CPL_TYPE_STRING)
1473  {
1474  if (strcmp(value, "") != 0) {
1475  uves_msg_debug("String array %s with length > 1 found. Ignoring remaining values", name);
1476  while (strcmp(value, "") != 0 && i+1 < plist_size) {
1477  i++;
1478  p = uves_propertylist_get_const(plist, i);
1479  value = cpl_property_get_string(
1480  uves_propertylist_get_const(plist, i));
1481  if (ncards != NULL) *ncards += 1;
1482  }
1483  }
1484  }
1485  }
1486  }
1487 
1488  } while (strcmp(value, "") != 0);
1489 
1490  cleanup:
1491  if (cpl_error_get_code() != CPL_ERROR_NONE)
1492  {
1493  cpl_free(result); result = NULL;
1494  }
1495  return result;
1496 }
1497 
1498 
1499 /*----------------------------------------------------------------------------*/
1517 /*----------------------------------------------------------------------------*/
1518 cpl_error_code
1519 uves_save_table_local(const char *description, const char *filename_prefix,
1520  const cpl_table *table,
1521  enum uves_chip chip, int trace, int window,
1522  const uves_propertylist *pheader, const uves_propertylist *eheader)
1523 {
1524  char *filename = NULL;
1525 
1526  check( filename = uves_local_filename(filename_prefix, chip, trace, window),
1527  "Error getting filename");
1528 
1529  check( uves_table_save(table, pheader, eheader, filename, CPL_IO_DEFAULT),
1530  "Error saving table to file '%s'", filename);
1531 
1532  if (description != NULL) uves_msg("%s saved to '%s'", description, filename);
1533 
1534  cleanup:
1535  cpl_free(filename);
1536  return cpl_error_get_code();
1537 }
1538 
1539 /*----------------------------------------------------------------------------*/
1560 /*----------------------------------------------------------------------------*/
1561 cpl_error_code
1562 uves_save_image_local(const char *description, const char *filename_prefix,
1563  const cpl_image *image,
1564  enum uves_chip chip, int trace, int window,
1565  const uves_propertylist *plist,
1566  bool use_bitpix16_for_int)
1567 {
1568  char *filename = NULL;
1569 
1570  check( filename = uves_local_filename(filename_prefix, chip, trace, window),
1571  "Error getting filename");
1572 
1573  check( uves_save_image(image, filename, plist, use_bitpix16_for_int, true),
1574  "Error saving image to file '%s'", filename);
1575  if (description != NULL) uves_msg("%s saved to '%s'", description, filename);
1576 
1577  cleanup:
1578  cpl_free(filename);
1579  return cpl_error_get_code();
1580 }
1581 
1582 
1583 /*----------------------------------------------------------------------------*/
1593 /*----------------------------------------------------------------------------*/
1594 cpl_image *uves_load_image(const cpl_frame *f,
1595  int plane,
1596  int extension,
1597  uves_propertylist **header)
1598 {
1599  cpl_image *image = NULL;
1600  uves_propertylist *plist = NULL;
1601  const char *filename;
1602  int bitpix;
1603  cpl_type type;
1604  int naxis=0;
1605  cpl_vector * vector=NULL;
1606 
1607 
1608  assure_nomsg( f != NULL, CPL_ERROR_NULL_INPUT );
1609 
1610  assure( cpl_frame_get_type(f) == CPL_FRAME_TYPE_IMAGE,
1611  CPL_ERROR_TYPE_MISMATCH, "Wrong type: %s",
1612  uves_tostring_cpl_frame_type(cpl_frame_get_type(f)));
1613 
1614  filename = cpl_frame_get_filename(f);
1615 
1616  check( plist = uves_propertylist_load(filename, extension),
1617  "Could not load header from %s extension %d",
1618  filename, extension);
1619 
1620  check( bitpix = uves_pfits_get_bitpix(plist),
1621  "Could not read BITPIX from %s extension %d",
1622  filename, extension);
1623 
1624  if (bitpix == -32) type = CPL_TYPE_FLOAT;
1625  else if (bitpix == -64) type = CPL_TYPE_DOUBLE;
1626  else if (bitpix == 32) type = CPL_TYPE_INT;
1627  else if (bitpix == 16) type = CPL_TYPE_INT;
1628  else
1629  {
1630  assure( false, CPL_ERROR_UNSUPPORTED_MODE,
1631  "No CPL type to represent BITPIX = %d", bitpix);
1632  }
1633 
1634  check( naxis = uves_pfits_get_naxis(plist),
1635  "could not get NAXIS" );
1636 
1637  if( naxis == 1) {
1638 
1639  check( vector = cpl_vector_load(filename,extension),
1640  "Could not load vector from extension %d of file '%s' ",
1641  extension, filename);
1642  cknull(image=uves_vector_to_image(vector,type),
1643  "could not convert vector to image");
1644  } else {
1645 
1646 
1647  check( image = cpl_image_load(filename,
1648  type,
1649  plane,
1650  extension),
1651  "Could not load image from extension %d of file '%s' ",
1652  extension, filename);
1653 
1654  }
1655 
1656  if (header != NULL)
1657  {
1658  *header = uves_propertylist_duplicate(plist);
1659  }
1660 
1661  cleanup:
1662  uves_free_vector(&vector);
1663  uves_free_propertylist(&plist);
1664  return image;
1665 }
1666 /*----------------------------------------------------------------------------*/
1670 /*----------------------------------------------------------------------------*/
1671 
1672 cpl_image *uves_load_image_file(const char *filename,
1673  int plane,
1674  int extension,
1675  uves_propertylist **header)
1676 {
1677  cpl_image *i;
1678  cpl_frame *f = cpl_frame_new();
1679  cpl_frame_set_filename(f, filename);
1680  cpl_frame_set_type(f, CPL_FRAME_TYPE_IMAGE);
1681 
1682  i = uves_load_image(f, plane, extension, header);
1683 
1684  uves_free_frame(&f);
1685 
1686  return i;
1687 }
1688 
1689 /*----------------------------------------------------------------------------*/
1714 /*----------------------------------------------------------------------------*/
1715 void
1716 uves_save_image(const cpl_image *image, const char *filename, const uves_propertylist *plist,
1717  bool use_bitpix16_for_int, bool save1d)
1718 {
1719  cpl_type_bpp bpp;
1720  cpl_type t;
1721  const cpl_vector *image_1d = NULL;
1722  uves_propertylist *header = NULL;
1723  cpl_image *thresholded = NULL;
1724  cpl_image *thresholded_double = NULL;
1725 
1726  if (image == NULL) {
1727  check( uves_image_save(image, filename, CPL_BPP_IEEE_FLOAT, plist, CPL_IO_DEFAULT),
1728  "Error saving NULL image to file '%s'", filename);
1729  }
1730  else {
1731  check( t = cpl_image_get_type(image), "Error reading image type");
1732  if (t == CPL_TYPE_FLOAT ) bpp = CPL_BPP_IEEE_FLOAT;
1733  else if (t == CPL_TYPE_DOUBLE) bpp = CPL_BPP_IEEE_FLOAT;
1734  /* Internal computations in double precision,
1735  save as single precision */
1736 
1737  /* Some FLAMES images are BITPIX=16 (ORDEF),
1738  some are 32 SLIT_FF_COM_REDL
1739  */
1740  else if (t == CPL_TYPE_INT ) {
1741  if (use_bitpix16_for_int) bpp = CPL_BPP_16_UNSIGNED;
1742  else bpp = CPL_BPP_32_SIGNED;
1743  }
1744  else assure(false, CPL_ERROR_UNSUPPORTED_MODE,
1745  "Unsupported image type '%s'", uves_tostring_cpl_type(t));
1746 
1747 
1748  thresholded = cpl_image_duplicate(image);
1749  assure_mem( thresholded );
1750 
1751  if (t == CPL_TYPE_DOUBLE)
1752  {
1753  passure( bpp == CPL_BPP_IEEE_FLOAT, "%d", bpp);
1754 
1755  /* Avoid infinities that would happen when casting
1756  double -> float
1757  by thresholding the image to +-FLT_MAX (or, better
1758  a little less than FLT_MAX just to be sure).
1759 
1760  (This is not a really nice solution because it solves the
1761  problem (too large/small values) after it is introduced
1762  (rather than avoiding it), but a general solution of the
1763  problem would probably mean guarding every arithmetic
1764  operation with range checks.)
1765  */
1766 
1767  check_nomsg( cpl_image_threshold(thresholded,
1768  -FLT_MAX, FLT_MAX,
1769  -FLT_MAX, FLT_MAX) );
1770 
1771  /* Also get rid of NaN, set to zero (what else?) */
1772  {
1773  double *data = cpl_image_get_data_double(thresholded);
1774  int nx = cpl_image_get_size_x(thresholded);
1775  int ny = cpl_image_get_size_y(thresholded);
1776  int x, y;
1777 
1778  for (y = 0; y < ny; y++)
1779  for (x = 0; x < nx; x++)
1780  {
1781  if (irplib_isnan(data[x + y*nx]))
1782  {
1783  data[x + y*nx] = 0;
1784  }
1785  }
1786  }
1787  }
1788 
1789  if (save1d &&
1790  cpl_image_get_size_y(thresholded) == 1 &&
1791  (t == CPL_TYPE_DOUBLE ||
1792  t == CPL_TYPE_FLOAT)) {
1793 
1794  bool invert = false;
1795  if (plist != NULL)
1796  {
1797  header = uves_propertylist_duplicate(plist);
1798 
1799  uves_propertylist_erase_regexp(header, "^CDELT2$", invert);
1800  uves_propertylist_erase_regexp(header, "^CRPIX2$", invert);
1801  uves_propertylist_erase_regexp(header, "^CRVAL2$", invert);
1802  uves_propertylist_erase_regexp(header, "^CTYPE2$", invert);
1803  if(uves_propertylist_has(plist,"CDELT1")) {
1804  double cdelt1=uves_pfits_get_cdelt1(header);
1805  uves_pfits_set_cd11(header,cdelt1);
1806  }
1807  }
1808  else
1809  {
1810  header = NULL;
1811  }
1812 
1813  /* Image type must be double, before wrapping it
1814  in a vector */
1815  if (t == CPL_TYPE_FLOAT) {
1816  thresholded_double = cpl_image_cast(thresholded, CPL_TYPE_DOUBLE);
1817  }
1818  else {
1819  thresholded_double = cpl_image_duplicate(thresholded);
1820  }
1821 
1822  passure( cpl_image_get_type(thresholded_double) == CPL_TYPE_DOUBLE, "%d",
1823  cpl_image_get_type(thresholded_double));
1824 
1825  image_1d = cpl_vector_wrap(
1826  cpl_image_get_size_x(thresholded_double),
1827  cpl_image_get_data_double(thresholded_double));
1828 
1829  check( uves_vector_save(image_1d, filename, bpp, header, CPL_IO_DEFAULT),
1830  "Error saving vector to file '%s'", filename );
1831  }
1832  else
1833  {
1834 
1835  if (plist != NULL) {
1836  if(uves_propertylist_has(plist,"CDELT1")) {
1837  double cdelt1=uves_pfits_get_cdelt1(plist);
1838  uves_pfits_set_cd11(plist,cdelt1);
1839  uves_pfits_set_cd12(plist,0);
1840  }
1841  if(uves_propertylist_has(plist,"CDELT2")) {
1842  double cdelt2=uves_pfits_get_cdelt2(plist);
1843  uves_pfits_set_cd21(plist,0);
1844  uves_pfits_set_cd22(plist,cdelt2);
1845  }
1846  }
1847 
1848 
1849  check( uves_image_save(thresholded, filename, bpp, plist, CPL_IO_DEFAULT),
1850  "Error saving image to file '%s'", filename);
1851  }
1852  }
1853 
1854  cleanup:
1855  uves_unwrap_vector_const(&image_1d);
1856  uves_free_propertylist(&header);
1857  uves_free_image(&thresholded);
1858  uves_free_image(&thresholded_double);
1859 
1860  return;
1861 }
1862 
1863 
1864 /*----------------------------------------------------------------------------*/
1884 /*----------------------------------------------------------------------------*/
1885 void
1886 uves_save_imagelist(const cpl_imagelist *iml, const char *filename, const uves_propertylist *plist)
1887 {
1888  const cpl_image* img=NULL;
1889  cpl_type_bpp bpp;
1890  cpl_type t;
1891  const cpl_vector *image_1d = NULL;
1892  uves_propertylist *header = NULL;
1893  cpl_imagelist *thresholded = NULL;
1894 
1895  int nx = 0;
1896  int ny = 0;
1897  int nz = 0;
1898 
1899 
1900  cknull(iml,"Null input image");
1901  check(img=cpl_imagelist_get_const(iml,0),"error reading image");
1902 
1903  check_nomsg( nx = cpl_image_get_size_x(img));
1904  check_nomsg( ny = cpl_image_get_size_y(img));
1905  check_nomsg( nz = cpl_imagelist_get_size(iml));
1906 
1907  check( t = cpl_image_get_type(img), "Error reading image type");
1908  if (t == CPL_TYPE_FLOAT ) bpp = CPL_BPP_IEEE_FLOAT;
1909  else if (t == CPL_TYPE_DOUBLE) bpp = CPL_BPP_IEEE_FLOAT;
1910  /* Internal computations in double precision,
1911  save as single precision */
1912  else if (t == CPL_TYPE_INT ) bpp = CPL_BPP_16_UNSIGNED;
1913  else assure(false, CPL_ERROR_UNSUPPORTED_MODE,
1914  "Unsupported image type '%s'", uves_tostring_cpl_type(t));
1915 
1916 
1917  thresholded = cpl_imagelist_duplicate(iml);
1918  assure_mem( thresholded );
1919 
1920  if (t == CPL_TYPE_DOUBLE)
1921  {
1922  passure( bpp == CPL_BPP_IEEE_FLOAT, "%d", bpp);
1923 
1924  /* Avoid infinities that would happen when casting
1925  double -> float
1926  by thresholding the image to +-FLT_MAX (or, better
1927  a little less than FLT_MAX just to be sure).
1928 
1929  (This is not a really nice solution because it solves the
1930  problem (too large/small values) after it is introduced
1931  (rather than avoiding it), but a general solution of the
1932  problem would probably mean guarding every arithmetic
1933  operation with range checks.)
1934  */
1935 
1936  check_nomsg( cpl_imagelist_threshold(thresholded,
1937  -FLT_MAX, FLT_MAX,
1938  -FLT_MAX, FLT_MAX) );
1939 
1940 
1941 
1942  /* Also get rid of NaN, set to zero (what else?) */
1943  {
1944  int x, y, z;
1945  double* data=NULL;
1946  cpl_image* ima=NULL;
1947  for (z = 0; z < nz; z++) {
1948  ima=cpl_imagelist_get(thresholded,z);
1949  data = cpl_image_get_data_double(ima);
1950 
1951  for (y = 0; y < ny; y++) {
1952  for (x = 0; x < nx; x++) {
1953  if (irplib_isnan(data[x + y*nx])) {
1954  data[x + y*nx] = 0;
1955  }
1956  }
1957  }
1958  }
1959  }
1960  }
1961  if (nz == 1 && t == CPL_TYPE_DOUBLE)
1962  /* To support other types (float, int) we would
1963  need to convert to double first */
1964  {
1965  bool invert = false;
1966  if (plist != NULL)
1967  {
1968  header = uves_propertylist_duplicate(plist);
1969 
1970  uves_propertylist_erase_regexp(header, "^CDELT3$", invert);
1971  uves_propertylist_erase_regexp(header, "^CRPIX3$", invert);
1972  uves_propertylist_erase_regexp(header, "^CRVAL3$", invert);
1973  uves_propertylist_erase_regexp(header, "^CTYPE3$", invert);
1974  }
1975  else
1976  {
1977  header = NULL;
1978  }
1979  /*
1980  image_1d = cpl_vector_wrap(nx,
1981  cpl_image_get_data_double_const(thresholded));
1982 
1983  check( uves_vector_save(image_1d, filename, bpp, header, CPL_IO_DEFAULT),
1984  "Error saving vector to file '%s'", filename );
1985  */
1986 
1987  }
1988  else
1989  {
1990  check( uves_imagelist_save(thresholded, filename, bpp, plist, CPL_IO_DEFAULT),
1991  "Error saving image to file '%s'", filename);
1992  }
1993 
1994  cleanup:
1995  uves_unwrap_vector_const(&image_1d);
1996  uves_free_propertylist(&header);
1997  uves_free_imagelist(&thresholded);
1998 
1999  return;
2000 }
2001 
2002 /*----------------------------------------------------------------------------*/
2016 /*----------------------------------------------------------------------------*/
2017 cpl_error_code
2018 uves_save_polynomial(polynomial *p, const char *filename, const uves_propertylist *header)
2019 {
2020  cpl_table *t = NULL;
2021 
2022  check( t = uves_polynomial_convert_to_table(p), "Error converting polynomial to table");
2023 
2024  check( uves_table_save(t,
2025  NULL, /* Primary header, ignored when
2026  mode = CPL_IO_EXTEND */
2027  header, /* Table header */
2028  filename,
2029  CPL_IO_EXTEND), /* Append to existing file */
2030  "Error saving table to file '%s'", filename);
2031 
2032  cleanup:
2033  uves_free_table(&t);
2034  return cpl_error_get_code();
2035 }
2036 
2037 
2038 /*----------------------------------------------------------------------------*/
2046 /*----------------------------------------------------------------------------*/
2047 static polynomial *
2048 load_polynomial(const char* filename, int extension)
2049 {
2050  polynomial *p = NULL; /* Result */
2051  cpl_table *t = NULL;
2052 
2053  check(t = cpl_table_load(filename,
2054  extension,
2055  1), /* Mark identified
2056  invalid null values (1=yes) */
2057  "Error loading polynomial from extension %d of file '%s'", extension, filename);
2058 
2059  assure( uves_erase_invalid_table_rows(t, NULL) == 0,
2060  CPL_ERROR_ILLEGAL_INPUT, "Table contains invalid rows");
2061 
2062  check(p = uves_polynomial_convert_from_table(t), "Error converting table to polynomial");
2063 
2064  cleanup:
2065  uves_free_table(&t);
2066  if (cpl_error_get_code() != CPL_ERROR_NONE)
2068  return p;
2069 }
2070 /*----------------------------------------------------------------------------*/
2085 /*----------------------------------------------------------------------------*/
2086 static const char *
2087 identify_arm(const cpl_frameset *frames, const char *blue_tag, const char *red_tag,
2088  bool *blue)
2089 {
2090  const char *tag = NULL; /* Result */
2091 
2092  const cpl_frame *frame = NULL;
2093 
2094  passure( frames != NULL, "");
2095  assure (!cpl_frameset_is_empty(frames), CPL_ERROR_ILLEGAL_INPUT, "No input frames");
2096 
2097  /* Identify blue/red arm */
2098  frame = cpl_frameset_find_const(frames, blue_tag);
2099  *blue = (frame != NULL);
2100 
2101  if (frame == NULL)
2102  {
2103  frame = cpl_frameset_find_const(frames, red_tag);
2104  }
2105 
2106  assure( frame != NULL, CPL_ERROR_ILLEGAL_INPUT,
2107  "No valid input frames "
2108  "('%s' or '%s') in frame set",
2109  blue_tag, red_tag);
2110 
2111  assure( cpl_frameset_find_const(frames, blue_tag) == NULL ||
2112  cpl_frameset_find_const(frames, red_tag) == NULL,
2113  CPL_ERROR_INCOMPATIBLE_INPUT,
2114  "Multiple types of input frames ('%s' and '%s') in frame set",
2115  blue_tag, red_tag);
2116 
2117  tag = cpl_frame_get_tag(frame);
2118 
2119  uves_msg("Input frames are '%s'", tag);
2120 
2121 
2122  cleanup:
2123  return tag;
2124 }
2125 
2126 /*----------------------------------------------------------------------------*/
2144 /*----------------------------------------------------------------------------*/
2145 cpl_image *
2146 uves_crop_and_rotate(const cpl_image *image, const uves_propertylist *header,
2147  enum uves_chip chip,
2148  const uves_propertylist *redl_header,
2149  bool new_format, uves_propertylist **out_header)
2150 {
2151  cpl_image *result = NULL;
2152  int prescanx, ovrscanx;
2153  cpl_size nx, ny;
2154  int x_0, y_0, x_1, y_1; /* Extracted area (inclusive) in
2155  FITS convention (i.e. counting from 1) */
2156 
2157  const char *ctype1, *ctype2; /* Geometry */
2158  const char *cunit1, *cunit2; /* Units */
2159  const char *bunit;
2160  double bscale=0;
2161  double crval1, crval2;
2162  double crpix1, crpix2;
2163  double cdelt1, cdelt2;
2164 
2165 
2166  passure( image != NULL, " ");
2167  passure( header != NULL, " ");
2168  passure( out_header != NULL, " ");
2169 
2170  nx = cpl_image_get_size_x(image);
2171  ny = cpl_image_get_size_y(image);
2172 
2173 
2174  /* Determine pre- and overscan areas */
2175  check( prescanx = uves_pfits_get_prescanx(header, chip), "Could not read x-prescan info" );
2176  check( ovrscanx = uves_pfits_get_ovrscanx(header, chip), "Could not read x-overscan info");
2177 
2178  /* Don't try to read the y pre- and overscan regions, which should be zero for UVES.
2179  The keywords are not present in older UVES data. */
2180 
2181  /* Read geometry */
2182  check( ctype1 = uves_pfits_get_ctype1(header), "Error reading keyword");
2183  check( ctype2 = uves_pfits_get_ctype2(header), "Error reading keyword");
2184  check( crval1 = uves_pfits_get_crval1(header), "Error reading keyword");
2185  check( crval2 = uves_pfits_get_crval2(header), "Error reading keyword");
2186  check( crpix1 = uves_pfits_get_crpix1(header), "Error reading keyword");
2187  check( crpix2 = uves_pfits_get_crpix2(header), "Error reading keyword");
2188  check( cdelt1 = uves_pfits_get_cdelt1(header), "Error reading keyword");
2189  check( cdelt2 = uves_pfits_get_cdelt2(header), "Error reading keyword");
2190  if (uves_propertylist_contains(header, UVES_BUNIT))
2191  {
2192  bunit = uves_pfits_get_bunit(header);
2193  }
2194  else
2195  {
2196  bunit = " ";
2197  }
2198  if (uves_propertylist_contains(header, UVES_BSCALE))
2199  {
2200  bscale = uves_pfits_get_bscale(header);
2201  }
2202  else
2203  {
2204  bscale = 0;
2205  }
2206 
2207  if (uves_propertylist_contains(header, UVES_CUNIT1))
2208  {
2209  cunit1 = uves_pfits_get_cunit1(header);
2210  }
2211  else
2212  {
2213  cunit1 = " ";
2214  }
2215  if (uves_propertylist_contains(header, UVES_CUNIT2))
2216  {
2217  cunit2 = uves_pfits_get_cunit2(header);
2218  }
2219  else
2220  {
2221  cunit2 = " ";
2222  }
2223 
2224 
2225  /* Crop the image */
2226  {
2227  y_0 = 1;
2228  y_1 = ny;
2229  if (new_format || chip == UVES_CHIP_BLUE)
2230  {
2231  x_0 = prescanx + 1;
2232  x_1 = nx - ovrscanx;
2233  }
2234  else /* red, old format */
2235  {
2236  if (chip == UVES_CHIP_REDU)
2237  {
2238  x_0 = prescanx + 1;
2239  x_1 = nx/2 - ovrscanx;
2240  }
2241  else
2242  { /* lower */
2243  x_0 = nx/2 + prescanx + 1;
2244  x_1 = nx - ovrscanx;
2245  }
2246  }
2247  check( result = cpl_image_extract(image, x_0, y_0, x_1, y_1), "Could not crop image");
2248  crpix1 = crpix1 - (x_0 - 1);
2249  crpix2 = crpix2 - (y_0 - 1);
2250  nx = (x_1 - x_0) + 1;
2251  ny = (y_1 - y_0) + 1;
2252  }
2253 
2254  UVES_TIME_START("Rotation");
2255  /* ... is a bit slow, and there's probably nothing to
2256  do about as it involves moving data between remote
2257  places in memory.
2258  */
2259 
2260  /* Rotate the image into standard orientation */
2261  {
2262  int crpix1_old = crpix1;
2263  int crpix2_old = crpix2;
2264  int crval1_old = crval1;
2265  int crval2_old = crval2;
2266  int cdelt1_old = cdelt1;
2267  int cdelt2_old = cdelt2;
2268  const char *ctype1_old = ctype1;
2269  const char *ctype2_old = ctype2;
2270 
2271  if (chip == UVES_CHIP_BLUE)
2272  {
2273  /* 90 deg counterclockwise rotation */
2274  check( cpl_image_turn(result, -1), "Could not turn image");
2275 
2276  crpix1 = ny - (crpix2_old - 1); /* Note: old value of ny */
2277  crpix2 = crpix1_old;
2278  crval1 = crval2_old;
2279  crval2 = crval1_old;
2280  }
2281  else
2282  {
2283  /* Red */
2284  /* Flip image around y=-x */
2285  check( cpl_image_flip(result, 3), "Could not flip image");
2286 
2287  crpix1 = ny - (crpix2_old - 1); /* Note: old value of nx, ny */
2288  crpix2 = nx - (crpix1_old - 1);
2289  crval1 = crval2_old;
2290  crval2 = crval1_old;
2291  }
2292 
2293 
2294  /* Always swap these ones */
2295  ctype1 = ctype2_old;
2296  ctype2 = ctype1_old;
2297  cdelt1 = cdelt2_old;
2298  cdelt2 = cdelt1_old;
2299  }
2300 
2301  UVES_TIME_END;
2302 
2303  /* Here we should use the CROTAi keywords to
2304  properly describe the new rotation */
2305 
2306  /* Instead, redefine CRVAL as in the following, on request from DFO */
2307 
2308  crpix1 = 1;
2309  crpix2 = 1;
2310  if (chip == UVES_CHIP_BLUE || chip == UVES_CHIP_REDL)
2311  {
2312  crval1 = 1;
2313  crval2 = 1;
2314  }
2315  else
2316  {
2317  int physical_gap_between_chips = 64; /* Pixels. Unbinned. Hardcoded. */
2318 
2319 
2320  passure( chip == UVES_CHIP_REDU , "%d", chip );
2321 
2322  crval1 = 1;
2323 
2324  /* Set CRVAL2 = REDL_height - REDL_overscan - REDL_prescan + gap. */
2325  if (new_format)
2326  {
2327 
2328  check( crval2 = 1 +
2329  (uves_pfits_get_naxis1(redl_header) -
2330  uves_pfits_get_ovrscanx(redl_header, UVES_CHIP_REDL) -
2331  uves_pfits_get_prescanx(redl_header, UVES_CHIP_REDL)) *
2332  uves_pfits_get_cdelt1(redl_header) +
2333  physical_gap_between_chips,
2334  "Error reading REDL chip geometry");
2335 
2336  uves_msg_debug("Setting CRVAL2 = 1 + (%d - %d - %d) * %f + %d = %f",
2337  uves_pfits_get_naxis1(redl_header),
2338  uves_pfits_get_ovrscanx(redl_header, UVES_CHIP_REDL),
2339  uves_pfits_get_prescanx(redl_header, UVES_CHIP_REDL),
2340  uves_pfits_get_cdelt1(redl_header),
2341  physical_gap_between_chips, crval2);
2342  }
2343  else
2344  {
2345 
2346  /* old format */
2347  check( crval2 = 1 +
2348  (uves_pfits_get_naxis1(header)/2 -
2349  uves_pfits_get_ovrscanx(redl_header, UVES_CHIP_REDL) -
2350  uves_pfits_get_prescanx(redl_header, UVES_CHIP_REDL)) *
2351  uves_pfits_get_cdelt1(redl_header) +
2352  physical_gap_between_chips,
2353  "Error reading REDL chip geometry");
2354 
2355  uves_msg_debug("Setting CRVAL2 = 1 + (%d - %d - %d) * %f + %d = %f",
2356  uves_pfits_get_naxis1(header)/2,
2357  uves_pfits_get_ovrscanx(redl_header, UVES_CHIP_REDL),
2358  uves_pfits_get_prescanx(redl_header, UVES_CHIP_REDL),
2359  uves_pfits_get_cdelt1(redl_header),
2360  physical_gap_between_chips, crval2);
2361  }
2362 
2363  }
2364 
2365 
2366  /* Update header with new geometry */
2367  check( *out_header = uves_initialize_image_header(ctype1, ctype2,
2368  cunit1, cunit2,
2369  bunit,bscale,
2370  crval1, crval2,
2371  crpix1, crpix2,
2372  cdelt1, cdelt2),
2373  "Error initializing header");
2374 
2375  //check(uves_propertylist_copy_property_regexp(*out_header, header,
2376  // "^ESO ", 0),
2377  // "Error copying hieararch keys");
2378 
2379 
2380  uves_msg("Raw image cropped and rotated from %" CPL_SIZE_FORMAT "x%" CPL_SIZE_FORMAT " to %" CPL_SIZE_FORMAT "x%" CPL_SIZE_FORMAT "",
2381  nx, ny,
2382  cpl_image_get_size_x(result),
2383  cpl_image_get_size_y(result));
2384 
2385  cleanup:
2386  if (cpl_error_get_code() != CPL_ERROR_NONE)
2387  {
2388  uves_free_image(&result);
2389  if (out_header != NULL)
2390  {
2391  uves_free_propertylist(out_header);
2392  }
2393  }
2394 
2395  return result;
2396 }
2397 
2398 /*----------------------------------------------------------------------------*/
2412 /*----------------------------------------------------------------------------*/
2413 void
2414 uves_warn_if_chip_names_dont_match(const uves_propertylist *calib_header,
2415  const char *raw_chip_name, enum uves_chip chip)
2416 {
2417  const char *calib_chip_name;
2418  bool mismatch = false;
2419 
2420  check( calib_chip_name = uves_pfits_get_chipid(calib_header, chip),
2421  "Could not read chip name of calibration data");
2422 
2423 
2424  /* Ignore leading/trailing blanks when comparing name strings.
2425  * (The following is O(n^2) where n is the string length,
2426  * but that's ok because the strings stored in a FITS card are short).
2427  */
2428  {
2429  unsigned int calib_first, calib_last; /* inclusive */
2430  unsigned int raw_first, raw_last;
2431 
2432  calib_first = 0;
2433  raw_first = 0;
2434  while (calib_chip_name[calib_first] == ' ' && calib_first < strlen(calib_chip_name) - 1)
2435  {
2436  calib_first++;
2437  }
2438  while (raw_chip_name[raw_first] == ' ' && raw_first < strlen(raw_chip_name) - 1)
2439  {
2440  raw_first++;
2441  }
2442 
2443  calib_last = strlen(calib_chip_name) - 1;
2444  raw_last = strlen(raw_chip_name) - 1;
2445  while (calib_chip_name[calib_last] == ' ' && calib_last > 0)
2446  {
2447  calib_last--;
2448  }
2449  while (raw_chip_name[raw_last] == ' ' && raw_last > 0)
2450  {
2451  raw_last--;
2452  }
2453 
2454  /* Compare substrings */
2455  if (calib_last - calib_first != raw_last - raw_first)
2456  {
2457  mismatch = true;
2458  }
2459  else
2460  {
2461  unsigned int i;
2462 
2463  for (i = 0; i <= (calib_last - calib_first); i++)
2464  {
2465  if (raw_chip_name[raw_first + i] !=
2466  calib_chip_name[calib_first + i])
2467  {
2468  mismatch = true;
2469  }
2470  }
2471  }
2472  }
2473 
2474 
2475  if (mismatch)
2476  {
2477  uves_msg_warning("Calibration frame chip ID '%s' does "
2478  "not match raw frame chip ID '%s'",
2479  calib_chip_name, raw_chip_name);
2480  }
2481 
2482  cleanup:
2483  return;
2484 }
2485 
2486 
2487 /*----------------------------------------------------------------------------*/
2509 /*----------------------------------------------------------------------------*/
2510 
2511 static cpl_error_code
2512 load_raw_image(const char *filename,
2513  cpl_type type,
2514  bool flames,
2515  bool blue,
2516  cpl_image *raw_image[2],
2517  uves_propertylist *raw_header[2],
2518  uves_propertylist *rotated_header[2])
2519 {
2520 
2521 
2522  cpl_image *image = NULL;
2523  uves_propertylist *primary_header = NULL;
2524  uves_propertylist *ext_header = NULL;
2525  int extension, nextensions;
2526  bool new_format;
2527  int plane = 0; /* Only one plane in FLAMES/UVES raw files */
2528 
2529  cpl_image* image1=NULL;
2530  cpl_image* image2=NULL;
2531  int sx=0;
2532  int sy=0;
2533 
2534 
2535  /* Initialize parameters */
2536  raw_image[0] = NULL;
2537  raw_image[1] = NULL;
2538  raw_header[0] = NULL;
2539  raw_header[1] = NULL;
2540  rotated_header[0] = NULL;
2541  rotated_header[1] = NULL;
2542 
2543  check( nextensions = uves_get_nextensions(filename),
2544  "Error reading number of extensions of file '%s'", filename);
2545 
2546  /* Find out if new/old format */
2547  extension = 0;
2548  check( primary_header = uves_propertylist_load(filename,
2549  extension),
2550  "Could not load header from extension %d of file '%s'",
2551  extension, filename);
2552 
2553  check( new_format = uves_format_is_new(primary_header),
2554  "Error determining new/old format of file %s", filename);
2555 
2556  uves_msg_low("Raw frame is %s, %s format, file '%s' has %d extensions",
2557  (blue) ? "blue" : "red", (new_format) ? "new" : "old",
2558  filename, nextensions);
2559 
2560  /* If the raw frame is blue, or if it's an old format red frame */
2561  if (blue || !new_format)
2562  {
2563  enum uves_chip chip;
2564 
2565  uves_msg_debug("Frame is blue or old format");
2566 
2567  assure( nextensions == 0 ||
2568  (blue && nextensions == 2) ||
2569  (flames && nextensions == 2),
2570  CPL_ERROR_ILLEGAL_INPUT,
2571  "Unrecognized format of file '%s'. %d extensions expected. %d found.",
2572  filename,
2573  ((flames||blue) && (nextensions ==2)) ? 2 : 0, nextensions);
2574 
2575  /* FLAMES: the 2 extensions contain OzPoz table and FLAMES FIBRE table */
2576 
2577  /* Load the header */
2578  check( raw_header[0] = uves_propertylist_load(filename,
2579  extension),
2580  "Could not load header from extension %d of file '%s'",
2581  extension, filename);
2582 
2583 
2584  extension = 0;
2585  if(blue && nextensions == 2) {
2586  extension = 1;
2587  check( raw_header[1] = uves_propertylist_load(filename,
2588  extension),
2589  "Could not load header from extension %d of file '%s'",
2590  extension, filename);
2591  check( uves_propertylist_append(raw_header[0],raw_header[1]),
2592  "Could not collate header from extension 1 to 0 of file '%s'",filename);
2593  uves_free_propertylist(&raw_header[1]);
2594 
2595  check( image1 = cpl_image_load(filename,
2596  type,
2597  plane,
2598  extension
2599  ), "Could not load image from extension %d of file '%s' ",
2600  extension, filename);
2601  cpl_image_save(image1, "ima1.fits", CPL_BPP_IEEE_FLOAT,
2602  NULL,CPL_IO_DEFAULT);
2603 
2604  extension = 2;
2605  check( image2 = cpl_image_load(filename,
2606  type,
2607  plane,
2608  extension
2609  ), "Could not load image from extension %d of file '%s' ",
2610  extension, filename);
2611  check_nomsg(sx=cpl_image_get_size_x(image1));
2612  check_nomsg(sy=cpl_image_get_size_y(image1));
2613 
2614  check_nomsg(image=cpl_image_new(2*sx,sy,type));
2615  check_nomsg(cpl_image_copy(image,image1,1,1));
2616  check_nomsg(cpl_image_copy(image,image2,1+sx,1));
2617 
2618 
2619  uves_free_image(&image1);
2620  uves_free_image(&image2);
2621 
2622  extension = 1;
2623 
2624 
2625 
2626  } else {
2627 
2628 
2629  check( image = cpl_image_load(filename,
2630  type,
2631  plane,
2632  extension
2633  ), "Could not load image from extension %d of file '%s' ",
2634  extension, filename);
2635  }
2636 
2637  /* Get blue (or lower red) chip */
2638  chip = (blue) ? UVES_CHIP_BLUE : UVES_CHIP_REDL;
2639  check( raw_image[0] = uves_crop_and_rotate(image, raw_header[0],
2640  chip, raw_header[0],
2641  new_format,
2642  &rotated_header[0]),
2643  "Error splitting image");
2644 
2645  if (!blue)
2646  {
2647  const uves_propertylist *redl_header;
2648 
2649  /* Upper red chip, use again the primary header */
2650  check( raw_header[1] = uves_propertylist_duplicate(raw_header[0]),
2651  "Error duplicating FITS header");
2652 
2653  /* Get upper red chip */
2654  chip = UVES_CHIP_REDU;
2655  redl_header = raw_header[0];
2656  check( raw_image[1] = uves_crop_and_rotate(image, raw_header[1],
2657  chip, redl_header,
2658  new_format,
2659  &rotated_header[1]),
2660  "Error splitting red image");
2661  }
2662  else
2663  {
2664  raw_image[1] = NULL;
2665  raw_header[1] = NULL;
2666  rotated_header[1] = NULL;
2667  }
2668  }
2669  else
2670  /* New red format. UVES must have 2 extensions,
2671  * FLAMES must have 2 or more extensions
2672  */
2673  {
2674  uves_msg_debug("Frame is red, new format");
2675 
2676  assure( nextensions >= 2, CPL_ERROR_UNSUPPORTED_MODE,
2677  "File '%s' (red frame) has %d extensions. 2+ extensions expected "
2678  "for new format",
2679  filename, nextensions);
2680 
2681  uves_msg_debug("New red format, %s frame",
2682  (nextensions > 2) ? "FLAMES" : "FLAMES/UVES");
2683 
2684 
2685  /* Images always in extension 1 and 2. First load just the headers */
2686  for (extension = 1; extension <= 2; extension++)
2687  {
2688  /* In the FITS file, REDU is stored
2689  in extension 1, and REDL is stored in
2690  extension 2 */
2691  enum uves_chip chip = (extension == 1) ? UVES_CHIP_REDU : UVES_CHIP_REDL;
2692  int indx = uves_chip_get_index(chip);
2693 
2694  /* Load the extension header */
2695  uves_free_propertylist(&ext_header);
2696  check( ext_header = uves_propertylist_load(filename,
2697  extension),
2698  "Could not load header from extension %d of file '%s'",
2699  extension, filename);
2700 
2701  /* Merge with primary header */
2702  check( raw_header[indx] = uves_propertylist_duplicate(primary_header),
2703  "Error cloning primary header");
2704 
2705  if (!uves_propertylist_is_empty(ext_header))
2706  {
2708  ext_header, ".*", 0),
2709  "Error merging primary header with extension %d header",
2710  extension);
2711  }
2712  }
2713 
2714 
2715  /* Remove pre-, overscan areas (we needed to load both image headers for this) */
2716  for (extension = 1; extension <= 2; extension++)
2717  {
2718  enum uves_chip chip = (extension == 1) ? UVES_CHIP_REDU : UVES_CHIP_REDL;
2719  int indx = uves_chip_get_index(chip);
2720  int indx_redl = uves_chip_get_index(UVES_CHIP_REDL);
2721 
2722  const uves_propertylist *redl_header = raw_header[indx_redl];
2723 
2724  uves_free_image(&image);
2725  check( image = cpl_image_load(filename,
2726  type,
2727  plane,
2728  extension),
2729  "Could not load image from extension %d of file '%s' ",
2730  extension, filename);
2731 
2732  check( raw_image[indx] = uves_crop_and_rotate(image,
2733  raw_header[indx],
2734  chip, redl_header,
2735  new_format,
2736  &rotated_header[indx]),
2737  "Error splitting red image");
2738  }
2739 
2740 
2741  }/* if new format */
2742 
2743 
2744  cleanup:
2745  uves_free_image(&image);
2746  uves_free_image(&image1);
2747  uves_free_image(&image2);
2748 
2749  uves_free_propertylist(&primary_header);
2750  uves_free_propertylist(&ext_header);
2751 
2752  if (cpl_error_get_code() != CPL_ERROR_NONE)
2753  {
2754  uves_free_image (&raw_image[0]);
2755  uves_free_image (&raw_image[1]);
2756  uves_free_propertylist(&raw_header[0]);
2757  uves_free_propertylist(&raw_header[1]);
2758  uves_free_propertylist(&rotated_header[0]);
2759  uves_free_propertylist(&rotated_header[1]);
2760  }
2761 
2762  return cpl_error_get_code();
2763 }
2764 
2765 
2766 /*----------------------------------------------------------------------------*/
2794 /*----------------------------------------------------------------------------*/
2795 cpl_error_code
2796 uves_load_raw_imagelist(const cpl_frameset *frames,
2797  bool flames,
2798  const char *blue_tag, const char *red_tag, cpl_type type,
2799  cpl_imagelist *images[2],
2800  uves_propertylist **raw_headers[2], uves_propertylist *rotated_header[2],
2801  bool *blue)
2802 {
2803  const char *tag = NULL;
2804  const cpl_frame *frame = NULL;
2805  cpl_image *temp_image[2] = {NULL, NULL};
2806  uves_propertylist *temp_header[2] = {NULL, NULL};
2807  cpl_size number_of_frames = 0;
2808  int frameset_size = 0; /* Keeps track of number of raw_header pointers allocated */
2809  int nchips;
2810  int chip;
2811 
2812  raw_headers[0] = NULL;
2813  raw_headers[1] = NULL;
2814 
2815  check( frameset_size = cpl_frameset_get_size(frames),
2816  "Error reading frameset size");
2817 
2818  check( tag = identify_arm(frames, blue_tag, red_tag, blue),
2819  "Could not identify chip type");
2820 
2821  nchips = (*blue) ? 1 : 2;
2822  for(chip = 0; chip < nchips; chip++)
2823  {
2824  images[chip] = NULL;
2825  rotated_header[chip] = NULL;
2826 
2827  images[chip] = cpl_imagelist_new();
2828  raw_headers[chip] = cpl_calloc(frameset_size, sizeof(uves_propertylist *));
2829  }
2830 
2831  /* Load all input images with correct tag,
2832  split,
2833  insert into image list(s) */
2834 
2835  number_of_frames = 0;
2836  int i=0;
2837  int nfrm;
2838  nfrm=cpl_frameset_get_size(frames);
2839  for(i=0;i<nfrm;i++)
2840  {
2841  frame=cpl_frameset_get_frame_const(frames,i);
2842  /* If match */
2843  if ( strcmp(cpl_frame_get_tag(frame), tag) == 0)
2844  {
2845  const char *filename = cpl_frame_get_filename(frame);
2846 
2847  /* Load image + header */
2848  uves_free_propertylist(&rotated_header[0]);
2849  uves_free_propertylist(&rotated_header[1]);
2850 
2851  check( load_raw_image(filename,
2852  type,
2853  flames,
2854  *blue,
2855  temp_image,
2856  temp_header,
2857  rotated_header),
2858  "Could not load image from file '%s'", filename);
2859 
2860  /* Append to image lists */
2861  for(chip = 0; chip < nchips; chip++)
2862  {
2863  raw_headers[chip][number_of_frames] = temp_header[chip];
2864  temp_header[chip] = NULL;
2865 
2866  check( cpl_imagelist_set(images[chip],
2867  temp_image[chip],
2868  /* Position */
2869  cpl_imagelist_get_size(images[chip])
2870  ),
2871  "Could not insert image into image list");
2872 
2873  /* Don't deallocate image or header */
2874  temp_image[chip] = NULL;
2875  }
2876 
2877  number_of_frames += 1;
2878  }
2879  }
2880 
2881  /* Check that image sizes are identical */
2882 
2883  for(chip = 0; chip < nchips; chip++)
2884  {
2885  /* This function returns zero iff the list is uniform */
2886  assure (cpl_imagelist_is_uniform(images[chip]) == 0,
2887  CPL_ERROR_INCOMPATIBLE_INPUT,
2888  "Input images are not of same size and type");
2889 
2890  passure( cpl_imagelist_get_size(images[chip]) == number_of_frames,
2891  "%" CPL_SIZE_FORMAT " %" CPL_SIZE_FORMAT"", cpl_imagelist_get_size(images[0]), number_of_frames);
2892 
2893  }
2894 
2895 
2896  /* Check central wavelengths (not bias/dark) */
2897  if ( strcmp(UVES_BIAS (*blue), tag) != 0 &&
2898  strcmp(UVES_DARK (*blue), tag) != 0 &&
2899  strcmp(UVES_PDARK(*blue), tag) != 0) {
2900  enum uves_chip chip_id;
2901  int i;
2902  double wlen = 0;
2903 
2904  for (chip_id = uves_chip_get_first(*blue);
2905  chip_id != UVES_CHIP_INVALID;
2906  chip_id = uves_chip_get_next(chip_id)) {
2907  for (i = 0; i < number_of_frames; i++) {
2908  if (i == 0) {
2910  raw_headers[uves_chip_get_index(chip_id)][i], chip_id),
2911  "Error reading central wavelength of input frame number %d", i+1);
2912  }
2913  else {
2914  double w;
2915 
2917  raw_headers[uves_chip_get_index(chip_id)][i], chip_id),
2918  "Error reading central wavelength of input frame number %d", i+1);
2919 
2920  assure( fabs((w-wlen)/wlen) < 0.01, CPL_ERROR_INCOMPATIBLE_INPUT,
2921  "Mis-matching input frame central wavelengths: "
2922  "%e (frame 1) != %e (frame %d)", wlen, w, i+1);
2923  }
2924  }
2925  }
2926  }
2927 
2928  cleanup:
2929  uves_free_image(&temp_image[0]);
2930  uves_free_image(&temp_image[1]);
2931  uves_free_propertylist(&temp_header[0]);
2932  uves_free_propertylist(&temp_header[1]);
2933 
2934  if (cpl_error_get_code() != CPL_ERROR_NONE) {
2935  if (raw_headers[0] != NULL) {
2936  int i;
2937  for (i = 0; i < frameset_size; i++) {
2938  if (raw_headers[0] != NULL) uves_free_propertylist(&raw_headers[0][i]);
2939  if (raw_headers[1] != NULL) uves_free_propertylist(&raw_headers[1][i]);
2940  }
2941  }
2942  cpl_free(raw_headers[0]); raw_headers[0] = NULL;
2943  cpl_free(raw_headers[1]); raw_headers[1] = NULL;
2944 
2945  uves_free_imagelist(&images[0]);
2946  uves_free_imagelist(&images[1]);
2947 
2948  uves_free_propertylist(&rotated_header[0]);
2949  uves_free_propertylist(&rotated_header[1]);
2950  }
2951 
2952  return cpl_error_get_code();
2953 }
2954 
2955 
2956 /*----------------------------------------------------------------------------*/
2973 /*----------------------------------------------------------------------------*/
2974 cpl_error_code
2975 uves_load_orderpos(const cpl_frameset *frames,
2976  bool flames,
2977  const char **raw_filename,
2978  cpl_image *raw_image[2],
2979  uves_propertylist *raw_header[2],
2980  uves_propertylist *rotated_header[2], bool *blue)
2981 {
2982  const char *tags[4];
2983 
2984  int number_of_tags = sizeof(tags) / sizeof(char *);
2985  int indx;
2986 
2987  /* Warning: Duplicate logic. The number of tags must match the size of the
2988  tags array defined above */
2989  tags[0] = UVES_ORDER_FLAT(flames, false); /* red */
2990  tags[1] = UVES_ORDER_FLAT(flames, true); /* blue */
2991  tags[2] = UVES_STD_STAR(false);
2992  tags[3] = UVES_STD_STAR(true);
2993 
2994  if (flames)
2995  {
2996  *blue = false;
2997  number_of_tags = 1;
2998 
2999  check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx,
3000  NULL),
3001  "Could not find raw frame (%s) in SOF",
3002  tags[0]);
3003 
3004  }
3005  else
3006  {
3007  check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx,
3008  NULL),
3009  "Could not find raw frame (%s, %s, %s, or %s) in SOF",
3010  tags[0], tags[1], tags[2], tags[3]);
3011 
3012  *blue = (indx == 1) || (indx == 3);
3013  }
3014 
3015  /* Load the image */
3016  check( load_raw_image(*raw_filename,
3017  CPL_TYPE_DOUBLE,
3018  flames,
3019  *blue,
3020  raw_image,
3021  raw_header,
3022  rotated_header),
3023  "Error loading image from file '%s'", *raw_filename);
3024 
3025  passure( !flames || !(*blue), "%d %d",
3026  flames, *blue );
3027 
3028  cleanup:
3029  if (cpl_error_get_code() != CPL_ERROR_NONE)
3030  {
3031  *raw_filename = NULL;
3032  }
3033 
3034  return cpl_error_get_code();
3035 }
3036 
3037 /*----------------------------------------------------------------------------*/
3053 /*----------------------------------------------------------------------------*/
3054 cpl_error_code
3055 uves_load_formatcheck(const cpl_frameset *frames,
3056  bool flames,
3057  const char **raw_filename,
3058  cpl_image *raw_image[2],
3059  uves_propertylist *raw_header[2],
3060  uves_propertylist *rotated_header[2], bool *blue)
3061 {
3062  const char *tags[2];
3063  int number_of_tags = sizeof(tags) / sizeof(char *);
3064  int indx;
3065 
3066  tags[0] = UVES_FORMATCHECK(flames, false); /* red */
3067  tags[1] = UVES_FORMATCHECK(flames, true); /* blue */
3068  if (flames)
3069  {
3070  *blue = false;
3071  number_of_tags = 1;
3072 
3073  check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
3074  "Could not find raw frame (%s) in SOF",
3075  tags[0]);
3076  }
3077  else
3078  {
3079  check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
3080  "Could not find raw frame (%s or %s) in SOF",
3081  tags[0], tags[1]);
3082 
3083  *blue = (indx == 1);
3084  }
3085 
3086  /* Load the image */
3087  check( load_raw_image(*raw_filename,
3088  CPL_TYPE_DOUBLE,
3089  flames,
3090  *blue,
3091  raw_image,
3092  raw_header,
3093  rotated_header),
3094  "Error loading image from file '%s'", *raw_filename);
3095 
3096  cleanup:
3097  if (cpl_error_get_code() != CPL_ERROR_NONE)
3098  {
3099  *raw_filename = NULL;
3100  }
3101  return cpl_error_get_code();
3102 }
3103 
3104 /*----------------------------------------------------------------------------*/
3123 /*----------------------------------------------------------------------------*/
3124 void uves_load_cd_align(const cpl_frameset *frames,
3125  const char **raw_filename1,
3126  const char **raw_filename2,
3127  cpl_image *raw_image1[2],
3128  cpl_image *raw_image2[2],
3129  uves_propertylist *raw_header1[2],
3130  uves_propertylist *raw_header2[2],
3131  uves_propertylist *rotated_header1[2],
3132  uves_propertylist *rotated_header2[2],
3133  bool *blue)
3134 {
3135  const char *tags[2];
3136  int number_of_tags = sizeof(tags) / sizeof(char *);
3137  int indx;
3138  bool flames = false;
3139  const cpl_frame *frame;
3140 
3141  tags[0] = UVES_CD_ALIGN(false); /* red */
3142  tags[1] = UVES_CD_ALIGN(true); /* blue */
3143 
3144  check( *raw_filename1 = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
3145  "Could not find raw frame (%s or %s) in SOF",
3146  tags[0], tags[1]);
3147 
3148  *blue = (indx == 1);
3149 
3150  assure( cpl_frameset_count_tags(frames, tags[indx]) == 2,
3151  CPL_ERROR_ILLEGAL_INPUT,
3152  "%d %s frames found. Exactly 2 required",
3153  cpl_frameset_count_tags(frames, tags[indx]), tags[indx] );
3154 
3155  /* Load the two frames */
3156  {
3157  int n = 1;
3158  int i=0;
3159  int nfrm=cpl_frameset_get_size(frames);
3160  for (i = 0;i < nfrm;i++)
3161  {
3162  frame=cpl_frameset_get_frame_const(frames,i);
3163  if (strcmp(cpl_frame_get_tag(frame), tags[indx]) == 0)
3164  {
3165  if (n == 1)
3166  {
3167  *raw_filename1 = cpl_frame_get_filename(frame);
3168  }
3169  else
3170  {
3171  *raw_filename2 = cpl_frame_get_filename(frame);
3172  }
3173 
3174  check( load_raw_image(n == 1 ?
3175  *raw_filename1 :
3176  *raw_filename2,
3177  CPL_TYPE_DOUBLE,
3178  flames,
3179  *blue,
3180  n == 1 ?
3181  raw_image1 :
3182  raw_image2,
3183  n == 1 ?
3184  raw_header1 :
3185  raw_header2,
3186  n == 1 ?
3187  rotated_header1 :
3188  rotated_header2),
3189  "Error loading image from file '%s'",
3190  n == 1 ? *raw_filename1 : *raw_filename2);
3191 
3192  n++;
3193  }
3194  }
3195  }
3196 
3197  cleanup:
3198  if (cpl_error_get_code() != CPL_ERROR_NONE)
3199  {
3200  *raw_filename1 = NULL;
3201  *raw_filename2 = NULL;
3202  }
3203 
3204  return;
3205 }
3206 
3207 
3208 /*----------------------------------------------------------------------------*/
3229 /*----------------------------------------------------------------------------*/
3230 void
3231 uves_load_arclamp(const cpl_frameset *frames,
3232  bool flames,
3233  const char **raw_filename,
3234  cpl_image *raw_image[2], uves_propertylist *raw_header[2],
3235  uves_propertylist *rotated_header[2], bool *blue,
3236  bool *sim_cal)
3237 {
3238  const char *tags[4];
3239 
3240  int number_of_tags = sizeof(tags) / sizeof(char *);
3241  int indx;
3242 
3243  /* Warning: duplicate logic. Array size above must match */
3244  if (flames)
3245  {
3246  assure_nomsg( sim_cal != NULL, CPL_ERROR_NULL_INPUT );
3247 
3248  tags[0] = UVES_ARC_LAMP(flames, true); /* blue flag not used */
3249  tags[1] = FLAMES_FIB_SCI_SIM;
3250 
3251  number_of_tags = 2;
3252  *blue = false;
3253 
3254  check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
3255  "Could not find raw frame (%s or %s) in SOF",
3256  tags[0], tags[1]);
3257 
3258  *sim_cal = (indx == 1);
3259  }
3260  else
3261  {
3262  tags[0] = UVES_ARC_LAMP(flames, true);
3263  tags[1] = UVES_ARC_LAMP(flames, false);
3264  tags[2] = UVES_ECH_ARC_LAMP(true);
3265  tags[3] = UVES_ECH_ARC_LAMP(false);
3266 
3267  check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
3268  "Could not find raw frame (%s, %s, %s or %s) in SOF",
3269  tags[0], tags[1], tags[2], tags[3]);
3270 
3271  *blue = (indx == 0 || indx == 2);
3272  }
3273 
3274  /* Load the image */
3275  check( load_raw_image(*raw_filename,
3276  CPL_TYPE_DOUBLE,
3277  flames,
3278  *blue,
3279  raw_image,
3280  raw_header,
3281  rotated_header),
3282  "Error loading image from file '%s'", *raw_filename);
3283 
3284  cleanup:
3285  if (cpl_error_get_code() != CPL_ERROR_NONE) {
3286  *raw_filename = NULL;
3287  uves_free_image (raw_image);
3288  uves_free_propertylist(raw_header);
3289  }
3290  return;
3291 }
3292 
3293 /*----------------------------------------------------------------------------*/
3308 /*----------------------------------------------------------------------------*/
3309 cpl_error_code
3310 uves_load_science(const cpl_frameset *frames, const char **raw_filename,
3311  cpl_image *raw_image[2],
3312  uves_propertylist *raw_header[2],
3313  uves_propertylist *rotated_header[2],
3314  bool *blue,
3315  const char **sci_type)
3316 {
3317  /* Note: the two following arrays must match */
3318  const char *tags[] =
3319  {
3320  UVES_SCIENCE(true), UVES_SCIENCE(false),
3321  UVES_SCI_EXTND(true), UVES_SCI_EXTND(false),
3322  UVES_SCI_POINT(true), UVES_SCI_POINT(false),
3323  UVES_SCI_SLICER(true), UVES_SCI_SLICER(false),
3324  UVES_TFLAT(true), UVES_TFLAT(false)
3325  };
3326 
3327  const char *type[] =
3328  {
3329  "SCIENCE", "SCIENCE",
3330  "SCI_EXTND", "SCI_EXTND",
3331  "SCI_POINT", "SCI_POINT",
3332  "SCI_SLICER", "SCI_SLICER",
3333  "TFLAT", "TFLAT",
3334  };
3335 
3336  int number_of_tags = sizeof(tags) / sizeof(char *);
3337  int indx;
3338  bool flames = false;
3339 
3340  check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
3341  "No science frame (%s, %s, %s, %s, %s, %s, %s, %s, %s or %s) in SOF",
3342  tags[0], tags[1], tags[2], tags[3],
3343  tags[4], tags[5], tags[6], tags[7], tags[7], tags[8]);
3344 
3345  *blue = (indx % 2 == 0);
3346  *sci_type = type[indx];
3347 
3348  /* Load the image */
3349  check( load_raw_image(*raw_filename,
3350  CPL_TYPE_DOUBLE,
3351  flames,
3352  *blue,
3353  raw_image,
3354  raw_header,
3355  rotated_header),
3356  "Error loading image from file '%s'", *raw_filename);
3357  cleanup:
3358  if (cpl_error_get_code() != CPL_ERROR_NONE)
3359  {
3360  *raw_filename = NULL;
3361  uves_free_image (raw_image);
3362  uves_free_propertylist(raw_header);
3363  }
3364  return cpl_error_get_code();
3365 }
3366 
3367 /*----------------------------------------------------------------------------*/
3384 /*----------------------------------------------------------------------------*/
3385 cpl_error_code
3386 uves_load_standard(const cpl_frameset *frames, const char **raw_filename,
3387  cpl_image *raw_image[2],
3388  uves_propertylist *raw_header[2],
3389  uves_propertylist *rotated_header[2], bool *blue)
3390 {
3391  const char *tags[] = { UVES_STD_STAR(true), UVES_STD_STAR(false) };
3392  int number_of_tags = sizeof(tags) / sizeof(char *);
3393  int indx;
3394  bool flames = false;
3395 
3396  check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
3397  "Could not identify raw frame (%s or %s) in SOF", tags[0], tags[1]);
3398 
3399  *blue = (indx == 0);
3400 
3401  /* Load the image */
3402  check( load_raw_image(*raw_filename,
3403  CPL_TYPE_DOUBLE,
3404  flames,
3405  *blue,
3406  raw_image,
3407  raw_header,
3408  rotated_header),
3409  "Error loading image from file '%s'", *raw_filename);
3410 
3411  cleanup:
3412  if (cpl_error_get_code() != CPL_ERROR_NONE)
3413  {
3414  *raw_filename = NULL;
3415  uves_free_image (raw_image);
3416  uves_free_propertylist(raw_header);
3417  }
3418  return cpl_error_get_code();
3419 }
3420 
3421 /*----------------------------------------------------------------------------*/
3437 /*----------------------------------------------------------------------------*/
3438 
3439 cpl_error_code
3440 uves_load_drs(const cpl_frameset *frames,
3441  bool flames,
3442  const char *chip_name,
3443  const char **drs_filename,
3444  uves_propertylist **drs_header,
3445  enum uves_chip chip)
3446 {
3447  const char *tags[1];
3448  int number_of_tags = sizeof(tags) / sizeof(char *);
3449  int extension;
3450  int indx;
3451 
3452  *drs_header = NULL;
3453  tags[0] = UVES_DRS_SETUP(flames, chip);
3454  extension = UVES_DRS_SETUP_EXTENSION(chip);
3455 
3456  check( *drs_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
3457  "Could not find DRS table (%s) in SOF", tags[0]);
3458 
3459  /* Load the header */
3460  check( *drs_header = uves_propertylist_load(*drs_filename,
3461  extension),
3462  "Could not load header from extension %d of file '%s'", extension, *drs_filename);
3463 
3464  check_nomsg( uves_warn_if_chip_names_dont_match(*drs_header, chip_name, chip) );
3465 
3466  cleanup:
3467  if (cpl_error_get_code() != CPL_ERROR_NONE) {
3468  *drs_filename = NULL;
3469  uves_free_propertylist(drs_header);
3470  }
3471  return cpl_error_get_code();
3472 }
3473 
3474 /*----------------------------------------------------------------------------*/
3482 /*----------------------------------------------------------------------------*/
3483 cpl_image *
3484 uves_load_weights(const cpl_frameset *frames, const char **weights_filename,
3485  enum uves_chip chip)
3486 {
3487  cpl_image *weights = NULL;
3488  const char *tags[1];
3489  int number_of_tags = sizeof(tags) / sizeof(char *);
3490  int extension = 0;
3491  int indx;
3492 
3493  assure( weights_filename != NULL, CPL_ERROR_NULL_INPUT, "Null filename");
3494 
3495  tags[0] = UVES_WEIGHTS(chip);
3496 
3497  check( *weights_filename = uves_find_frame(frames,
3498  tags, number_of_tags, &indx, NULL),
3499  "Could not find '%s' in frame set", tags[0]);
3500 
3501  check( weights = cpl_image_load(*weights_filename,
3502  CPL_TYPE_DOUBLE, /* Convert to this type */
3503  0, /* plane number */
3504  extension /* Extension number */
3505  ),
3506  "Could not load master bias from extension %d of file '%s'",
3507  extension, *weights_filename);
3508 
3509  cleanup:
3510  return weights;
3511 }
3512 
3513 
3514 /*----------------------------------------------------------------------------*/
3530 /*----------------------------------------------------------------------------*/
3531 
3532 cpl_error_code
3533 uves_load_mbias(const cpl_frameset *frames, const char *chip_name,
3534  const char **mbias_filename,
3535  cpl_image **mbias, uves_propertylist **mbias_header, enum uves_chip chip)
3536 {
3537  const char *tags[1];
3538  int number_of_tags = sizeof(tags) / sizeof(char *);
3539  int extension;
3540  int indx;
3541 
3542  *mbias = NULL;
3543  *mbias_header = NULL;
3544 
3545  tags[0] = UVES_MASTER_BIAS (chip);
3546  extension = UVES_MASTER_BIAS_EXTENSION(chip);
3547 
3548  check( *mbias_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
3549  "Could not find '%s' in frame set", tags[0]);
3550 
3551  /* Load the mbias image */
3552  check( *mbias = cpl_image_load(*mbias_filename,
3553  CPL_TYPE_DOUBLE, /* Convert to this type */
3554  0, /* plane number */
3555  extension /* Extension number */
3556  ),
3557  "Could not load master bias from extension %d of file '%s'",
3558  extension, *mbias_filename);
3559 
3560  /* Load the header */
3561  check( *mbias_header = uves_propertylist_load(*mbias_filename,
3562  extension),
3563  "Could not load header from extension %d of file '%s'",
3564  extension, *mbias_filename);
3565 
3566  check_nomsg( uves_warn_if_chip_names_dont_match(*mbias_header, chip_name, chip) );
3567 
3568  cleanup:
3569  if (cpl_error_get_code() != CPL_ERROR_NONE)
3570  {
3571  *mbias_filename = NULL;
3572  uves_free_image(mbias);
3573  uves_free_propertylist(mbias_header);
3574  }
3575  return cpl_error_get_code();
3576 }
3577 
3578 
3579 /*----------------------------------------------------------------------------*/
3595 /*----------------------------------------------------------------------------*/
3596 
3597 cpl_error_code
3598 uves_load_master_formatcheck(const cpl_frameset *frames, const char *chip_name,
3599  const char **mform_filename,
3600  cpl_image **mform, uves_propertylist **mform_header, enum uves_chip chip)
3601 {
3602  const char *tags[1];
3603  int number_of_tags = sizeof(tags) / sizeof(char *);
3604  int extension;
3605  int indx;
3606 
3607  *mform = NULL;
3608  *mform_header = NULL;
3609 
3610  tags[0] = UVES_MASTER_ARC_FORM (chip);
3611  extension = UVES_MASTER_ARC_FORM_EXTENSION(chip);
3612 
3613  check( *mform_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
3614  "Could not find '%s' in frame set", tags[0]);
3615 
3616  /* Load the mbias image */
3617  check( *mform = cpl_image_load(*mform_filename,
3618  CPL_TYPE_DOUBLE, /* Convert to this type */
3619  0, /* plane number */
3620  extension /* Extension number */
3621  ),
3622  "Could not load master formatcheck from extension %d of file '%s'",
3623  extension, *mform_filename);
3624 
3625  /* Load the header */
3626 
3627  check( *mform_header = uves_propertylist_load(*mform_filename,
3628  extension),
3629  "Could not load header from extension %d of file '%s'",
3630  extension, *mform_filename);
3631 
3632  check_nomsg( uves_warn_if_chip_names_dont_match(*mform_header, chip_name, chip) );
3633 
3634  cleanup:
3635  if (cpl_error_get_code() != CPL_ERROR_NONE)
3636  {
3637  *mform_filename = NULL;
3638  uves_free_image(mform);
3639  uves_free_propertylist(mform_header);
3640  }
3641  return cpl_error_get_code();
3642 }
3643 
3644 /*----------------------------------------------------------------------------*/
3660 /*----------------------------------------------------------------------------*/
3661 
3662 cpl_error_code
3663 uves_load_mdark(const cpl_frameset *frames, const char *chip_name,
3664  const char **mdark_filename, cpl_image **mdark,
3665  uves_propertylist **mdark_header, enum uves_chip chip)
3666 {
3667  const char *tags[2];
3668  int number_of_tags = sizeof(tags) / sizeof(char *);
3669  int extension;
3670  int indx;
3671 
3672  *mdark = NULL;
3673  *mdark_header = NULL;
3674 
3675  tags[0] = UVES_MASTER_DARK (chip);
3676  tags[1] = UVES_MASTER_PDARK (chip);
3677  extension = UVES_MASTER_DARK_EXTENSION(chip);
3678 
3679  check( *mdark_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
3680  "Could not find %s or %s in frame set", tags[0], tags[1]);
3681 
3682  /* Load the mdark image */
3683  check( *mdark = cpl_image_load(*mdark_filename,
3684  CPL_TYPE_DOUBLE, /* Convert to this type */
3685  0, /* plane number */
3686  extension /* Extension number */
3687  ),
3688  "Could not load master dark from extension %d of file '%s'",
3689  extension, *mdark_filename);
3690 
3691  /* Load the header */
3692  check( *mdark_header = uves_propertylist_load(*mdark_filename,
3693  extension),
3694  "Could not load header from extension %d of file '%s'",
3695  extension, *mdark_filename);
3696 
3697  check_nomsg( uves_warn_if_chip_names_dont_match(*mdark_header, chip_name, chip) );
3698 
3699  cleanup:
3700  if (cpl_error_get_code() != CPL_ERROR_NONE)
3701  {
3702  *mdark_filename = NULL;
3703  uves_free_image(mdark);
3704  uves_free_propertylist(mdark_header);
3705  }
3706  return cpl_error_get_code();
3707 }
3708 /*----------------------------------------------------------------------------*/
3724 /*----------------------------------------------------------------------------*/
3725 void
3726 uves_load_ref_flat(const cpl_frameset *frames, const char *chip_name,
3727  const char **filename, cpl_image **rflat,
3728  uves_propertylist **rflat_header, enum uves_chip chip)
3729 {
3730  const char *tags[1];
3731  int number_of_tags = sizeof(tags) / sizeof(char *);
3732  int extension;
3733  int indx;
3734 
3735  *rflat = NULL;
3736  *rflat_header = NULL;
3737 
3738  tags[0] = UVES_REF_TFLAT(chip);
3739  extension = UVES_MASTER_FLAT_EXTENSION(chip);
3740 
3741  check( *filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
3742  "Could not find %s in frame set", tags[0]);
3743 
3744  check( *rflat = cpl_image_load(*filename,
3745  CPL_TYPE_DOUBLE, /* Convert to this type */
3746  0, /* plane number */
3747  extension /* Extension number */
3748  ),
3749  "Could not load reference dark from extension %d of file '%s'",
3750  extension, *filename);
3751 
3752  check( *rflat_header = uves_propertylist_load(*filename,
3753  extension),
3754  "Could not load header from extension %d of file '%s'",
3755  extension, *filename);
3756 
3757  check_nomsg( uves_warn_if_chip_names_dont_match(*rflat_header, chip_name, chip) );
3758 
3759  cleanup:
3760  if (cpl_error_get_code() != CPL_ERROR_NONE)
3761  {
3762  *filename = NULL;
3763  uves_free_image(rflat);
3764  uves_free_propertylist(rflat_header);
3765  }
3766 
3767  return;
3768 }
3769 
3770 /*----------------------------------------------------------------------------*/
3786 /*----------------------------------------------------------------------------*/
3787 
3788 cpl_error_code
3789 uves_load_mflat_const(const cpl_frameset *frames, const char *chip_name,
3790  const char **mflat_filename,
3791  cpl_image **mflat, uves_propertylist **mflat_header,
3792  enum uves_chip chip,
3793  const cpl_frame **mflat_frame)
3794 {
3795  const char *tags[6];
3796  int number_of_tags = sizeof(tags) / sizeof(char *);
3797  int extension;
3798  int indx;
3799 
3800  *mflat = NULL;
3801  *mflat_header = NULL;
3802 
3803  tags[0] = UVES_REF_TFLAT (chip); /* Use REF TFLAT, rather than MASTER_TFLAT */
3804  tags[1] = UVES_MASTER_FLAT (chip);
3805  tags[2] = UVES_MASTER_DFLAT (chip);
3806  tags[3] = UVES_MASTER_IFLAT (chip);
3807  tags[4] = UVES_MASTER_TFLAT (chip);
3808  tags[5] = UVES_MASTER_SCREEN_FLAT (chip);
3809  extension = UVES_MASTER_FLAT_EXTENSION(chip);
3810 
3811  check( *mflat_filename = uves_find_frame(frames, tags, number_of_tags, &indx,
3812  mflat_frame),
3813  "Could not find '%s', '%s', '%s', '%s' or '%s' in frame set",
3814  tags[0], tags[1], tags[2], tags[3], tags[4]);
3815 
3816  /* Load the mflat image */
3817  check( *mflat = cpl_image_load(*mflat_filename,
3818  CPL_TYPE_DOUBLE, /* Convert to this type */
3819  0, /* plane number */
3820  extension /* Extension number */
3821  ),
3822  "Could not load master flat from extension %d of file '%s'",
3823  extension, *mflat_filename);
3824 
3825  /* Load the header */
3826  check( *mflat_header = uves_propertylist_load(*mflat_filename,
3827  extension),
3828  "Could not load header from extension %d of file '%s'",
3829  extension, *mflat_filename);
3830 
3831  check_nomsg( uves_warn_if_chip_names_dont_match(*mflat_header, chip_name, chip) );
3832 
3833  cleanup:
3834  if (cpl_error_get_code() != CPL_ERROR_NONE)
3835  {
3836  *mflat_filename = NULL;
3837  uves_free_image(mflat);
3838  uves_free_propertylist(mflat_header);
3839  }
3840  return cpl_error_get_code();
3841 }
3842 
3843 /*----------------------------------------------------------------------------*/
3858 /*----------------------------------------------------------------------------*/
3859 cpl_error_code
3860 uves_load_mflat(cpl_frameset *frames, const char *chip_name,
3861  const char **mflat_filename,
3862  cpl_image **mflat, uves_propertylist **mflat_header, enum uves_chip chip,
3863  cpl_frame **mflat_frame)
3864 {
3865  return uves_load_mflat_const((const cpl_frameset *)frames,
3866  chip_name,
3867  mflat_filename,
3868  mflat, mflat_header, chip,
3869  (const cpl_frame **) mflat_frame);
3870 }
3871 
3872 /*----------------------------------------------------------------------------*/
3904 /*----------------------------------------------------------------------------*/
3905 cpl_error_code
3906 uves_load_ordertable(const cpl_frameset *frames,
3907  bool flames,
3908  const char *chip_name,
3909  const char **ordertable_filename,
3910  cpl_table **ordertable,
3911  uves_propertylist **ordertable_header,
3912  uves_propertylist **ordertable_xheader,
3913  polynomial **order_locations,
3914  cpl_table **traces,
3915  int *tab_in_out_oshift,
3916  double *tab_in_out_yshift,
3917  int ** fib_msk,
3918  double ** fib_pos,
3919  enum uves_chip chip,
3920  bool guess_table)
3921 {
3922  uves_propertylist *midas_header = NULL; /* Table header if midas format */
3923  uves_propertylist *prime_header = NULL; /* Prime header if flames */
3924  const char *tags[1];
3925  int number_of_tags = sizeof(tags) / sizeof(char *);
3926  bool format_is_midas;
3927  int *tioo = NULL;
3928  double *tioy = NULL;
3929  int indx;
3930 
3931  double *fibre_pos = NULL;
3932  int *fibre_mask = NULL;
3933 
3934  if (guess_table)
3935  {
3936  tags[0] = UVES_GUESS_ORDER_TABLE(flames, chip);
3937  }
3938  else
3939  {
3940  tags[0] = UVES_ORDER_TABLE(flames, chip);
3941  }
3942 
3943  check( *ordertable_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
3944  "No order table (%s) found in SOF", tags[0]);
3945 
3946  check( *ordertable = cpl_table_load(*ordertable_filename,
3947  UVES_ORDER_TABLE_EXTENSION,
3948  1), /* Mark identified
3949  invalid values? (1=yes) */
3950  "Error loading order table from extension %d of file '%s'",
3951  UVES_ORDER_TABLE_EXTENSION, *ordertable_filename);
3952 
3953  assure(ordertable_header != NULL,CPL_ERROR_NULL_INPUT,
3954  "NULL primary header uves_propertylist variable header");
3955  check( *ordertable_header = uves_propertylist_load(*ordertable_filename, 0),
3956  "Could not load header from extension 0 of '%s'", *ordertable_filename);
3957 
3958  if(ordertable_xheader != NULL) {
3959 
3960  check( *ordertable_xheader = uves_propertylist_load(*ordertable_filename, 1),
3961  "Could not load header from extension 1 of '%s'", *ordertable_filename);
3962 
3963 
3964 
3965  }
3966  check_nomsg( uves_warn_if_chip_names_dont_match(*ordertable_header, chip_name, chip) );
3967 
3968  check(uves_check_if_format_is_midas(*ordertable_header,&format_is_midas),
3969  "Error getting FITS format");
3970 
3971 
3972  if (!format_is_midas && !flames)
3973  {
3974  /* The format check and order position recipes create order tables
3975  with different column names. Rename if necessary.
3976 
3977  This is a workaround for the problem that different recipes
3978  create the same products (order tables and line tables).
3979  The true solution would be to remove the format check recipe from
3980  the recution cascade, and use the theoretical physical model to
3981  bootstrap the order definition and wavelength calibration.
3982  */
3983  if (cpl_table_has_column(*ordertable, "ORDER"))
3984  {
3985  cpl_table_name_column(*ordertable, "ORDER", "Order");
3986  }
3987  if (cpl_table_has_column(*ordertable, "YFIT"))
3988  {
3989  cpl_table_name_column(*ordertable, "YFIT", "Yfit");
3990  }
3991 
3992  if (order_locations != NULL)
3993  {
3994  check( *order_locations =
3995  load_polynomial(*ordertable_filename, UVES_ORDER_TABLE_EXTENSION_POLY),
3996  "Could not read polynomial from extension %d of file '%s'",
3997  UVES_ORDER_TABLE_EXTENSION_POLY, *ordertable_filename);
3998  }
3999 
4000  if (traces != NULL)
4001  {
4002  check( *traces = cpl_table_load(*ordertable_filename,
4003  UVES_ORDER_TABLE_EXTENSION_FIBRE,
4004  1), /* Mark identified
4005  invalid values? (1=yes) */
4006  "Error loading fibre table from extension %d of file '%s'",
4007  UVES_ORDER_TABLE_EXTENSION_FIBRE, *ordertable_filename);
4008  }
4009  }
4010  else
4011  /* MIDAS format, or FLAMES */
4012  {
4013  /* Rename */
4014  check(( cpl_table_cast_column (*ordertable, "ORDER", "Order", CPL_TYPE_INT),
4015  cpl_table_erase_column(*ordertable, "ORDER")),
4016  "Error casting and renaming column 'ORDER'");
4017 
4018  check( cpl_table_name_column(*ordertable, "YFIT", "Yfit"),
4019  "Error renaming column 'YFIT'");
4020 
4021  //check( midas_header = uves_propertylist_load(*ordertable_filename, 1),
4022  // "Could not load header from extension 1 of '%s'",
4023  // *ordertable_filename);
4024  check(midas_header = uves_propertylist_load(*ordertable_filename, 1),
4025  "Could not load header from extension 1 of '%s'",
4026  *ordertable_filename);
4027 
4028  if(flames) {
4029  check(prime_header = uves_propertylist_load(*ordertable_filename, 0),
4030  "Could not load header from extension 0 of '%s'",
4031  *ordertable_filename);
4032  check_nomsg(uves_propertylist_append(midas_header,prime_header));
4033  }
4034 
4035  /* Load polynomial named 'COEFF' from descriptors in extension 1 */
4036  if (order_locations != NULL)
4037  {
4038  check( *order_locations =
4039  uves_polynomial_convert_from_plist_midas(midas_header, "COEFF",-1),
4040  "Error reading polynomial from %s", *ordertable_filename);
4041  }
4042 
4043 
4044  if (flames && tab_in_out_oshift != NULL )
4045  {
4046  /* Get tab_in_out_oshift */
4047  int tioo_length;
4048  cpl_type tioo_type;
4049 
4050  check( tioo = uves_read_midas_array(
4051  midas_header, "TAB_IN_OUT_OSHIFT", &tioo_length,
4052  &tioo_type, NULL),
4053  "Error reading TAB_IN_OUT_OSHIFT from MIDAS header");
4054 
4055  assure( tioo_type == CPL_TYPE_INT, CPL_ERROR_TYPE_MISMATCH,
4056  "Type of TAB_IN_OUT_OSHIFT is %s, double expected",
4057  uves_tostring_cpl_type(tioo_type));
4058 
4059  if (tioo_length != 1)
4060  {
4061  uves_msg_warning("Length of TAB_IN_OUT_OSHIFT array is %d; "
4062  "%d expected", tioo_length, 1);
4063  }
4064 
4065  *tab_in_out_oshift = tioo[0];
4066 
4067  uves_msg_debug("TAB_IN_OUT_OSHIFT = %d", *tab_in_out_oshift);
4068 
4069  }
4070 
4071  if (flames && tab_in_out_yshift != NULL)
4072  {
4073  /* Get tab_in_out_yshift */
4074  int tioy_length;
4075  cpl_type tioy_type;
4076 
4077  check( tioy = uves_read_midas_array(
4078  midas_header, "TAB_IN_OUT_YSHIFT", &tioy_length,
4079  &tioy_type, NULL),
4080  "Error reading TAB_IN_OUT_YSHIFT from MIDAS header");
4081 
4082  assure( tioy_type == CPL_TYPE_DOUBLE, CPL_ERROR_TYPE_MISMATCH,
4083  "Type of TAB_IN_OUT_YSHIFT is %s, double expected",
4084  uves_tostring_cpl_type(tioy_type));
4085 
4086  if (tioy_length != 1)
4087  {
4088  uves_msg_warning("Length of TAB_IN_OUT_YSHIFT array is %d; "
4089  "%d expected", tioy_length, 1);
4090  }
4091 
4092  *tab_in_out_yshift = tioy[0];
4093 
4094  uves_msg_debug("TAB_IN_OUT_YSHIFT = %f", *tab_in_out_yshift);
4095  }
4096 
4097  if (traces != NULL)
4098  {
4099  *traces = uves_ordertable_traces_new();
4100 
4101  if (!flames)
4102  /* UVES: one trace with zero offset */
4103  {
4104  int fibre_ID = 0;
4105  double fibre_offset = 0.0;
4106  int fibre_msk = 1;
4107  uves_ordertable_traces_add(*traces,
4108  fibre_ID,
4109  fibre_offset,
4110  fibre_msk);
4111  }
4112  else
4113  /* FLAMES */
4114  {
4115 
4116  int fibre_pos_length;
4117  int fibre_mask_length;
4118  cpl_type fibre_pos_type;
4119  cpl_type fibre_mask_type;
4120  int fibre_ID;
4121 
4122  check( fibre_pos = uves_read_midas_array(
4123  midas_header, "FIBREPOS", &fibre_pos_length,
4124  &fibre_pos_type, NULL),
4125  "Error reading FIBREPOS from MIDAS header");
4126 
4127  assure( fibre_pos_type == CPL_TYPE_DOUBLE, CPL_ERROR_TYPE_MISMATCH,
4128  "Type of FIBREPOS is %s, double expected",
4129  uves_tostring_cpl_type(fibre_pos_type));
4130 
4131  check( fibre_mask = uves_read_midas_array(
4132  midas_header, "FIBREMASK", &fibre_mask_length,
4133  &fibre_mask_type, NULL),
4134  "Error reading FIBREMASK from MIDAS header");
4135 
4136  assure( fibre_mask_type == CPL_TYPE_INT, CPL_ERROR_TYPE_MISMATCH,
4137  "Type of FIBREMASK is %s, double expected",
4138  uves_tostring_cpl_type(fibre_mask_type));
4139 
4140  assure( fibre_pos_length == fibre_mask_length,
4141  CPL_ERROR_INCOMPATIBLE_INPUT,
4142  "FIBREMASK has length %d, but "
4143  "FIBREPOS has length %d",
4144  fibre_mask_length, fibre_pos_length );
4145 
4146  *fib_pos= cpl_malloc(sizeof(double) * fibre_pos_length);
4147  *fib_msk= cpl_malloc(sizeof(int) * fibre_mask_length);
4148 
4149  for (fibre_ID = 0; fibre_ID < fibre_mask_length; fibre_ID++)
4150  {
4151  uves_msg_debug("Found trace %d, position %f (%s)",
4152  fibre_ID, fibre_pos[fibre_ID],
4153  fibre_mask[fibre_ID] ?
4154  "enabled" : "disabled");
4155  uves_ordertable_traces_add(*traces,
4156  fibre_ID,
4157  fibre_pos[fibre_ID],
4158  fibre_mask[fibre_ID]);
4159  (*fib_pos)[fibre_ID]=fibre_pos[fibre_ID];
4160  (*fib_msk)[fibre_ID]=fibre_mask[fibre_ID];
4161  }
4162  }
4163  }
4164  }
4165 
4166  cleanup:
4167  uves_free_propertylist(&midas_header);
4168  uves_free_double(&fibre_pos);
4169  uves_free_int(&fibre_mask);
4170  uves_free_int(&tioo);
4171  uves_free_double(&tioy);
4172  uves_free_propertylist(&prime_header);
4173 
4174  if (cpl_error_get_code() != CPL_ERROR_NONE)
4175  {
4176  *ordertable_filename = NULL;
4177  uves_free_table (ordertable);
4178  uves_free_propertylist(ordertable_header);
4179  if (order_locations != NULL) uves_polynomial_delete(order_locations);
4180  if (traces != NULL) uves_free_table (traces);
4181  }
4182  return cpl_error_get_code();
4183 }
4184 
4185 
4186 
4187 /*--------------------------------------------------------------------------*/
4196 /*--------------------------------------------------------------------------*/
4197 
4198 
4199 cpl_error_code
4200 uves_check_if_format_is_midas(uves_propertylist* header, bool* format_is_midas)
4201 {
4202 
4203  /* Determine format of order table and read the polynomial */
4204  if (uves_propertylist_contains(header, UVES_DRS_ID)) {
4205 
4206 
4207  const char* drs_id=NULL;
4208 
4209  check( drs_id = uves_pfits_get_drs_id(header), "Error reading DRS ID");
4210  if (strstr(drs_id, "CPL") != NULL ||
4211  strstr(drs_id, "cpl") != NULL) {
4212  *format_is_midas = false;
4213  uves_msg_debug("Order table was written by CPL");
4214  } else if (strstr(drs_id, "MIDAS") != NULL ||
4215  strstr(drs_id, "midas") != NULL) {
4216  *format_is_midas = true;
4217  uves_msg_low("Order table was written by MIDAS");
4218  } else {
4219  assure ( false, CPL_ERROR_ILLEGAL_INPUT,
4220  "Unrecognized order table format, DRS_ID = '%s'", drs_id);
4221  }
4222  } else {
4223 
4224  *format_is_midas = true;
4225  uves_msg_debug("No '%s' keyword found. Assuming MIDAS format", UVES_DRS_ID);
4226  }
4227 
4228  cleanup:
4229  return cpl_error_get_code();
4230 
4231 }
4232 
4233 /*--------------------------------------------------------------------------*/
4243 /*--------------------------------------------------------------------------*/
4244 
4245 static cpl_error_code
4246 create_column_pixelsize(cpl_table *linetable)
4247 {
4248  polynomial *p = NULL;
4249  cpl_table *t = NULL;
4250  double d1, d2;
4251  int i;
4252  int degree = 3;
4253 
4254  /* Remove rows with Ident = 0 (unidentified lines) */
4255  check( t = uves_extract_table_rows(linetable, "Ident", CPL_GREATER_THAN, 0.1),
4256  "Error deleting rows with Ident=0");
4257 
4258  /* Create column Aux := Ident * Order */
4259  check(( cpl_table_duplicate_column(t, "Aux", t, "Ident"),
4260  cpl_table_multiply_columns(t, "Aux", "Order")),
4261  "Error creating 'Aux' column");
4262 
4264  "X", "Aux", NULL,
4265  degree,
4266  NULL, NULL,
4267  NULL,
4268  -1),
4269  "Regression failed");
4270 
4271  check( d1 = uves_polynomial_get_coeff_1d(p, 1),
4272  "Error reading polynomial coefficient");
4273 
4274  check( d2 = uves_polynomial_get_coeff_1d(p, 2),
4275  "Error reading polynomial coefficient");
4276 
4277  cpl_table_new_column(linetable, LINETAB_PIXELSIZE, CPL_TYPE_DOUBLE);
4278 
4279  for (i = 0; i < cpl_table_get_nrow(linetable); i++)
4280  {
4281  int x;
4282  int order;
4283  double pixelsize;
4284  double ident;
4285 
4286  check(( x = cpl_table_get_double(linetable, "X", i, NULL),
4287  order = cpl_table_get_int (linetable, "Order", i, NULL),
4288  ident = cpl_table_get_double(linetable, "Ident", i, NULL)),
4289  "Error reading line table");
4290 
4291  assure( order != 0, CPL_ERROR_ILLEGAL_INPUT, "Illegal order number: %d", order);
4292 
4293  /*
4294  * MIDAS approximates
4295  * d(lambda m)/dx (x,m) = d1 + 2*d2*x
4296  *
4297  * where the polynomial itself is ... + d1*x + d2*x^2 + ...
4298  */
4299  pixelsize = (d1 + 2*d2* x) / order;
4300 // pixelsize = uves_polynomial_derivative_2d(dispersion_relation, x, order, 1)/order;
4301 
4302  if (ident > 0.01)
4303  {
4304  cpl_table_set_double(linetable, LINETAB_PIXELSIZE, i, pixelsize);
4305  }
4306  else
4307  {
4308  cpl_table_set_invalid(linetable, LINETAB_PIXELSIZE, i);
4309  }
4310  }
4311 
4312  cleanup:
4313  uves_free_table(&t);
4315  return cpl_error_get_code();
4316 }
4317 
4318 
4319 
4320 /*----------------------------------------------------------------------------*/
4347 /*----------------------------------------------------------------------------*/
4348 static void
4349 align_order_line_table(cpl_table *linetable, const polynomial *absolute_order,
4350  uves_propertylist **linetable_header,
4351  const polynomial *order_locations, int minorder, int maxorder)
4352 {
4353  polynomial *absord = NULL;
4354 
4355  assure ( order_locations != NULL, CPL_ERROR_NULL_INPUT,
4356  "Null order locations polynomial!");
4357 
4358  assure ( absolute_order != NULL, CPL_ERROR_NULL_INPUT,
4359  "Null absolute order pllynomial!");
4360  assure( cpl_table_has_column(linetable, "X" ), CPL_ERROR_DATA_NOT_FOUND,
4361  "Missing line table column 'X'");
4362  assure( cpl_table_has_column(linetable, "Ynew"), CPL_ERROR_DATA_NOT_FOUND,
4363  "Missing line table column 'Ynew'");
4364  assure( cpl_table_has_column(linetable, "Order"), CPL_ERROR_DATA_NOT_FOUND,
4365  "Missing line table column 'Order'");
4366 
4367  assure( cpl_table_get_column_type(linetable, "X") == CPL_TYPE_DOUBLE,
4368  CPL_ERROR_TYPE_MISMATCH, "Line table column 'X' has type %s (double expected))",
4369  uves_tostring_cpl_type(cpl_table_get_column_type(linetable, "X")) );
4370 
4371  assure( cpl_table_get_column_type(linetable, "Ynew") == CPL_TYPE_DOUBLE,
4372  CPL_ERROR_TYPE_MISMATCH, "Line table column 'Ynew' has type %s (double expected))",
4373  uves_tostring_cpl_type(cpl_table_get_column_type(linetable, "Ynew")) );
4374 
4375  assure( cpl_table_get_column_type(linetable, "Y") == CPL_TYPE_INT,
4376  CPL_ERROR_TYPE_MISMATCH, "Line table column 'Y' has type %s (integer expected))",
4377  uves_tostring_cpl_type(cpl_table_get_column_type(linetable, "Y")) );
4378 
4379 
4380  if (linetable_header != NULL)
4381  /* then correct first/abs order keywords */
4382  {
4383  int line_first, line_last;
4384  int ord_first, ord_last;
4385  {
4386 
4387  int maxx;
4388  int minx;
4389  int x, y, order, absorder; /* At chip center */
4390  int coeff;
4391 
4392 
4393  maxx = uves_round_double(cpl_table_get_column_max(linetable, "X"));
4394 
4395  minx = uves_round_double(cpl_table_get_column_min(linetable, "X"));
4396 
4397  assure( 1 <= minx && minx <= maxx, CPL_ERROR_ILLEGAL_INPUT,
4398  "Illegal min/max line x positions: %d/%d, must be > 1",
4399  minx, maxx);
4400 
4401  /* Center of chip */
4402  x = (minx + maxx) / 2;
4403  order = (minorder + maxorder) / 2;
4404 
4405  y = uves_polynomial_evaluate_2d(order_locations, x, order);
4406  if (uves_polynomial_derivative_2d(absolute_order, x, y, 2) > 0) {
4407  coeff = +1;
4408  }
4409  else {
4410  coeff = -1;
4411  }
4412 
4413  assure ( order_locations != NULL, CPL_ERROR_NULL_INPUT,
4414  "Null order locations polynomial!");
4415 
4416 
4417  absorder = uves_round_double(uves_polynomial_evaluate_2d(absolute_order, x, y));
4418 
4419 
4420  uves_msg_debug("Absolute order polynomial at (%d, %d) = %f, "
4421  "rounding to %d", x, y,
4422  uves_polynomial_evaluate_2d(absolute_order, x, y), absorder);
4423 
4424  ord_first = absorder + (minorder - order) * coeff;
4425  ord_last = absorder + (maxorder - order) * coeff;
4426  }
4427 
4428  check( line_first =
4429  uves_pfits_get_firstabsorder(*linetable_header),
4430  "Could not read order number from line table header");
4431 
4432  check( line_last =
4433  uves_pfits_get_lastabsorder (*linetable_header),
4434  "Could not read order number from line table header");
4435 
4436  uves_msg_debug("Order table range: %d - %d. Line table range: %d - %d",
4437  ord_first, ord_last, line_first, line_last);
4438 
4439  if (line_first != ord_first ||
4440  line_last != ord_last)
4441  {
4442  uves_msg_warning("Provided line and order tables are incompatible. "
4443  "Line table contains orders %d - %d. "
4444  "Order table contains orders %d - %d. "
4445  "Correcting on the fly",
4446  line_first, line_last, ord_first, ord_last);
4447 
4448  check( uves_pfits_set_firstabsorder(*linetable_header,
4449  ord_first),
4450  "Could not write corrected first absolute order number");
4451  check( uves_pfits_set_lastabsorder(*linetable_header,
4452  ord_last),
4453  "Could not write corrected first absolute order number");
4454 
4455  uves_msg_debug("Setting line table order range = %d - %d",
4456  ord_first, ord_last);
4457  }
4458  }
4459  /* This 'Y' column is the relative order number in linetables
4460  but the absolute order number (and therefore equal to
4461  the 'order' column) in line guess tables (!!)
4462  */
4463 
4464  {
4465  double epsilon = 0.01; /* Must be larger than machine precision but
4466  less than the typical difference between
4467  absolute/relative numbering (~100)
4468  */
4469 
4470  if (fabs(cpl_table_get_column_median(linetable, "Y") -
4471  cpl_table_get_column_median(linetable, "Order")) > epsilon)
4472 
4473  /* If column 'Y' is different from 'Order',
4474  then 'Y' is the relative order number and
4475  should be corrected (if there is an inconsistency).
4476 
4477  For now, simply delete the 'Y' column because it is
4478  not used later. If the 'Y' column will be used later,
4479  it must be corrected at this place.
4480  */
4481  {
4482  uves_msg_debug("Removing line table column 'Y'");
4483  cpl_table_erase_column(linetable, "Y");
4484  }
4485  }
4486 
4487  cleanup:
4488  uves_polynomial_delete(&absord);
4489 }
4490 
4491 
4492 /*----------------------------------------------------------------------------*/
4531 /*----------------------------------------------------------------------------*/
4532 void
4533 uves_load_linetable(const cpl_frameset *frames,
4534  bool flames,
4535  const char *chip_name,
4536  const polynomial *order_locations, int minorder, int maxorder,
4537  const char **linetable_filename,
4538  cpl_table **linetable,
4539  uves_propertylist **linetable_header,
4540  polynomial **dispersion_relation,
4541  polynomial **absolute_order,
4542  enum uves_chip chip, int trace_id, int window)
4543 {
4544  uves_propertylist *primary_header = NULL;
4545  uves_propertylist *header = NULL;
4546  uves_propertylist *midas_header = NULL; /* MIDAS extension header */
4547  int *absorders = NULL; /* Absolute order numbers */
4548  cpl_table *temp = NULL;
4549  polynomial *absolute_order_local = NULL;
4550  const char *tags[3];
4551  int number_of_tags = sizeof(tags) / sizeof(char *);
4552  const char *drs_id;
4553  bool format_is_midas; /* Was file written by CPL or MIDAS? */
4554  int base_extension; /* Last extension (e.g. 0) before
4555  extension with line table */
4556  int indx;
4557 
4558  if (flames)
4559  {
4560  tags[0] = UVES_GUESS_LINE_TABLE(flames, chip);
4561  tags[1] = UVES_LINE_TABLE(flames, chip);
4562  tags[2] = UVES_LINE_TABLE(flames, chip);
4563  number_of_tags = 3;
4564 
4565  check( *linetable_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
4566  "No line table (%s, %s or %s) found in SOF", tags[0], tags[1], tags[2]);
4567  }
4568  else
4569  {
4570  tags[0] = UVES_LINE_TABLE(flames, chip);
4571  tags[1] = UVES_LINE_TABLE(flames, chip);
4572  tags[2] = UVES_GUESS_LINE_TABLE(flames, chip);
4573 
4574  /* For backwards compatibility with MIDAS,
4575  also look for LINE_TABLE_chip%d */
4576  if (cpl_frameset_find_const(frames, tags[0]) == NULL &&
4577  cpl_frameset_find_const(frames, tags[1]) == NULL &&
4578  cpl_frameset_find_const(frames, tags[2]) == NULL)
4579  {
4580  uves_msg_debug("No %s", tags[0]);
4581 
4582  if (window >= 1)
4583  {
4584  /* Look for LINE_TABLE_BLUEwindow */
4585 
4586  tags[0] = UVES_LINE_TABLE_MIDAS(chip, window);
4587  tags[1] = UVES_LINE_TABLE_MIDAS(chip, window);
4588  tags[2] = UVES_LINE_TABLE_MIDAS(chip, window);
4589 
4590  uves_msg_debug("Trying %s", tags[0]);
4591  }
4592  if (window <= 0)
4593  {
4594  /* Look for any LINE_TABLE_BLUEi */
4595  tags[0] = UVES_LINE_TABLE_MIDAS(chip, 1);
4596  tags[1] = UVES_LINE_TABLE_MIDAS(chip, 2);
4597  tags[2] = UVES_LINE_TABLE_MIDAS(chip, 3);
4598 
4599  uves_msg_debug("Trying %s, %s or %s", tags[0], tags[1], tags[2]);
4600  }
4601  }
4602 
4603  check( *linetable_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
4604  "No line table (%s, %s or %s) found in SOF", tags[0], tags[1], tags[2]);
4605  }
4606 
4607  /* Read primary header */
4608  check( primary_header = uves_propertylist_load(*linetable_filename, 0),
4609  "Could not load primary header of '%s'", *linetable_filename);
4610 
4611  check_nomsg( uves_warn_if_chip_names_dont_match(primary_header, chip_name, chip) );
4612 
4613  /* Determine format of line table */
4614  if (uves_propertylist_contains(primary_header, UVES_DRS_ID))
4615  {
4616  check( drs_id = uves_pfits_get_drs_id(primary_header), "Error reading DRS ID");
4617  if (strstr(drs_id, "CPL") != NULL || strstr(drs_id, "cpl") != NULL)
4618  {
4619  format_is_midas = false;
4620  uves_msg_debug("Line table was written by CPL");
4621  }
4622  else if (strstr(drs_id, "MIDAS") != NULL || strstr(drs_id, "midas") != NULL)
4623  {
4624  format_is_midas = true;
4625  uves_msg_debug("Line table was written by MIDAS");
4626  }
4627  else
4628  {
4629  assure ( false,
4630  CPL_ERROR_ILLEGAL_INPUT,
4631  "Unrecognized line table format, DRS_ID = '%s'", drs_id);
4632  }
4633  }
4634  else
4635  {
4636  format_is_midas = true;
4637  uves_msg_debug("No '%s' keyword found. Assuming MIDAS format", UVES_DRS_ID);
4638  }
4639 
4640  if (format_is_midas || flames)
4641  {
4642  if (!flames)
4643  {
4644  assure( trace_id == 0 && (window == -1 || (1 <= window && window <= 3)),
4645  CPL_ERROR_UNSUPPORTED_MODE,
4646  "Cannot read (fibre, window) = (%d, %d) from MIDAS line table",
4647  trace_id, window);
4648 
4649  base_extension = 0;
4650  }
4651  else
4652  {
4653 
4654  if(trace_id > 0) {
4655 
4656  assure( ((1<= trace_id && trace_id <= 9) && (window == -1)),
4657  CPL_ERROR_UNSUPPORTED_MODE,
4658  "Cannot read (fibre, window) = (%d, %d) from MIDAS line table",
4659  trace_id, window);
4660 
4661  base_extension = 0;
4662 
4663 
4664  } else {
4665 
4666  uves_msg_warning("Assuming line table is guess table");
4667  base_extension = 0;
4668  }
4669  }
4670  }
4671  else
4672  /* Find table extension containing the line table for the specified trace and window */
4673  {
4674  int nextensions;
4675  bool found;
4676 
4677  check( nextensions = uves_get_nextensions(*linetable_filename),
4678  "Error reading number of extensions of file '%s'", *linetable_filename);
4679  header = NULL;
4680  found = false;
4681 
4682  uves_msg_debug("Number of extensions = %d", nextensions);
4683 
4684  for (base_extension = 1; base_extension < nextensions && !found; base_extension++)
4685  {
4686  int header_trace;
4687  int header_window;
4688 
4689  /* Read header trace & window info */
4690  check(( uves_free_propertylist(&header),
4691  header = uves_propertylist_load(*linetable_filename, base_extension)),
4692  "Could not header of extension %d of '%s'",
4693  base_extension, *linetable_filename);
4694 
4695  check( header_trace = uves_pfits_get_traceid (header),
4696  "Error reading trace ID from header of extension %d of '%s'",
4697  base_extension, *linetable_filename);
4698 
4699  check( header_window = uves_pfits_get_windownumber(header),
4700  "Error reading window number from header of extension %d of '%s'",
4701  base_extension, *linetable_filename);
4702 
4703  uves_msg_debug("Found (trace, window) = (%d, %d), need (%d, %d)",
4704  header_trace, header_window,
4705  trace_id, window);
4706 
4707  found = ( (trace_id == header_trace) &&
4708  (window == -1 || window == header_window) );
4709  }
4710 
4711  assure( found,
4712  CPL_ERROR_ILLEGAL_INPUT,
4713  "Line table (trace, window) = (%d, %d) is not present in file '%s'",
4714  trace_id, window, *linetable_filename);
4715 
4716  /* Let 'base_extension' be the first extension before
4717  the proper extension was found (0, 3, 6, ...) */
4718  base_extension -= 2;
4719  /* ...and incremented in for-loop */
4720  }
4721 
4722  check( *linetable = cpl_table_load(*linetable_filename,
4723  base_extension + UVES_LINE_TABLE_EXTENSION,
4724  1), /* Mark identified
4725  invalid values? (1=yes) */
4726  "Error loading line table from extension %d of file '%s'",
4727  base_extension + UVES_LINE_TABLE_EXTENSION, *linetable_filename);
4728 
4729  /* Read header of table extension if requested */
4730  if (linetable_header != NULL)
4731  {
4732  check( *linetable_header =
4733  uves_propertylist_load(*linetable_filename,
4734  base_extension + UVES_LINE_TABLE_EXTENSION),
4735  "Could not load header of extension %d of '%s'",
4736  base_extension + UVES_LINE_TABLE_EXTENSION, *linetable_filename);
4737 
4738  if (format_is_midas)
4739  {
4740  int size = 0;
4741  cpl_type type;
4742  absorders = uves_read_midas_array(*linetable_header, "ORDER", &size,
4743  &type, NULL);
4744 
4745  assure( type == CPL_TYPE_INT, CPL_ERROR_TYPE_MISMATCH,
4746  "Type of ORDER is %s, int expected",
4747  uves_tostring_cpl_type(type));
4748 
4749  assure( size == 2,
4750  CPL_ERROR_ILLEGAL_INPUT,
4751  "'ORDER' array has size %d. Size 2 expected.", size);
4752  check(( uves_pfits_set_firstabsorder(*linetable_header, absorders[0]),
4753  uves_pfits_set_lastabsorder(*linetable_header, absorders[1])),
4754  "Error updating table header");
4755  }
4756  }
4757 
4758  /* Read the polynomials if requested */
4759  if (format_is_midas)
4760  {
4761  /* Rename & cast order/ident/X columns */
4762  check(( cpl_table_cast_column(*linetable, "X", "xxxx", CPL_TYPE_DOUBLE),
4763  cpl_table_erase_column(*linetable, "X"),
4764  cpl_table_name_column(*linetable, "xxxx", "X")),
4765  "Error casting and renaming column 'X'");
4766 
4767  check(( cpl_table_cast_column(*linetable, "YNEW", "xxxx", CPL_TYPE_DOUBLE),
4768  cpl_table_erase_column(*linetable, "YNEW"),
4769  cpl_table_name_column(*linetable, "xxxx", "Ynew")),
4770  "Error casting and renaming column 'YNEW'");
4771 
4772  check(( cpl_table_cast_column(*linetable, "Y", "xxxx", CPL_TYPE_INT),
4773  cpl_table_erase_column(*linetable, "Y"),
4774  cpl_table_name_column(*linetable, "xxxx", "Y")),
4775  "Error casting and renaming column 'Y'");
4776 
4777  check(( cpl_table_cast_column(*linetable, "ORDER", "Order", CPL_TYPE_INT),
4778  cpl_table_erase_column(*linetable, "ORDER")),
4779  "Error casting and renaming column 'ORDER'");
4780 
4781  check( cpl_table_name_column(*linetable, "IDENT", "Ident"),
4782  "Error renaming column 'IDENT'");
4783 
4784  check( midas_header = uves_propertylist_load(
4785  *linetable_filename,
4786  base_extension + UVES_LINE_TABLE_EXTENSION),
4787  "Could not load header of extension %d of '%s'",
4788  base_extension + UVES_LINE_TABLE_EXTENSION, *linetable_filename);
4789 
4790  if (dispersion_relation != NULL) {
4791  if (trace_id > 0) {
4792  check( *dispersion_relation =
4793  uves_polynomial_convert_from_plist_midas(midas_header,
4794  "REGR", trace_id),
4795  "Error reading polynomial 'REGR%d' from '%s'",
4796  trace_id,
4797  *linetable_filename);
4798  }
4799  else {
4800  check( *dispersion_relation =
4801  uves_polynomial_convert_from_plist_midas(midas_header,
4802  "REGR", -1),
4803  "Error reading polynomial 'REGR' from '%s'",
4804  *linetable_filename);
4805  }
4806  }
4807 
4808 
4809  check( absolute_order_local =
4810  uves_polynomial_convert_from_plist_midas(midas_header, "RORD",-1),
4811  "Error reading polynomial 'RORD' from '%s'", *linetable_filename);
4812 
4813  /* For FLAMES data, it seems that the polynomial is half an order shifted
4814  (for unknown reasons) */
4815  if (flames)
4816  {
4817  check_nomsg( uves_polynomial_shift(absolute_order_local, 0, 0.5) );
4818  }
4819  }
4820  else
4821  /* CPL format */
4822  {
4823  /* physmod + wavecal recipes use different naming conventions,
4824  workaround for this:
4825  */
4826  if (cpl_table_has_column(*linetable, "YNEW"))
4827  {
4828  cpl_table_name_column(*linetable, "YNEW", "Ynew");
4829  }
4830 
4831  if (dispersion_relation != NULL)
4832  {
4833  check( *dispersion_relation = load_polynomial(
4834  *linetable_filename,
4835  base_extension + UVES_LINE_TABLE_EXTENSION_DISPERSION),
4836  "Could not read polynomial from extension %d of file '%s'",
4837  base_extension + UVES_LINE_TABLE_EXTENSION_DISPERSION,
4838  *linetable_filename);
4839  }
4840 
4841  check( absolute_order_local =
4842  load_polynomial(*linetable_filename,
4843  base_extension + UVES_LINE_TABLE_EXTENSION_ABSORDER),
4844  "Could not read polynomial from extension %d of file '%s'",
4845  base_extension + UVES_LINE_TABLE_EXTENSION_ABSORDER, *linetable_filename);
4846  }
4847 
4848  if (absolute_order != NULL)
4849  {
4850  *absolute_order = uves_polynomial_duplicate(absolute_order_local);
4851  }
4852 
4853 
4854  check( align_order_line_table(
4855  *linetable, absolute_order_local, linetable_header,
4856  order_locations, minorder, maxorder),
4857  "Error while aligning line/order tables");
4858 
4859 
4860  /* Remove all other columns than 'Ident', 'Order', 'X', 'Pixelsize' */
4861  {
4862  const char *colname;
4863 
4864  /* Loop through all columns */
4865 
4866  /* It is undefined behaviour (for a reason!) to loop through
4867  columns while deleting some of them. Therefore, copy the
4868  structure of the linetable to another (empty) table */
4869 
4870  uves_free_table(&temp);
4871  check(( temp = cpl_table_new(0),
4872  cpl_table_copy_structure(temp, *linetable)),
4873  "Error duplicating line table column structure");
4874 
4875  colname = cpl_table_get_column_name(temp);
4876  while (colname != NULL)
4877  {
4878  if (!(strcmp(colname, "X" ) == 0 ||
4879  strcmp(colname, "Order" ) == 0 ||
4880  strcmp(colname, "Ident" ) == 0 ||
4881  strcmp(colname, "FIBRE" ) == 0 ||
4882  strcmp(colname, "Fibre" ) == 0 ||
4883  strcmp(colname, LINETAB_PIXELSIZE) == 0))
4884  {
4885  cpl_table_erase_column(*linetable, colname);
4886  uves_msg_debug("Removing unused column '%s'", colname);
4887  }
4888 
4889  /* Call with NULL argument to get the next column name */
4890  colname = cpl_table_get_column_name(NULL);
4891  }
4892  }
4893 
4894  /* support MIDAS
4895  * Calculate 'Pixel' column (lower case) for MIDAS tables
4896  */
4897  if ( !cpl_table_has_column(*linetable, LINETAB_PIXELSIZE) )
4898  {
4899  check( create_column_pixelsize(*linetable),
4900  "Error adding 'Pixelsize' column");
4901  }
4902 
4903  /* Remove un-identified lines (where Ident = invalid or Ident = zero) ... */
4904  check( uves_erase_invalid_table_rows(*linetable, "Ident"),
4905  "Error deleting rows with illegal 'Ident' value");
4906 
4907  check( uves_erase_table_rows(*linetable, "Ident", CPL_LESS_THAN, 0.01),
4908  "Error deleting rows with illegal 'Ident' value");
4909 
4910  /* Check for any other invalid value */
4911  assure( uves_erase_invalid_table_rows(*linetable, NULL) == 0, CPL_ERROR_ILLEGAL_INPUT,
4912  "After deleting rows with invalid 'Ident' values, "
4913  "the table in extension %d of file '%s' still contains invalid rows",
4914  base_extension + UVES_LINE_TABLE_EXTENSION, *linetable_filename);
4915 
4916  /* Sort line table by 'Order' (ascending), then 'X' (ascending) */
4917  check( uves_sort_table_2(*linetable, "Order", "X", false, false), "Error sorting line table");
4918 
4919  cleanup:
4920  uves_free_propertylist(&primary_header);
4921  uves_free_propertylist(&header);
4922  uves_free_propertylist(&midas_header);
4923  uves_free_table(&temp);
4924  uves_polynomial_delete(&absolute_order_local);
4925  cpl_free(absorders);
4926  if (cpl_error_get_code() != CPL_ERROR_NONE) {
4927  *linetable_filename = NULL;
4928  uves_free_table(linetable);
4929  if (dispersion_relation != NULL) uves_polynomial_delete(dispersion_relation);
4930  if (absolute_order != NULL) uves_polynomial_delete(absolute_order);
4931  }
4932  return;
4933 }
4934 
4935 /*----------------------------------------------------------------------------*/
4939 /*----------------------------------------------------------------------------*/
4940 void
4941 uves_load_linetable_const(const cpl_frameset *frames,
4942  bool flames,
4943  const char *chip_name,
4944  const polynomial *order_locations, int minorder, int maxorder,
4945  const char **linetable_filename,
4946  const cpl_table **linetable,
4947  const uves_propertylist **linetable_header,
4948  const polynomial **dispersion_relation,
4949  polynomial **absolute_order,
4950  enum uves_chip chip, int trace_id, int window)
4951 {
4952  uves_load_linetable(frames, flames, chip_name, order_locations,
4953  minorder, maxorder,
4954  linetable_filename,
4955  (cpl_table **)linetable,
4956  (uves_propertylist **)linetable_header,
4957  (polynomial **)dispersion_relation,
4958  absolute_order,
4959  chip, trace_id, window);
4960 }
4961 
4962 
4963 
4964 /*----------------------------------------------------------------------------*/
4979 /*----------------------------------------------------------------------------*/
4980 
4981 cpl_error_code
4982 uves_load_response_curve(const cpl_frameset *frames, const char *chip_name,
4983  const char **response_filename,
4984  cpl_image **response_curve,
4985  cpl_table **master_response,
4986  uves_propertylist **response_header, enum uves_chip chip)
4987 {
4988  const char *tags[2];
4989  int number_of_tags = sizeof(tags) / sizeof(char *);
4990  int extension;
4991  int indx;
4992 
4993  *response_curve = NULL;
4994  *response_header = NULL;
4995  *master_response = NULL;
4996 
4997  tags[0] = UVES_INSTR_RESPONSE (chip);
4998  tags[1] = UVES_MASTER_RESPONSE(chip);
4999 
5000  check( *response_filename = uves_find_frame(frames, tags, number_of_tags, &indx,
5001  NULL),
5002  "Could not find '%s' in frame set", tags[0]);
5003 
5004 
5005  if (indx == 0)
5006  {
5007  extension = UVES_INSTR_RESPONSE_EXTENSION(chip);
5008 
5009  /* Load the response image
5010 
5011  Note: Even if the response curve was saved as
5012  a FITS file with NAXIS=1, cpl_image_load() will
5013  create an image of size nx1, which is just
5014  what we want
5015  */
5016  check( *response_curve = uves_load_image_file(*response_filename,
5017  /* CPL_TYPE_DOUBLE, Convert to this type */
5018  0, /* plane number */
5019  extension, /* Extension number */
5020 
5021 response_header
5022  ),
5023  "Could not load response curve from extension %d of file '%s'",
5024  extension, *response_filename);
5025 
5026  /* Load the header */
5027 /*
5028  check( *response_header = uves_propertylist_load(*response_filename,
5029  extension),
5030  "Could not load header from extension %d of file '%s'",
5031  extension, *response_filename);
5032 */
5033  check_nomsg( uves_warn_if_chip_names_dont_match(*response_header, chip_name, chip) );
5034  }
5035  else
5036  /* Master response */
5037  {
5038  extension = UVES_MASTER_RESPONSE_EXTENSION(chip);
5039 
5040  check( *master_response = cpl_table_load(*response_filename,
5041  UVES_LINE_INTMON_TABLE_EXTENSION,
5042  1), /* Mark identified
5043  invalid values? (1=yes) */
5044  "Error master response curve from extension %d of file '%s'",
5045  extension, *response_filename);
5046 
5047  /* Convert columns to double */
5048  check(( cpl_table_cast_column(*master_response, "LAMBDA", "LAMBDA_double",
5049  CPL_TYPE_DOUBLE),
5050  cpl_table_erase_column(*master_response, "LAMBDA"),
5051  cpl_table_name_column(*master_response, "LAMBDA_double", "LAMBDA")),
5052  "Could not cast column 'LAMBDA'");
5053 
5054  check(( cpl_table_cast_column(*master_response, "FLUX_CONV", "FLUX_CONV_double",
5055  CPL_TYPE_DOUBLE),
5056  cpl_table_erase_column(*master_response, "FLUX_CONV"),
5057  cpl_table_name_column(*master_response, "FLUX_CONV_double", "FLUX_CONV")),
5058  "Could not cast column 'FLUX_CONV'");
5059 
5060  /* Do not need the header, which also does not contain
5061  keywords needed for uves_warn_if_chip_names_dont_match() */
5062  }
5063 
5064  cleanup:
5065  if (cpl_error_get_code() != CPL_ERROR_NONE)
5066  {
5067  *response_filename = NULL;
5068  uves_free_image(response_curve);
5069  uves_free_propertylist(response_header);
5070  }
5071  return cpl_error_get_code();
5072 }
5073 
5074 
5075 /*----------------------------------------------------------------------------*/
5085 /*----------------------------------------------------------------------------*/
5086 cpl_error_code uves_load_lineintmon(const cpl_frameset *frames,
5087  const char **line_intmon_filename,
5088  cpl_table **line_intmon)
5089 {
5090  const char *tags[1] = {UVES_LINE_INTMON_TABLE};
5091 
5092  int number_of_tags = sizeof(tags) / sizeof(char *);
5093  int indx;
5094 
5095  /* Get filename */
5096  check( *line_intmon_filename = uves_find_frame(frames, tags, number_of_tags,
5097  &indx, NULL),
5098  "No line intensity table (%s) found in SOF", tags[0]);
5099 
5100  /* Load table */
5101  check( *line_intmon = cpl_table_load(*line_intmon_filename,
5102  UVES_LINE_INTMON_TABLE_EXTENSION,
5103  1), /* Mark identified
5104  invalid values? (1=yes) */
5105  "Error loading line reference table from extension %d of file '%s'",
5106  UVES_LINE_INTMON_TABLE_EXTENSION, *line_intmon_filename);
5107 
5108  check(( cpl_table_cast_column(*line_intmon, "WAVE", "Wave", CPL_TYPE_DOUBLE),
5109  cpl_table_erase_column(*line_intmon, "WAVE")),
5110  "Could not cast and rename column");
5111 
5112  /* Sort table by 'Wave' (ascending) */
5113  check( uves_sort_table_1(*line_intmon, "Wave", false), "Error sorting table");
5114 
5115  cleanup:
5116  if (cpl_error_get_code() != CPL_ERROR_NONE)
5117  {
5118  *line_intmon_filename = NULL;
5119  uves_free_table(line_intmon);
5120  }
5121  return cpl_error_get_code();
5122 }
5123 
5124 
5125 /*----------------------------------------------------------------------------*/
5137 /*----------------------------------------------------------------------------*/
5138 void
5139 uves_load_corvel(const cpl_frameset *frames,
5140  cpl_table **corvel,
5141  uves_propertylist **corvel_header,
5142  const char **corvel_filename)
5143 {
5144  const char *tags[1];
5145  int number_of_tags = sizeof(tags) / sizeof(char *);
5146  int indx;
5147  int extension;
5148 
5149  tags[0] = FLAMES_CORVEL_MASK;
5150 
5151  assure_nomsg( corvel != NULL, CPL_ERROR_NULL_INPUT );
5152  assure_nomsg( corvel_filename != NULL, CPL_ERROR_NULL_INPUT );
5153 
5154  /* Get filename */
5155  check( *corvel_filename = uves_find_frame(frames, tags, number_of_tags,
5156  &indx, NULL),
5157  "No velocity correction table (%s) found in SOF", tags[0]);
5158 
5159  /* Load table */
5160  extension = 1;
5161  check( *corvel = cpl_table_load(*corvel_filename,
5162  extension,
5163  1), /* Mark identified
5164  invalid values? (1=yes) */
5165  "Error loading line reference table from extension %d of file '%s'",
5166  extension, *corvel_filename);
5167 
5168  /* Load header */
5169  if (corvel_header != NULL)
5170  {
5171  extension = 0;
5172  check( *corvel_header = uves_propertylist_load(*corvel_filename,
5173  extension),
5174  "Could not load header from extension %d of file %s",
5175  extension, *corvel_filename);
5176 
5177  }
5178 
5179  cleanup:
5180  if (cpl_error_get_code() != CPL_ERROR_NONE)
5181  {
5182  *corvel_filename = NULL;
5183  uves_free_table(corvel);
5184  }
5185  return;
5186 }
5187 
5188 /*----------------------------------------------------------------------------*/
5204 /*----------------------------------------------------------------------------*/
5205 cpl_error_code
5206 uves_load_linerefertable(const cpl_frameset *frames,
5207  const char **line_refer_filename,
5208  cpl_table **line_refer, uves_propertylist **line_refer_header)
5209 {
5210  const char *tags[1] = {UVES_LINE_REFER_TABLE};
5211 
5212  int number_of_tags = sizeof(tags) / sizeof(char *);
5213  int indx;
5214 
5215  /* Get filename */
5216  check( *line_refer_filename = uves_find_frame(frames, tags, number_of_tags,
5217  &indx, NULL),
5218  "No line reference table (%s) found in SOF", tags[0]);
5219 
5220  /* Load table */
5221  check( *line_refer = cpl_table_load(*line_refer_filename,
5222  UVES_LINE_REFER_TABLE_EXTENSION,
5223  1), /* Mark identified
5224  invalid values? (1=yes) */
5225  "Error loading line reference table from extension %d of file '%s'",
5226  UVES_LINE_REFER_TABLE_EXTENSION, *line_refer_filename);
5227 
5228  /* Load header if requested */
5229  if (line_refer_header != NULL)
5230  {
5231  check( *line_refer_header = uves_propertylist_load(*line_refer_filename, 0),
5232  "Could not load header of line_refer table in '%s'", *line_refer_filename);
5233  }
5234 
5235  assure( uves_erase_invalid_table_rows(*line_refer, NULL) == 0, CPL_ERROR_ILLEGAL_INPUT,
5236  "Table in extension %d of file '%s' contains invalid rows",
5237  UVES_LINE_REFER_TABLE_EXTENSION, *line_refer_filename);
5238 
5239  check(( cpl_table_cast_column(*line_refer, "WAVE", "Wave", CPL_TYPE_DOUBLE),
5240  cpl_table_erase_column(*line_refer, "WAVE")),
5241  "Could not cast and rename column");
5242 
5243  /* Write uncertainties of wavelengths.
5244  The value 0.002 is finetuned/retro-fitted to get a chi_sq ~ 1 when
5245  using the new catalogue from
5246 
5247  M. T. Murphy, P. Tzanavaris, J. K. Webb, C. Lovis
5248  "Selection of ThAr lines for wavelength calibration of echelle
5249  spectra and implications for variations in the fine-structure constant",
5250  Submitted to MNRAS
5251  */
5252 
5253 #if 0
5254  check(( cpl_table_duplicate_column(*line_refer, "dWave", *line_refer, "Wave"),
5255  cpl_table_divide_scalar (*line_refer, "dWave", 300000*10)),
5256  "Error writing wavelength uncertainties");
5257 #else
5258  /* we should do this */
5259  check(( cpl_table_new_column(*line_refer, "dWave", CPL_TYPE_DOUBLE),
5260  cpl_table_fill_column_window(*line_refer,
5261  "dWave",
5262  0,
5263  cpl_table_get_nrow(*line_refer), 0.002)),
5264  "Error writing wavelength uncertainties");
5265 #endif
5266 
5267  /* Sort table by 'Wave' (ascending) */
5268  check( uves_sort_table_1(*line_refer, "Wave", false), "Error sorting table");
5269 
5270  cleanup:
5271  if (cpl_error_get_code() != CPL_ERROR_NONE) {
5272  *line_refer_filename = NULL;
5273  uves_free_table (line_refer);
5274  if (line_refer_header != NULL) uves_free_propertylist(line_refer_header);
5275  }
5276  return cpl_error_get_code();
5277 }
5278 
5279 /*----------------------------------------------------------------------------*/
5293 /*----------------------------------------------------------------------------*/
5294 cpl_error_code
5295 uves_load_flux_table(const cpl_frameset *frames, const char **flux_table_filename,
5296  cpl_table **flux_table)
5297 {
5298  const char *tags[1] = {UVES_FLUX_STD_TABLE};
5299 
5300  int number_of_tags = sizeof(tags) / sizeof(char *);
5301  int indx;
5302 
5303  /* Get filename */
5304  check( *flux_table_filename = uves_find_frame(frames, tags, number_of_tags,
5305  &indx, NULL),
5306  "No standard star flux table (%s) in SOF", tags[0]);
5307 
5308  /* Load table */
5309  check( *flux_table = cpl_table_load(*flux_table_filename,
5310  UVES_FLUX_STD_TABLE_EXTENSION,
5311  1), /* Mark identified
5312  invalid values? (1=yes) */
5313  "Error loading flux table from extension %d of file '%s'",
5314  UVES_FLUX_STD_TABLE_EXTENSION, *flux_table_filename);
5315 
5316  if (false)
5317  /* Don't do this, it will remove one std (LTT2415) from the table which has TYPE = NULL.
5318  Instead, set type to "NULL" (this is only used for messages)
5319  */
5320  {
5321  if (uves_erase_invalid_table_rows(*flux_table, NULL) != 0)
5322  {
5323  uves_msg_warning("Table in extension %d of file '%s' contains null values",
5324  UVES_FLUX_STD_TABLE_EXTENSION, *flux_table_filename);
5325  }
5326  }
5327  else
5328  {
5329  int i;
5330  for (i = 0; i < cpl_table_get_nrow(*flux_table); i++)
5331  {
5332  if (cpl_table_get_string(*flux_table, "TYPE", i) == NULL)
5333  {
5334  cpl_table_set_string(*flux_table, "TYPE", i, "NULL");
5335  }
5336  }
5337  }
5338 
5339 
5340  cleanup:
5341  if (cpl_error_get_code() != CPL_ERROR_NONE)
5342  {
5343  *flux_table_filename = NULL;
5344  uves_free_table(flux_table);
5345  }
5346  return cpl_error_get_code();
5347 }
5348 
5349 
5350 /*----------------------------------------------------------------------------*/
5364 /*----------------------------------------------------------------------------*/
5365 cpl_error_code
5366 uves_load_atmo_ext(const cpl_frameset *frames, const char **atmext_table_filename,
5367  cpl_table **atmext_table)
5368 {
5369  const char *tags[1] = {UVES_EXTCOEFF_TABLE};
5370 
5371  int number_of_tags = sizeof(tags) / sizeof(char *);
5372  int indx;
5373 
5374  /* Get filename */
5375  check( *atmext_table_filename = uves_find_frame(frames, tags, number_of_tags,
5376  &indx, NULL),
5377  "No atmospheric extinction table (%s) found in SOF", tags[0]);
5378 
5379  /* Load table */
5380  check( *atmext_table = cpl_table_load(*atmext_table_filename,
5381  UVES_EXTCOEFF_TABLE_EXTENSION,
5382  1), /* Mark identified
5383  invalid values? (1=yes) */
5384  "Error loading atmospheric extinction table from extension %d of file '%s'",
5385  UVES_EXTCOEFF_TABLE_EXTENSION, *atmext_table_filename);
5386 
5387  assure( uves_erase_invalid_table_rows(*atmext_table, NULL) == 0, CPL_ERROR_ILLEGAL_INPUT,
5388  "Table in extension %d of file '%s' contains invalid rows",
5389  UVES_EXTCOEFF_TABLE_EXTENSION, *atmext_table_filename);
5390 
5391  check( uves_sort_table_1(*atmext_table, "LAMBDA", false),
5392  "Error sorting table");
5393 
5394  /* Convert columns to double */
5395  check(( cpl_table_cast_column(*atmext_table, "LAMBDA", "LAMBDA_double", CPL_TYPE_DOUBLE),
5396  cpl_table_erase_column(*atmext_table, "LAMBDA"),
5397  cpl_table_name_column(*atmext_table, "LAMBDA_double", "LAMBDA")),
5398  "Could not cast column 'LAMBDA'");
5399 
5400  check(( cpl_table_cast_column(*atmext_table, "LA_SILLA", "LA_SILLA_double", CPL_TYPE_DOUBLE),
5401  cpl_table_erase_column(*atmext_table, "LA_SILLA"),
5402  cpl_table_name_column(*atmext_table, "LA_SILLA_double", "LA_SILLA")),
5403  "Could not cast column 'LA_SILLA'");
5404 
5405  cleanup:
5406  if (cpl_error_get_code() != CPL_ERROR_NONE)
5407  {
5408  *atmext_table_filename = NULL;
5409  uves_free_table(atmext_table);
5410  }
5411  return cpl_error_get_code();
5412 }
5413 /*----------------------------------------------------------------------------*/
5421 /*----------------------------------------------------------------------------*/
5422 char *
5423 uves_guess_order_table_filename(enum uves_chip chip)
5424 {
5425  return uves_local_filename("orderguesstable", chip, -1, -1);
5426 }
5427 
5428 /*----------------------------------------------------------------------------*/
5436 /*----------------------------------------------------------------------------*/
5437 char *
5438 uves_order_table_filename(enum uves_chip chip)
5439 {
5440  return uves_local_filename("ordertable", chip, -1, -1);
5441 }
5442 
5443 /*----------------------------------------------------------------------------*/
5450 /*----------------------------------------------------------------------------*/
5451 char *uves_ordef_filename(enum uves_chip chip)
5452 {
5453  return uves_local_filename("order_def", chip, -1, -1);
5454 }
5455 
5456 /*----------------------------------------------------------------------------*/
5464 /*----------------------------------------------------------------------------*/
5465 char *
5466 uves_masterdark_filename(enum uves_chip chip)
5467 {
5468  return uves_local_filename("masterdark", chip, -1, -1);
5469 }
5470 
5471 
5472 /*----------------------------------------------------------------------------*/
5478 /*----------------------------------------------------------------------------*/
5479 char *
5480 uves_flat_ratio_filename(enum uves_chip chip)
5481 {
5482  return uves_local_filename("ratio", chip, -1, -1);
5483 }
5484 
5485 /*----------------------------------------------------------------------------*/
5492 /*----------------------------------------------------------------------------*/
5493 char *uves_cd_align_filename(enum uves_chip chip)
5494 {
5495  return uves_local_filename("cd_align", chip, -1, -1);
5496 }
5497 
5498 /*----------------------------------------------------------------------------*/
5506 /*----------------------------------------------------------------------------*/
5507 char *
5508 uves_masterflat_filename(enum uves_chip chip)
5509 {
5510  return uves_local_filename("masterflat", chip, -1, -1);
5511 }
5512 /*----------------------------------------------------------------------------*/
5520 /*----------------------------------------------------------------------------*/
5521 char *
5522 uves_masterflat_bkg_filename(enum uves_chip chip)
5523 {
5524  return uves_local_filename("masterflat_bkg", chip, -1, -1);
5525 }
5526 
5527 /*----------------------------------------------------------------------------*/
5535 /*----------------------------------------------------------------------------*/
5536 char *
5537 uves_masterbias_filename(enum uves_chip chip)
5538 {
5539  return uves_local_filename("masterbias", chip, -1, -1);
5540 }
5541 
5542 /*----------------------------------------------------------------------------*/
5550 /*----------------------------------------------------------------------------*/
5551 char *
5552 uves_guess_line_table_filename(enum uves_chip chip)
5553 {
5554  return uves_local_filename("lineguesstable", chip, -1, -1);
5555 }
5556 /*----------------------------------------------------------------------------*/
5564 /*----------------------------------------------------------------------------*/
5565 char *
5566 uves_line_table_filename(enum uves_chip chip)
5567 {
5568  return uves_local_filename("linetable", chip, -1, -1);
5569 }
5570 
5571 /*----------------------------------------------------------------------------*/
5579 /*----------------------------------------------------------------------------*/
5580 char *
5581 uves_line_table_filename_paf(enum uves_chip chip)
5582 {
5583  return uves_local_filename("linetable_paf", chip, -1, -1);
5584 }
5585 
5586 /*----------------------------------------------------------------------------*/
5594 /*----------------------------------------------------------------------------*/
5595 char *
5596 uves_response_curve_filename(enum uves_chip chip)
5597 {
5598  return uves_local_filename("response", chip, -1, -1);
5599 }
5600 
5601 /*----------------------------------------------------------------------------*/
5609 /*----------------------------------------------------------------------------*/
5610 char *
5611 uves_response_curve_2d_filename(enum uves_chip chip)
5612 {
5613  return uves_local_filename("response_2d", chip, -1, -1);
5614 }
5615 
5616 /*----------------------------------------------------------------------------*/
5624 /*----------------------------------------------------------------------------*/
5625 char *
5626 uves_response_red_standard_filename(enum uves_chip chip)
5627 {
5628  return uves_local_filename("red_std", chip, -1, -1);
5629 }
5630 
5631 
5632 /*----------------------------------------------------------------------------*/
5640 /*----------------------------------------------------------------------------*/
5641 char *
5642 uves_response_red_noappend_standard_filename(enum uves_chip chip)
5643 {
5644  return uves_local_filename("red_nonmerged", chip, -1, -1);
5645 }
5646 
5647 /*----------------------------------------------------------------------------*/
5655 /*----------------------------------------------------------------------------*/
5656 char *
5657 uves_response_bkg_standard_filename(enum uves_chip chip)
5658 {
5659  return uves_local_filename("bkg_std", chip, -1, -1);
5660 }
5661 
5662 
5663 /*----------------------------------------------------------------------------*/
5671 /*----------------------------------------------------------------------------*/
5672 char *
5673 uves_order_extract_qc_standard_filename(enum uves_chip chip)
5674 {
5675  return uves_local_filename("order_extract_qc", chip, -1, -1);
5676 }
5677 
5678 /*----------------------------------------------------------------------------*/
5686 /*----------------------------------------------------------------------------*/
5687 char *
5688 uves_response_efficiency_filename(enum uves_chip chip)
5689 {
5690  return uves_local_filename("efficiency", chip, -1, -1);
5691 }
5692 
5693 /*----------------------------------------------------------------------------*/
5701 /*----------------------------------------------------------------------------*/
5702 
5703 char *
5704 uves_scired_red_2d_science_filename(enum uves_chip chip)
5705 {
5706  return uves_local_filename("red_2d_science", chip, -1, -1);
5707 }
5708 
5716 /*----------------------------------------------------------------------------*/
5717 
5718 
5719 
5720 char *
5721 uves_scired_red_science_filename(enum uves_chip chip)
5722 {
5723  return uves_local_filename("red_science", chip, -1, -1);
5724 }
5732 /*----------------------------------------------------------------------------*/
5733 
5734 
5735 
5736 char *
5737 uves_scired_red_noappend_science_filename(enum uves_chip chip)
5738 {
5739  return uves_local_filename("red_nonmerged_science", chip, -1, -1);
5740 }
5741 /*----------------------------------------------------------------------------*/
5749 /*----------------------------------------------------------------------------*/
5750 char *
5751 uves_scired_red_error_filename(enum uves_chip chip)
5752 {
5753  return uves_local_filename("error_red_science", chip, -1, -1);
5754 }
5755 
5756 /*----------------------------------------------------------------------------*/
5764 /*----------------------------------------------------------------------------*/
5765 char *
5766 uves_scired_red_noappend_error_filename(enum uves_chip chip)
5767 {
5768  return uves_local_filename("error_red_nonmerged_science", chip, -1, -1);
5769 }
5770 
5771 /*----------------------------------------------------------------------------*/
5779 /*----------------------------------------------------------------------------*/
5780 char *
5781 uves_scired_red_2d_error_filename(enum uves_chip chip)
5782 {
5783  return uves_local_filename("error_2d_science", chip, -1, -1);
5784 }
5785 
5786 
5787 /*----------------------------------------------------------------------------*/
5795 /*----------------------------------------------------------------------------*/
5796 char *
5797 uves_scired_fluxcal_science_filename(enum uves_chip chip)
5798 {
5799  return uves_local_filename("fluxcal_science", chip, -1, -1);
5800 }
5801 
5802 
5803 /*----------------------------------------------------------------------------*/
5811 /*----------------------------------------------------------------------------*/
5812 char *
5813 uves_scired_fluxcal_science_noappend_filename(enum uves_chip chip)
5814 {
5815  return uves_local_filename("fluxcal_nonmerged_science", chip, -1, -1);
5816 }
5817 /*----------------------------------------------------------------------------*/
5825 /*----------------------------------------------------------------------------*/
5826 char *
5827 uves_scired_fluxcal_error_filename(enum uves_chip chip)
5828 {
5829  return uves_local_filename("fluxcal_error_science", chip, -1, -1);
5830 }
5831 
5832 
5833 /*----------------------------------------------------------------------------*/
5841 /*----------------------------------------------------------------------------*/
5842 char *
5843 uves_scired_fluxcal_error_noappend_filename(enum uves_chip chip)
5844 {
5845  return uves_local_filename("fluxcal_error_nonmerged_science", chip, -1, -1);
5846 }
5847 
5848 
5849 
5857 /*----------------------------------------------------------------------------*/
5858 char *
5859 uves_scired_fluxcal_science_2d_filename(enum uves_chip chip)
5860 {
5861  return uves_local_filename("fluxcal_2d_science", chip, -1, -1);
5862 }
5863 /*----------------------------------------------------------------------------*/
5871 /*----------------------------------------------------------------------------*/
5872 char *
5873 uves_scired_fluxcal_error_2d_filename(enum uves_chip chip)
5874 {
5875  return uves_local_filename("fluxcal_error_2d_science", chip, -1, -1);
5876 }
5877 /*----------------------------------------------------------------------------*/
5885 /*----------------------------------------------------------------------------*/
5886 char *
5887 uves_scired_ff_variance_filename(enum uves_chip chip)
5888 {
5889  return uves_local_filename("variance_ff_science", chip, -1, -1);
5890 }
5891 
5892 /*----------------------------------------------------------------------------*/
5900 /*----------------------------------------------------------------------------*/
5901 char *
5902 uves_scired_ff_variance_2d_filename(enum uves_chip chip)
5903 {
5904  return uves_local_filename("variance_ff_2d_science", chip, -1, -1);
5905 }
5906 
5907 /*----------------------------------------------------------------------------*/
5914 /*----------------------------------------------------------------------------*/
5915 char *
5916 uves_scired_merged_2d_science_filename(enum uves_chip chip)
5917 {
5918  return uves_local_filename("merged_2d_science", chip, -1, -1);
5919 }
5920 
5928 /*----------------------------------------------------------------------------*/
5929 char *
5930 uves_scired_merged_science_filename(enum uves_chip chip)
5931 {
5932  return uves_local_filename("merged_science", chip, -1, -1);
5933 }
5934 /*----------------------------------------------------------------------------*/
5942 /*----------------------------------------------------------------------------*/
5943 char *
5944 uves_scired_merged_sky_filename(enum uves_chip chip)
5945 {
5946  return uves_local_filename("merged_sky", chip, -1, -1);
5947 }
5948 
5949 /*----------------------------------------------------------------------------*/
5957 /*----------------------------------------------------------------------------*/
5958 char *
5959 uves_scired_background_filename(enum uves_chip chip)
5960 {
5961  return uves_local_filename("background", chip, -1, -1);
5962 }
5963 
5964 /*----------------------------------------------------------------------------*/
5972 /*----------------------------------------------------------------------------*/
5973 char *
5974 uves_scired_resampled_filename(enum uves_chip chip)
5975 {
5976  return uves_local_filename("resampled_science", chip, -1, -1);
5977 }
5978 
5979 
5980 
5981 /*----------------------------------------------------------------------------*/
5989 /*----------------------------------------------------------------------------*/
5990 char *
5991 uves_scired_resampled_2d_filename(enum uves_chip chip)
5992 {
5993  return uves_local_filename("resampled_2d_science", chip, -1, -1);
5994 }
5995 
5996 
5997 /*----------------------------------------------------------------------------*/
6005 /*----------------------------------------------------------------------------*/
6006 char *
6007 uves_scired_resampledmf_filename(enum uves_chip chip)
6008 {
6009  return uves_local_filename("resampled_mflat", chip, -1, -1);
6010 }
6011 
6012 /*----------------------------------------------------------------------------*/
6021 /*----------------------------------------------------------------------------*/
6022 char *
6023 uves_scired_rebinned_filename(enum uves_chip chip)
6024 {
6025  return uves_local_filename("resampled_ff_science", chip, -1, -1);
6026 }
6027 
6028 /*----------------------------------------------------------------------------*/
6037 /*----------------------------------------------------------------------------*/
6038 char *
6039 uves_scired_rebinned_error_filename(enum uves_chip chip)
6040 {
6041  return uves_local_filename("resampled_error_ff_science", chip, -1, -1);
6042 }
6043 
6044 
6053 /*----------------------------------------------------------------------------*/
6054 char *
6055 uves_scired_rebinned_2d_filename(enum uves_chip chip)
6056 {
6057  return uves_local_filename("resampled_ff_2d_science", chip, -1, -1);
6058 }
6059 
6068 /*----------------------------------------------------------------------------*/
6069 char *
6070 uves_scired_rebinned_2d_error_filename(enum uves_chip chip)
6071 {
6072  return uves_local_filename("resampled_error_ff_2d_science", chip, -1, -1);
6073 }
6074 /*----------------------------------------------------------------------------*/
6082 /*----------------------------------------------------------------------------*/
6083 char *
6084 uves_scired_ordertrace_filename(enum uves_chip chip)
6085 {
6086  return uves_local_filename("ordertrace", chip, -1, -1);
6087 }
6088 
6089 /*----------------------------------------------------------------------------*/
6097 /*----------------------------------------------------------------------------*/
6098 char *
6099 uves_scired_crmask_filename(enum uves_chip chip)
6100 {
6101  return uves_local_filename("cr_mask", chip, -1, -1);
6102 }
6103 
6104 /*----------------------------------------------------------------------------*/
6112 /*----------------------------------------------------------------------------*/
6113 char *
6114 uves_scired_wmap_filename(enum uves_chip chip)
6115 {
6116  return uves_local_filename("wave_map", chip, -1, -1);
6117 }
6118 
6119 /*----------------------------------------------------------------------------*/
6127 /*----------------------------------------------------------------------------*/
6128 char *uves_scired_ext2d_filename(enum uves_chip chip)
6129 {
6130  return uves_local_filename("ext_2d_science", chip, -1, -1);
6131 }
6132 
6133 /*----------------------------------------------------------------------------*/
6141 /*----------------------------------------------------------------------------*/
6142 char *uves_scired_ff2d_filename(enum uves_chip chip)
6143 {
6144  return uves_local_filename("ff_2d_science", chip, -1, -1);
6145 }
6146 
6147 /*----------------------------------------------------------------------------*/
6168 /*----------------------------------------------------------------------------*/
6169 char *
6170 uves_local_filename(const char *prefix, enum uves_chip chip, int trace, int window)
6171 {
6172  char *result = NULL;
6173  const char *chip_string;
6174  const char *suffix = ".fits"; /* Always */
6175  char *t = NULL;
6176  char *w = NULL;
6177 
6178  assure( (trace < 0 && window < 0) || /* Empty suffix */
6179  (trace < 0 && window > 0) || /* Window only suffix */
6180  (trace >= 0 && window > 0), /* Trace & window suffix */
6181  CPL_ERROR_ILLEGAL_INPUT, "Illegal trace and window numbers: (%d, %d)",
6182  trace, window);
6183 
6184  /* Chip */
6185  chip_string = uves_chip_tostring_lower(chip);
6186 
6187  /* Trace and window number (possibly empty string) */
6188  check(( t = int_to_string(trace),
6189  w = int_to_string(window)),
6190  "Error creating substrings");
6191 
6192 /* old code:
6193  result = cpl_calloc(strlen(prefix) + 1 +
6194  strlen(chip_string) + strlen(t) + strlen(w) + strlen(suffix) + 1,
6195  sizeof(char));
6196 
6197  assure_mem( result );
6198 
6199  strcpy(result, prefix);
6200  strcat(result, "_");
6201  strcat(result, chip_string);
6202  strcat(result, t);
6203  strcat(result, w);
6204  strcat(result, suffix);
6205 */
6206  result = uves_sprintf("%s_%s%s%s%s", prefix, chip_string, t, w, suffix);
6207  assure_mem( result );
6208 
6209  cleanup:
6210  cpl_free(t);
6211  cpl_free(w);
6212  if (cpl_error_get_code() != CPL_ERROR_NONE)
6213  {
6214  cpl_free(result); result = NULL;
6215  }
6216  return result;
6217 }
6218 
6219 /*----------------------------------------------------------------------------*/
6230 /*----------------------------------------------------------------------------*/
6231 static char *
6232 int_to_string(int i)
6233 {
6234  char *result = NULL;
6235 
6236  assure( -1 <= i, CPL_ERROR_ILLEGAL_INPUT, "Illegal number (%d)", i);
6237 
6238  if (i == -1)
6239  {
6240  /* Empty string */
6241  result = cpl_calloc(1, sizeof(char));
6242  assure_mem( result );
6243  }
6244  else
6245  {
6246  result = uves_sprintf("_%d", i);
6247  }
6248 
6249  cleanup:
6250  if (cpl_error_get_code() != CPL_ERROR_NONE){
6251  cpl_free(result); result = NULL;
6252  }
6253  return result;
6254 }
6255 
6256 
6257 /*----------------------------------------------------------------------------*/
6267 /*----------------------------------------------------------------------------*/
6268 
6269 cpl_image*
6270 uves_vector_to_image(const cpl_vector* vector,cpl_type type)
6271 {
6272  int i=0;
6273  cpl_image* image=NULL;
6274  int size=0;
6275  const double* pv=NULL;
6276  int* pi=NULL;
6277  float* pf=NULL;
6278  double* pd=NULL;
6279 
6280 
6281  size=cpl_vector_get_size(vector);
6282  image=cpl_image_new(size,1,type);
6283  pv=cpl_vector_get_data_const(vector);
6284  if(type == CPL_TYPE_INT) {
6285  pi=cpl_image_get_data_int(image);
6286  for(i=0;i<size;i++) {
6287  pi[i]=pv[i];
6288  }
6289  } else if (type == CPL_TYPE_FLOAT) {
6290  pf=cpl_image_get_data_float(image);
6291  for(i=0;i<size;i++) {
6292  pf[i]=pv[i];
6293  }
6294  } else if (type == CPL_TYPE_DOUBLE) {
6295  pd=cpl_image_get_data_double(image);
6296  for(i=0;i<size;i++) {
6297  pd[i]=pv[i];
6298  }
6299  } else {
6300  assure( false, CPL_ERROR_INVALID_TYPE,
6301  "No CPL type to represent BITPIX = %d", type);
6302  }
6303 
6304  cleanup:
6305  if (cpl_error_get_code() != CPL_ERROR_NONE){
6306  uves_free_image(&image);
6307  }
6308 
6309  return image;
6310 
6311 }
int uves_pfits_get_prescanx(const uves_propertylist *plist, enum uves_chip chip)
Find out the x-prescan.
Definition: uves_pfits.c:594
int uves_pfits_get_firstabsorder(const uves_propertylist *plist)
Get first absolute order number.
Definition: uves_pfits.c:1734
const cpl_property * uves_propertylist_get_const(const uves_propertylist *self, long position)
Access property list elements by index.
cpl_error_code uves_pfits_set_data_median(uves_propertylist *plist, double median)
Write the median pixel value.
Definition: uves_pfits.c:1816
#define uves_msg_error(...)
Print an error message.
Definition: uves_msg.h:64
void uves_polynomial_delete(polynomial **p)
Delete a polynomial.
char * uves_get_datetime_iso8601(void)
Returns the current date and time as a static string.
Definition: uves_time.c:118
#define uves_msg_warning(...)
Print an warning message.
Definition: uves_msg.h:87
cpl_error_code uves_pfits_set_data_stddev(uves_propertylist *plist, double stddev)
Write the RMS error of pixel values.
Definition: uves_pfits.c:1796
int uves_pfits_get_ovrscanx(const uves_propertylist *plist, enum uves_chip chip)
Find out the x-overscan.
Definition: uves_pfits.c:659
int uves_propertylist_erase(uves_propertylist *self, const char *name)
Erase the given property from a property list.
int uves_propertylist_is_empty(const uves_propertylist *self)
Check whether a property list is empty.
const char * uves_pfits_get_cunit1(const uves_propertylist *plist)
Find out the cunit1.
Definition: uves_pfits.c:2024
double uves_pfits_get_bscale(const uves_propertylist *plist)
Find out the bscale.
Definition: uves_pfits.c:2004
cpl_error_code uves_pfits_set_stoptime(uves_propertylist *plist, const char *stop_time)
Write the stop time.
Definition: uves_pfits.c:2642
int uves_pfits_get_lastabsorder(const uves_propertylist *plist)
Get last absolute order number.
Definition: uves_pfits.c:1764
const char * uves_pfits_get_cunit2(const uves_propertylist *plist)
Find out the cunit2.
Definition: uves_pfits.c:2043
int uves_pfits_get_windownumber(const uves_propertylist *plist)
Get the window number.
Definition: uves_pfits.c:1972
#define check_nomsg(CMD)
Definition: uves_error.h:204
polynomial * uves_polynomial_convert_from_table(cpl_table *t)
Convert a table to a polynomial.
cpl_table * uves_ordertable_traces_new(void)
Create the table that describes fibre traces.
Definition: uves_utils.c:3898
const char * uves_pfits_get_drs_id(const uves_propertylist *plist)
Find out the drs id.
Definition: uves_pfits.c:1017
double uves_pfits_get_cdelt2(const uves_propertylist *plist)
Find out the cdelt2.
Definition: uves_pfits.c:2483
#define passure(BOOL,...)
Definition: uves_error.h:207
const char * uves_tostring_cpl_frame_type(cpl_frame_type ft)
Convert a frame type to a string.
Definition: uves_dump.c:315
double uves_pfits_get_gratwlen(const uves_propertylist *plist, enum uves_chip chip)
find out the central wavelength
Definition: uves_pfits.c:1371
cpl_table * uves_polynomial_convert_to_table(const polynomial *p)
Convert a polynomial to a table.
int uves_pfits_get_slit3_x2encoder(const uves_propertylist *plist)
find out the value of UVES_ENCODER_REF2
Definition: uves_pfits.c:174
int uves_pfits_get_naxis(const uves_propertylist *plist)
Find out the NAXIS.
Definition: uves_pfits.c:2259
double uves_polynomial_derivative_2d(const polynomial *p, double x1, double x2, int varno)
Evaluate the partial derivative of a 2d polynomial.
uves_propertylist * uves_initialize_image_header(const char *ctype1, const char *ctype2, const char *cunit1, const char *cunit2, const char *bunit, const double bscale, double crval1, double crval2, double crpix1, double crpix2, double cdelt1, double cdelt2)
Initialize image header.
Definition: uves_utils.c:2174
double uves_pfits_get_crpix2(const uves_propertylist *plist)
Find out the crpix2.
Definition: uves_pfits.c:2447
uves_propertylist * uves_propertylist_new(void)
Create an empty property list.
long uves_propertylist_get_size(const uves_propertylist *self)
Get the current size of a property list.
#define uves_msg(...)
Print a message on 'info' or 'debug' level.
Definition: uves_msg.h:119
uves_propertylist * uves_propertylist_load(const char *name, int position)
Create a property list from a file.
const char * uves_pfits_get_bunit(const uves_propertylist *plist)
Find out the bunit.
Definition: uves_pfits.c:1985
polynomial * uves_polynomial_duplicate(const polynomial *p)
Copy a polynomial.
cpl_error_code uves_propertylist_set_string(uves_propertylist *self, const char *name, const char *value)
Set the value of the given string property list entry.
int uves_pfits_get_slit3_x1encoder(const uves_propertylist *plist)
find out the value of UVES_ENCODER_REF1
Definition: uves_pfits.c:156
cpl_error_code uves_pfits_set_data_max(uves_propertylist *plist, double max)
Write the max pixel value.
Definition: uves_pfits.c:1852
cpl_error_code uves_propertylist_copy_property_regexp(uves_propertylist *self, const uves_propertylist *other, const char *regexp, int invert)
Copy matching properties from another property list.
void uves_pfits_set_cd11(uves_propertylist *plist, double value)
Write the CD1_1 value.
Definition: uves_pfits.c:95
cpl_error_code uves_pfits_set_starttime(uves_propertylist *plist, const char *start_time)
Write the start time.
Definition: uves_pfits.c:2625
#define assure_mem(PTR)
Definition: uves_error.h:181
polynomial * uves_polynomial_new(const cpl_polynomial *pol)
Create a polynomial.
void uves_pfits_set_cd12(uves_propertylist *plist, double value)
Write the CD1_2 value.
Definition: uves_pfits.c:110
double uves_polynomial_evaluate_2d(const polynomial *p, double x1, double x2)
Evaluate a 2d polynomial.
int uves_chip_get_index(enum uves_chip chip)
Convert to integer.
Definition: uves_chip.c:124
double uves_polynomial_get_coeff_1d(const polynomial *p, int degree)
Get a coefficient of a 1D polynomial.
enum uves_chip uves_chip_get_first(bool blue)
Get first chip for blue or red arm.
Definition: uves_chip.c:92
void uves_pfits_set_ra(uves_propertylist *plist, double ra)
Write the right ascension.
Definition: uves_pfits.c:982
cpl_error_code uves_ordertable_traces_add(cpl_table *traces, int fibre_ID, double fibre_offset, int fibre_mask)
Add a trace.
Definition: uves_utils.c:3925
polynomial * uves_polynomial_regression_1d(cpl_table *t, const char *X, const char *Y, const char *sigmaY, int degree, const char *polynomial_fit, const char *residual_square, double *mean_squared_error, double kappa)
Fit a 1d polynomial to two table columns.
Definition: uves_utils.c:2590
cpl_error_code uves_pfits_set_data_average(uves_propertylist *plist, double average)
Write the average pixel value.
Definition: uves_pfits.c:1778
const char * uves_tostring_cpl_type(cpl_type t)
Convert a CPL type to a string.
Definition: uves_dump.c:378
#define uves_msg_low(...)
Print a message on a lower message level.
Definition: uves_msg.h:105
bool uves_format_is_new(const uves_propertylist *plist)
Find out FITS header format.
Definition: uves_pfits.c:573
const char * uves_chip_tostring_lower(enum uves_chip chip)
Convert to string.
Definition: uves_chip.c:139
cpl_error_code uves_polynomial_shift(polynomial *p, int varno, double shift)
Shift a polynomial.
int uves_propertylist_erase_regexp(uves_propertylist *self, const char *regexp, int invert)
Erase all properties with name matching a given regular expression.
void uves_pfits_set_lastabsorder(uves_propertylist *plist, int last_abs_order)
Write the last absolute order number.
Definition: uves_pfits.c:1750
enum uves_chip uves_chip_get_next(enum uves_chip chip)
Get next chip.
Definition: uves_chip.c:108
#define uves_msg_debug(...)
Print a debug message.
Definition: uves_msg.h:97
double uves_pfits_get_cdelt1(const uves_propertylist *plist)
Find out the cdelt1.
Definition: uves_pfits.c:2465
double uves_pfits_get_crval1(const uves_propertylist *plist)
Find out the crval1.
Definition: uves_pfits.c:2393
uves_propertylist * uves_propertylist_duplicate(const uves_propertylist *self)
Create a copy of the given property list.
#define assure_nomsg(BOOL, CODE)
Definition: uves_error.h:177
int uves_pfits_get_naxis1(const uves_propertylist *plist)
Find out the NAXIS1.
Definition: uves_pfits.c:2316
cpl_error_code uves_pfits_set_wlen1(uves_propertylist *plist, double wlen1)
Write the WLEN1 value.
Definition: uves_pfits.c:1873
int uves_propertylist_contains(const uves_propertylist *self, const char *name)
Check whether a property is present in a property list.
cpl_error_code uves_pfits_set_data_min(uves_propertylist *plist, double min)
Write the min pixel value.
Definition: uves_pfits.c:1834
int uves_pfits_get_traceid(const uves_propertylist *plist)
Get the trace ID number.
Definition: uves_pfits.c:1959
#define check(CMD,...)
Definition: uves_error.h:198
double uves_pfits_get_crval2(const uves_propertylist *plist)
Find out the crval2.
Definition: uves_pfits.c:2411
void uves_pfits_set_dec(uves_propertylist *plist, double dec)
Write the declination.
Definition: uves_pfits.c:964
int uves_pfits_get_bitpix(const uves_propertylist *plist)
Find out the BITPIX.
Definition: uves_pfits.c:2298
void uves_pfits_set_cd22(uves_propertylist *plist, double value)
Write the CD2_2 value.
Definition: uves_pfits.c:140
const char * uves_pfits_get_chipid(const uves_propertylist *plist, enum uves_chip chip)
Find out the chip ID.
Definition: uves_pfits.c:619
void uves_pfits_set_firstabsorder(uves_propertylist *plist, int first_abs_order)
Write the first absolute order number.
Definition: uves_pfits.c:1717
void uves_pfits_set_cd21(uves_propertylist *plist, double value)
Write the CD2_1 value.
Definition: uves_pfits.c:125
double uves_pfits_get_crpix1(const uves_propertylist *plist)
Find out the crpix1.
Definition: uves_pfits.c:2429
double uves_pfits_get_wlen1(const uves_propertylist *plist)
find out the WLEN1 wavelength value
Definition: uves_pfits.c:1350
const char * uves_pfits_get_ctype2(const uves_propertylist *plist)
Find out the ctype2.
Definition: uves_pfits.c:2081
int uves_propertylist_has(const uves_propertylist *self, const char *name)
Check whether a property is present in a property list.
int uves_pfits_put_qc(uves_propertylist *plist, const cpl_table *qclog)
Add QC-LOG to FITS header.
Definition: uves_qclog.c:735
const char * uves_pfits_get_ctype1(const uves_propertylist *plist)
Find out the ctype1.
Definition: uves_pfits.c:2062
cpl_error_code uves_propertylist_append(uves_propertylist *self, const uves_propertylist *other)
Append a property list..
cpl_error_code uves_propertylist_copy_property(uves_propertylist *self, const uves_propertylist *other, const char *name)
Copy a property from another property list.