uves_dfs.c

00001 /*
00002  * This file is part of the UVES Pipeline
00003  * Copyright (C) 2002, 2003, 2004, 2005 European Southern Observatory
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
00018  */
00019 
00020 /*
00021  * $Author: jmlarsen $
00022  * $Date: 2007/10/30 17:45:03 $
00023  * $Revision: 1.240 $
00024  * $Name: uves-3_4_5 $
00025  * $Log: uves_dfs.c,v $
00026  * Revision 1.240  2007/10/30 17:45:03  jmlarsen
00027  * Added WEIGHTS_<chip> images to support object weighted arclamp extraction
00028  *
00029  * Revision 1.239  2007/10/17 14:58:59  amodigli
00030  * added uves_check_if_format_is_midas and fixed compilation warnings
00031  *
00032  * Revision 1.238  2007/10/15 06:39:13  amodigli
00033  * keep 'Fibre' column in linetable to make work flames-uves data reduction chain
00034  *
00035  * Revision 1.237  2007/10/01 17:07:49  amodigli
00036  * cleaned output
00037  *
00038  * Revision 1.236  2007/09/19 11:09:49  amodigli
00039  * Now FLAMES_FIB_FF_DT is a macro
00040  *
00041  * Revision 1.235  2007/09/12 13:11:56  amodigli
00042  * fixed bug with UVES-ech data reduction
00043  *
00044  * Revision 1.234  2007/09/11 17:08:07  amodigli
00045  * added uves_polynomial_convert_from_plist_midas from uves_utils_polynomial.h
00046  *
00047  * Revision 1.233  2007/09/06 15:48:42  amodigli
00048  * added info on old/new format
00049  *
00050  * Revision 1.232  2007/09/06 14:15:16  amodigli
00051  * changed filenames science products
00052  *
00053  * Revision 1.231  2007/08/24 06:43:37  amodigli
00054  * fixed compilation warnings
00055  *
00056  * Revision 1.230  2007/08/21 13:08:26  jmlarsen
00057  * Removed irplib_access module, largely deprecated by CPL-4
00058  *
00059  * Revision 1.229  2007/08/20 07:59:15  amodigli
00060  * update to CPL4
00061  *
00062  * Revision 1.228  2007/08/16 13:21:15  amodigli
00063  * added uves_scired_red_2d_error_filename
00064  *
00065  * Revision 1.227  2007/08/16 06:49:47  amodigli
00066  * added uves_vector_to_image
00067  *
00068  * Revision 1.226  2007/08/10 12:10:35  amodigli
00069  * changed 2d extraction product file names as by DFS04196
00070  *
00071  * Revision 1.225  2007/07/27 14:17:07  amodigli
00072  * commented out code to remove blanks (' ') from  string descriptors. Added code to check that HISTORY keywords are in group of 3 lines, 2 not empty and the last empty
00073  *
00074  * Revision 1.224  2007/07/25 10:56:23  amodigli
00075  * fixed small leak
00076  *
00077  * Revision 1.223  2007/07/25 10:52:17  amodigli
00078  * fixed problem with images with NAXIS=1 and CPL4
00079  *
00080  * Revision 1.222  2007/07/23 06:30:50  amodigli
00081  * added FLAMES_FIB_FF_DT
00082  *
00083  * Revision 1.221  2007/07/03 12:40:03  amodigli
00084  * added FLAMES_CORVEL_MASK FLAMES_SCI_SIM_RED and support for cubes FIB_FF and SLIT_FF
00085  *
00086  * Revision 1.220  2007/06/29 10:47:50  jmlarsen
00087  * load_linetable: Assume MIDAS like format if FLAMES
00088  *
00089  * Revision 1.219  2007/06/28 09:17:16  jmlarsen
00090  * Make work order table column renaming for FLAMES
00091  *
00092  * Revision 1.218  2007/06/26 14:48:11  jmlarsen
00093  * Removed unused variable
00094  *
00095  * Revision 1.217  2007/06/26 14:46:01  jmlarsen
00096  * Do not try to read dispersion polynomial when not requested
00097  *
00098  * Revision 1.216  2007/06/26 14:04:35  jmlarsen
00099  * Save with BITPIX16 for FLAMES orderpos
00100  *
00101  * Revision 1.215  2007/06/26 13:34:52  jmlarsen
00102  * Exported function for FLAMES
00103  *
00104  * Revision 1.214  2007/06/25 15:43:45  jmlarsen
00105  * uves_frameset_insert(): propagate custom keywords before, not after, calling cpl_dfs_setup_product_header
00106  *
00107  * Revision 1.213  2007/06/25 05:55:11  amodigli
00108  * added FLAMES_SCI_RED FLAMES_SCI_COM_RED to raw frames list
00109  *
00110  * Revision 1.212  2007/06/22 14:50:46  jmlarsen
00111  * Optionally save height=1 images as NAXIS=1
00112  *
00113  * Revision 1.211  2007/06/22 11:15:05  jmlarsen
00114  * uves_save_image(): Also save float images with NAXIS=1 when height is 1
00115  *
00116  * Revision 1.210  2007/06/22 09:30:08  jmlarsen
00117  * Allow saving CPL_TYPE_INT images as 16 or 32 bit FITS
00118  *
00119  * Revision 1.209  2007/06/20 15:49:05  jmlarsen
00120  * Enabled check for NULL polynoimal
00121  *
00122  * Revision 1.208  2007/06/20 13:05:17  amodigli
00123  * commented assure not to make fail a test case
00124  *
00125  * Revision 1.207  2007/06/20 08:32:52  amodigli
00126  * updated uves_load_linetable to support FIBER mode
00127  *
00128  * Revision 1.206  2007/06/06 08:17:33  amodigli
00129  * replace tab with 4 spaces
00130  *
00131  * Revision 1.205  2007/05/23 12:50:53  jmlarsen
00132  * Replace isnan/isinf -> irplib_isnan/irplib_isinf
00133  *
00134  * Revision 1.204  2007/05/16 14:56:27  jmlarsen
00135  * Fixed error message
00136  *
00137  * Revision 1.203  2007/05/16 11:47:18  amodigli
00138  * added FLAMES_SCI_COM_RED
00139  *
00140  * Revision 1.202  2007/05/04 08:55:15  amodigli
00141  * moved up declaration of img to suppress compilation warning
00142  *
00143  * Revision 1.201  2007/05/03 15:19:10  jmlarsen
00144  * Added const version of uves_load_linetable()
00145  *
00146  * Revision 1.200  2007/05/02 13:36:14  jmlarsen
00147  * Decreased verbosity of debug message
00148  *
00149  * Revision 1.199  2007/05/02 13:16:30  jmlarsen
00150  * Fixed error message typo
00151  *
00152  * Revision 1.198  2007/04/26 13:19:11  jmlarsen
00153  * Exported function copy_if_possible
00154  *
00155  * Revision 1.197  2007/04/24 16:44:26  amodigli
00156  * changed interface uves_load_ordertable to return also extention table
00157  *
00158  * Revision 1.196  2007/04/24 12:50:29  jmlarsen
00159  * Replaced cpl_propertylist -> uves_propertylist which is much faster
00160  *
00161  * Revision 1.195  2007/04/23 06:59:29  amodigli
00162  * added uves_save_imagelist
00163  *
00164  * Revision 1.194  2007/04/12 12:15:12  jmlarsen
00165  * Propagate keyword OS-EXPOI
00166  *
00167  * Revision 1.193  2007/04/12 11:58:46  jmlarsen
00168  * Rename order table column if necessary
00169  *
00170  * Revision 1.192  2007/04/10 07:06:59  jmlarsen
00171  * Take into account 64 pixel gap in REDU CRVAL2 computation
00172  *
00173  * Revision 1.191  2007/04/04 06:27:06  jmlarsen
00174  * Fixed malloc -> cpl_malloc
00175  *
00176  * Revision 1.190  2007/04/03 11:02:25  jmlarsen
00177  * Support reading float MIDAS arrays
00178  *
00179  * Revision 1.189  2007/04/03 08:03:59  jmlarsen
00180  * uves_read_midas_array: support arrays of any length
00181  *
00182  * Revision 1.188  2007/04/03 06:28:45  amodigli
00183  * uves_load_ordertable provides now fibre_mask and fibre_pos if appropriate
00184  *
00185  * Revision 1.187  2007/03/30 07:06:59  jmlarsen
00186  * Initialize variables to suppress warnings
00187  *
00188  * Revision 1.186  2007/03/23 07:59:30  jmlarsen
00189  * Fixed minor memory leak
00190  *
00191  * Revision 1.185  2007/03/20 15:39:46  amodigli
00192  * added FLAMES tags
00193  *
00194  * Revision 1.184  2007/03/20 07:26:57  jmlarsen
00195  * Don't remove std star from flux table which has NULL type
00196  *
00197  * Revision 1.183  2007/03/15 15:04:34  jmlarsen
00198  * Allow spaces in HISTORY keyword string values
00199  *
00200  * Revision 1.182  2007/03/05 10:16:12  jmlarsen
00201  * Define 'dWave' as constant
00202  *
00203  * Revision 1.181  2007/02/27 14:04:35  jmlarsen
00204  * Added comment
00205  *
00206  * Revision 1.180  2007/02/26 13:27:53  jmlarsen
00207  * Partial workaround for slow uves_propertylist_copy_property_regexp()
00208  *
00209  * Revision 1.179  2007/02/22 15:33:24  jmlarsen
00210  * Redefine catalogue wavelength uncertainties to better match new catalogue
00211  *
00212  * Revision 1.178  2007/02/14 14:06:34  jmlarsen
00213  * Use REF_TFLAT, not MASTER_TFLAT as master
00214  *
00215  * Revision 1.177  2007/02/12 10:09:33  jmlarsen
00216  * Fixed recently introduced bug that REDL image was loaded twice, instead of REDL + REDU
00217  *
00218  * Revision 1.176  2007/02/09 13:36:04  jmlarsen
00219  * Added function to load ref_flat
00220  *
00221  * Revision 1.175  2007/02/09 08:51:06  jmlarsen
00222  * Use define's rather than hard-coded recipe names
00223  *
00224  * Revision 1.174  2007/02/09 08:03:08  jmlarsen
00225  * Changed definition of CRVAL in products
00226  *
00227  * Revision 1.173  2007/02/08 07:33:01  jmlarsen
00228  * Added uves_load_cd_align(), changed CRVAL computation
00229  *
00230  * Revision 1.172  2007/02/01 07:23:44  jmlarsen
00231  * Removed debugging code
00232  *
00233  * Revision 1.171  2007/01/31 15:18:52  jmlarsen
00234  * Write +- FLT_MAX to FITS file if double value out of range
00235  *
00236  * Revision 1.170  2007/01/31 15:10:34  jmlarsen
00237  * Avoid inf+nan when saving FITS files
00238  *
00239  * Revision 1.169  2007/01/17 13:25:39  jmlarsen
00240  * Added uves_load_image()
00241  *
00242  * Revision 1.168  2007/01/16 10:27:30  jmlarsen
00243  * Implemented self-consistent propagation of FITS geometry keywords
00244  *
00245  * Revision 1.167  2007/01/15 08:45:27  jmlarsen
00246  * Added comment
00247  *
00248  * Revision 1.166  2007/01/10 12:37:16  jmlarsen
00249  * Exported function to warn about mismatching calibration frames
00250  *
00251  * Revision 1.165  2007/01/09 17:45:42  amodigli
00252  * added uves_check_rec_status
00253  *
00254  * Revision 1.164  2006/12/12 12:09:14  jmlarsen
00255  * Added function to load corvel table
00256  *
00257  * Revision 1.163  2006/12/11 12:34:01  jmlarsen
00258  * Use date to determine new/old format
00259  *
00260  * Revision 1.162  2006/12/07 08:22:59  jmlarsen
00261  * uves_load_raw_imagelist: support FLAMES
00262  *
00263  * Revision 1.161  2006/12/01 08:26:56  jmlarsen
00264  * Load FLAMES order table oshift/yshift
00265  *
00266  * Revision 1.160  2006/11/24 16:21:07  jmlarsen
00267  * Added FIB_LINE_TABLE_x
00268  *
00269  * Revision 1.159  2006/11/24 11:10:14  jmlarsen
00270  * Support for loading FLAMES guess line table
00271  *
00272  * Revision 1.158  2006/11/24 09:35:40  jmlarsen
00273  * Workaround for slow uves_propertylist_get_size
00274  *
00275  * Revision 1.157  2006/11/23 10:04:11  jmlarsen
00276  * Minor message change
00277  *
00278  * Revision 1.156  2006/11/22 08:39:55  jmlarsen
00279  * Exported and fixed bug in uves_read_midas_array
00280  *
00281  * Revision 1.154  2006/11/22 08:22:29  jmlarsen
00282  * Set message level according to preprocessor symbol
00283  *
00284  * Revision 1.153  2006/11/16 14:08:33  jmlarsen
00285  * Implemented loading FLAMES ordertable
00286  *
00287  * Revision 1.152  2006/11/16 09:51:13  jmlarsen
00288  * Use compile time branching to support both released and development CPL versions
00289  *
00290  * Revision 1.151  2006/11/16 08:32:03  jmlarsen
00291  * Save CPL_TYPE_INT images as 16 bit unsigned, to support flames_cal_orderpos
00292  *
00293  * Revision 1.150  2006/11/15 15:02:14  jmlarsen
00294  * Implemented const safe workarounds for CPL functions
00295  *
00296  * Revision 1.148  2006/11/15 14:04:08  jmlarsen
00297  * Removed non-const version of parameterlist_get_first/last/next which is already 
00298  * in CPL, added const-safe wrapper, unwrapper and deallocator functions
00299  *
00300  * Revision 1.147  2006/11/13 14:23:55  jmlarsen
00301  * Removed workarounds for CPL const bugs
00302  *
00303  * Revision 1.146  2006/11/13 12:44:31  jmlarsen
00304  * Support FLAMES FIB_ARC_LAMP_RED frames
00305  *
00306  * Revision 1.145  2006/11/08 14:03:31  jmlarsen
00307  * Fixed doc bug when warning about deprecated background table
00308  *
00309  * Revision 1.144  2006/11/08 08:03:26  jmlarsen
00310  * Avoid initializers not computable at compile time, for portability
00311  *
00312  * Revision 1.143  2006/11/07 14:01:10  jmlarsen
00313  * Moved flames_load_ functions to separate source file
00314  *
00315  * Revision 1.142  2006/11/06 15:19:41  jmlarsen
00316  * Removed unused include directives
00317  *
00318  * Revision 1.141  2006/11/03 15:01:21  jmlarsen
00319  * Killed UVES 3d table module and use CPL 3d tables
00320  *
00321  * Revision 1.140  2006/10/26 14:02:41  jmlarsen
00322  * Removed redundant goto
00323  *
00324  * Revision 1.139  2006/10/24 14:05:23  jmlarsen
00325  * Generalized load functions to support FLAMES
00326  *
00327  * Revision 1.138  2006/10/19 13:53:25  jmlarsen
00328  * Changed guess line table tag to LINE_GUESS_TAB
00329  *
00330  * Revision 1.137  2006/10/12 11:37:28  jmlarsen
00331  * Temporarily disabled FLAMES code generation
00332  *
00333  * Revision 1.136  2006/10/10 11:29:24  jmlarsen
00334  * Added code to propagate TM-START
00335  *
00336  * Revision 1.135  2006/10/10 11:20:47  jmlarsen
00337  * Renamed line table columns to match MIDAS
00338  *
00339  * Revision 1.134  2006/10/05 11:14:59  jmlarsen
00340  * Removed debugging code
00341  *
00342  * Revision 1.133  2006/10/02 08:34:04  jmlarsen
00343  * Added REF_TFLAT
00344  *
00345  * Revision 1.132  2006/09/27 13:13:26  jmlarsen
00346  * Use dynamic memory allocation to store bad pixels
00347  *
00348  * Revision 1.131  2006/09/20 15:42:17  jmlarsen
00349  * Implemented MASTER_RESPONSE support
00350  *
00351  * Revision 1.130  2006/09/20 10:56:50  jmlarsen
00352  * Propagate DATAMEAN/DATAMED/DATARMS if present
00353  *
00354  * Revision 1.129  2006/09/19 14:25:30  jmlarsen
00355  * Propagate FITS keywords from master flat, not science, to WCALIB_FLAT_OBJ
00356  *
00357  * Revision 1.128  2006/09/19 06:55:06  jmlarsen
00358  * Changed interface of uves_frameset to optionally write image statistics kewwords
00359  *
00360  * Revision 1.127  2006/09/14 08:46:51  jmlarsen
00361  * Added support for TFLAT, SCREEN_FLAT frames
00362  *
00363  * Revision 1.126  2006/09/08 14:04:41  jmlarsen
00364  * Documentation update
00365  *
00366  * Revision 1.125  2006/08/31 07:24:57  jmlarsen
00367  * Fixed buffer overruns happening when raw frames are not available
00368  *
00369  * Revision 1.124  2006/08/24 11:36:56  jmlarsen
00370  * Write recipe start/stop time to header
00371  *
00372  * Revision 1.123  2006/08/23 09:33:03  jmlarsen
00373  * Renamed local variables shadowing POSIX reserved names
00374  *
00375  * Revision 1.122  2006/08/21 07:53:17  jmlarsen
00376  * Added debug message
00377  *
00378  * Revision 1.121  2006/08/18 13:32:13  jmlarsen
00379  * Use legal FITS keywords for TRACEID/WINDOW/FABSORD/LABSORD
00380  *
00381  * Revision 1.120  2006/08/18 07:07:43  jmlarsen
00382  * Switched order of cpl_calloc arguments
00383  *
00384  * Revision 1.119  2006/08/17 14:11:25  jmlarsen
00385  * Use assure_mem macro to check for memory allocation failure
00386  *
00387  * Revision 1.118  2006/08/17 13:56:52  jmlarsen
00388  * Reduced max line length
00389  *
00390  * Revision 1.117  2006/08/17 13:04:10  jmlarsen
00391  * Reduced max line length
00392  *
00393  * Revision 1.116  2006/08/17 09:17:15  jmlarsen
00394  * Removed CPL2 code
00395  *
00396  * Revision 1.115  2006/08/11 14:56:05  amodigli
00397  * removed Doxygen warnings
00398  *
00399  * Revision 1.114  2006/08/11 11:26:59  jmlarsen
00400  * Change text message
00401  *
00402  * Revision 1.113  2006/08/11 08:59:07  jmlarsen
00403  * Take into account the different meanings of line table 'Y' column
00404  *
00405  * Revision 1.112  2006/08/08 12:55:00  jmlarsen
00406  * Support uppercase column names when loading linetable
00407  *
00408  * Revision 1.111  2006/08/08 11:27:18  amodigli
00409  * upgrade to CPL3
00410  *
00411  * Revision 1.110  2006/08/07 14:42:02  jmlarsen
00412  * Implemented on-the-fly correction of a line table when its 
00413  * order numbering is inconsistent with the order table (DFS02694)
00414  *
00415  * Revision 1.109  2006/08/07 12:14:13  jmlarsen
00416  * Removed unused code
00417  *
00418  * Revision 1.108  2006/08/01 14:43:36  amodigli
00419  * fixed bug loading fitsheader in uves_load_masterformatcheck
00420  *
00421  * Revision 1.107  2006/07/31 06:29:05  amodigli
00422  * added flames_load_frame_index
00423  *
00424  * Revision 1.106  2006/07/14 12:19:28  jmlarsen
00425  * Support multiple QC tests per product
00426  *
00427  * Revision 1.105  2006/07/03 12:59:14  jmlarsen
00428  * Changed message to debug level
00429  *
00430  * Revision 1.104  2006/06/29 07:57:21  amodigli
00431  * fixed warning messages from make html
00432  *
00433  * Revision 1.103  2006/06/29 07:32:05  amodigli
00434  * removed warning from make html
00435  *
00436  * Revision 1.102  2006/06/28 13:27:50  amodigli
00437  * Fixed problem dumping ARCFILE key changing uves_save_paf interface
00438  *
00439  * Revision 1.101  2006/06/26 07:54:14  amodigli
00440  * flames_load_image flames_load_table
00441  *
00442  * Revision 1.100  2006/06/23 15:31:32  amodigli
00443  * added useful stuff for flames
00444  *
00445  * Revision 1.99  2006/06/22 15:25:35  amodigli
00446  * changes for flames_cal_prep_sff_ofpos
00447  *
00448  * Revision 1.98  2006/06/22 12:03:56  amodigli
00449  * clean msg warning
00450  *
00451  * Revision 1.97  2006/06/22 09:42:56  jmlarsen
00452  * Removed syntax error
00453  *
00454  * Revision 1.96  2006/06/22 08:57:38  jmlarsen
00455  * Changed a few messages
00456  *
00457  * Revision 1.95  2006/06/22 06:42:38  amodigli
00458  * fixed some compilation warnings
00459  *
00460  * Revision 1.94  2006/06/20 08:25:56  amodigli
00461  * fixed doxigen warnings
00462  *
00463  * Revision 1.93  2006/06/19 06:51:14  amodigli
00464  * added support flames-old format
00465  *
00466  * Revision 1.92  2006/06/16 08:22:01  jmlarsen
00467  * Manually propagate ESO.DET. keywords from 1st/2nd input header
00468  *
00469  * Revision 1.91  2006/06/13 11:55:06  jmlarsen
00470  * Shortened max line length
00471  *
00472  * Revision 1.90  2006/06/05 08:51:55  amodigli
00473  * cleaned some warnings from static checks
00474  *
00475  * Revision 1.89  2006/06/01 14:43:17  jmlarsen
00476  * Added missing documentation
00477  *
00478  * Revision 1.88  2006/06/01 14:21:02  amodigli
00479  * frm --> frm_tmp, dup --> frm_dup
00480  *
00481  * Revision 1.87  2006/05/31 09:51:01  amodigli
00482  * removed compilation warning
00483  *
00484  * Revision 1.86  2006/05/22 06:47:15  amodigli
00485  * fixed some bugs on msflat
00486  *
00487  * Revision 1.85  2006/05/19 13:07:52  amodigli
00488  * modified to support SFLATs
00489  *
00490  * Revision 1.84  2006/05/17 09:54:55  amodigli
00491  * added supposr SFLATs
00492  *
00493  * Revision 1.82  2006/05/15 06:09:52  amodigli
00494  * added support for some FLAMES input frames
00495  *
00496  * Revision 1.81  2006/05/12 15:01:30  jmlarsen
00497  * Changed msg level warning -> debug when there's no QC log
00498  *
00499  * Revision 1.80  2006/04/25 14:58:48  amodigli
00500  * added paf creation functionalities
00501  *
00502  * Revision 1.79  2006/04/24 09:18:06  jmlarsen
00503  * Minor message change
00504  *
00505  * Revision 1.78  2006/04/20 10:48:20  amodigli
00506  * inform that no QC log is provided
00507  *
00508  * Revision 1.77  2006/04/10 12:35:42  jmlarsen
00509  * Simplified the save-product function
00510  *
00511  * Revision 1.76  2006/04/06 13:12:54  jmlarsen
00512  * Fixed doc. bug
00513  *
00514  * Revision 1.75  2006/04/06 12:56:50  jmlarsen
00515  * Added support for PDARK, IFLAT, DLFAT frames
00516  *
00517  * Revision 1.74  2006/04/06 11:48:17  jmlarsen
00518  * Support for SCI_POINT_-, SCI_EXTND_- and SCI_SLICER-frames
00519  *
00520  * Revision 1.73  2006/04/06 09:48:15  amodigli
00521  * changed uves_frameset_insert interface to have QC log
00522  *
00523  * Revision 1.72  2006/04/06 08:31:15  jmlarsen
00524  * Added support for reading MASTER_DFLAT, MASTER_IFLAT, MASTER_PDARK
00525  *
00526  * Revision 1.71  2006/03/24 14:24:29  jmlarsen
00527  * Don't blindly stack flat-fields of different wavelenghts
00528  *
00529  * Revision 1.70  2006/03/09 10:51:58  jmlarsen
00530  * Added timing info
00531  *
00532  * Revision 1.69  2006/03/06 09:22:43  jmlarsen
00533  * Added support for reading MIDAS line tables with MIDAS tags
00534  *
00535  * Revision 1.68  2006/03/03 13:54:11  jmlarsen
00536  * Changed syntax of check macro
00537  *
00538  * Revision 1.67  2006/02/15 13:19:15  jmlarsen
00539  * Reduced source code max. line length
00540  *
00541  * Revision 1.66  2006/01/17 10:14:20  jmlarsen
00542  * Changed order of functions
00543  *
00544  * Revision 1.65  2006/01/16 07:10:53  amodigli
00545  *
00546  * Clean
00547  *
00548  * Revision 1.64  2006/01/09 15:22:53  jmlarsen
00549  * Removed some warnings
00550  *
00551  * Revision 1.63  2006/01/09 14:05:21  amodigli
00552  * Fixed doxigen warnings
00553  *
00554  * Revision 1.62  2006/01/03 16:56:53  amodigli
00555  * Added MASTER_ARC_FORM
00556  *
00557  * Revision 1.61  2005/12/19 16:17:56  jmlarsen
00558  * Replaced bool -> int
00559  *
00560  */
00561 
00562 #ifdef HAVE_CONFIG_H
00563 #include <config.h>
00564 #endif
00565 
00566 /*----------------------------------------------------------------------------*/
00573 /*----------------------------------------------------------------------------*/
00574 
00575 /*-----------------------------------------------------------------------------
00576                                    Includes
00577  -----------------------------------------------------------------------------*/
00578 
00579 #include <uves_dfs.h>
00580 
00581 #include <uves_utils.h>
00582 #include <uves_wavecal_utils.h>
00583 #include <uves_pfits.h>
00584 #include <uves_dump.h>
00585 #include <uves_qclog.h>
00586 #include <uves.h>
00587 #include <uves_utils_wrappers.h>
00588 #include <uves_error.h>
00589 #include <uves_msg.h>
00590 
00591 #include <irplib_utils.h>
00592 
00593 #include <cpl.h>
00594 
00595 #include <qfits.h> /* iso time */
00596 
00597 #include <float.h>
00598 
00599 /*-----------------------------------------------------------------------------
00600                                    Defines
00601  -----------------------------------------------------------------------------*/
00602 
00603 #define DICTIONARY "PRO-1.15"
00604 /*-----------------------------------------------------------------------------
00605                                    Prototypes
00606  -----------------------------------------------------------------------------*/
00607 
00608 static polynomial *load_polynomial(const char* filename, int extension);
00609 static char *uves_local_filename(const char *prefix, enum uves_chip chip, int trace, int window);
00610 static char *int_to_string(int i);
00611 
00612 static cpl_error_code
00613 load_raw_image(const char *filename, 
00614            cpl_type type, bool flames, bool blue,
00615            cpl_image *raw_image[2],
00616            uves_propertylist *raw_header[2], 
00617            uves_propertylist *rotated_header[2]);
00618 
00626 int uves_check_rec_status(const int val) {
00627    if(cpl_error_get_code() != CPL_ERROR_NONE) {
00628       uves_msg_error("error before %d",val);
00629       uves_msg_error((char* ) cpl_error_get_message());
00630       uves_msg_error((char* ) cpl_error_get_where());
00631       return -1;
00632     }
00633     return 0;
00634 }
00635 
00636 
00637 /*----------------------------------------------------------------------------*/
00654 /*----------------------------------------------------------------------------*/
00655 polynomial *
00656 uves_polynomial_convert_from_plist_midas(const uves_propertylist *plist, 
00657                      const char *regression_name,
00658                                          const int index)
00659 {
00660     polynomial *result = NULL;
00661     cpl_polynomial *pol = NULL;
00662     int N = strlen(regression_name);
00663     const char *coeffi_name = NULL;
00664     cpl_type type;
00665     int length;
00666     int *coeffi = NULL;
00667     int degree1 = -1;
00668     int degree2 = -1; 
00669     bool found = false;
00670     const long int plist_size = uves_propertylist_get_size(plist);
00671     int i;
00672      
00673     char cind=' ';
00674 
00675     if (index == -1) {
00676       coeffi_name = cpl_sprintf("%sI", regression_name);
00677     }
00678     else {
00679 
00680      switch(index) {
00681 
00682      case 1: cind='1'; break;
00683      case 2: cind='2'; break;
00684      case 3: cind='3'; break;
00685      case 4: cind='4'; break;
00686      case 5: cind='5'; break;
00687      case 6: cind='6'; break;
00688      case 7: cind='7'; break;
00689      case 8: cind='8'; break;
00690      case 9: cind='9'; break;
00691      default: 
00692        assure( false, CPL_ERROR_ILLEGAL_INPUT, 
00693              "Illegal index %d, 1-9 expected", index);
00694        break;
00695      }
00696 
00697 
00698       coeffi_name = cpl_sprintf("%sI%d", regression_name, index);
00699     }
00700 
00701     check_nomsg( coeffi = uves_read_midas_array(plist, coeffi_name, &length, &type, NULL));
00702 
00703 
00704     assure( type == CPL_TYPE_INT, CPL_ERROR_TYPE_MISMATCH,
00705         "Type of array %s is %s, integer expected",
00706         coeffi_name, uves_tostring_cpl_type(type));
00707     /*
00708     assure( length == 7, CPL_ERROR_ILLEGAL_INPUT,
00709         "Wrong array length = %d, 7 expected",
00710         length);
00711     */
00712     /* ignore OUTPUTI(1)- N,no.of data, */
00713     
00714     /* OUTPUTI(2)- M,no.of ind.var. */
00715     
00716     assure( coeffi[1] == 2, CPL_ERROR_UNSUPPORTED_MODE,
00717         "Regressions is %d-dimensional (2D expected)", 
00718         coeffi[1]);
00719 
00720     /* ignore OUTPUTI(3-5) (column number of variables)
00721        (3)- col.no. of dep.var.
00722        (4)- col.no. of indep.var.
00723        (5)-
00724     */
00725     
00726     /* Read degree of first and second variable 
00727        (6)- degree (ND) */
00728 
00729     degree1 = coeffi[5];
00730     degree2 = coeffi[6];
00731     
00732     uves_msg_debug("Degree of 2D regression %s is (%d, %d)",
00733                    regression_name, degree1, degree2);
00734 
00735     /* The degree of the regression is now known. Next, read the coefficients */
00736 
00737     pol = cpl_polynomial_new(2);
00738 
00739     /* Search for <regression_name>D */
00740     found = false;
00741     for (i = 0; !found && i < plist_size; i++){
00742     const cpl_property *p = uves_propertylist_get_const(plist, i);
00743     const char *name = cpl_property_get_name(p);
00744     
00745     if (strcmp(name, "HISTORY") == 0) {
00746         const char *value;
00747         check( value = cpl_property_get_string(p),
00748            "Error reading property value");
00749         
00750         /* match the string  "'<regression_name>D'"  */
00751 
00752         if (
00753          
00754         (((index < 0) &&
00755         (int)strlen(value) >= 1+N+2 &&
00756              value[0]     == '\'' &&
00757              value[1+N]   == 'D' && 
00758          value[1+N+1] == '\'') 
00759 
00760                 || 
00761 
00762         ((index > 0) &&
00763         (int)strlen(value) >= 1+N+3 &&
00764              value[0]     == '\'' &&
00765              value[1+N]   == 'D' && 
00766              value[1+N+1] == cind && 
00767          value[1+N+2] == '\'') ) 
00768 
00769                  &&
00770  
00771         strncmp(value+1, regression_name, N) == 0
00772         ) {
00773         double coeff;
00774         char *next;
00775         int power[2];
00776         int j = i; /* points to the property currently being read */
00777 
00778         power[0] = 0;  /* Current degree */
00779         power[1] = 0;
00780 
00781         found = true;
00782         value = "dummy"; /* This will make strtod fail the first time */
00783         
00784         while (power[1] <= degree2){
00785             /* Read coefficient */
00786             coeff = strtod(value, &next);
00787             
00788             if (next != value) {
00789             /* A prefix of the string was successfully converted to double */
00790             cpl_polynomial_set_coeff(pol, power, coeff);
00791             uves_msg_debug("Polynomial coefficient of order (%d, %d) is %e", 
00792                        power[0], power[1], coeff);
00793             
00794             power[0]++;
00795             if (power[0] > degree1){
00796                 power[0] = 0;
00797                 power[1]++;
00798             }
00799             value = next;
00800             }
00801             else {
00802             /* No more doubles could be read from the string,
00803                so move to the next property in the plist */
00804             j = j + 1;
00805             
00806             assure(j < plist_size, CPL_ERROR_ILLEGAL_INPUT,
00807                    "Missing header data");
00808             
00809             p = uves_propertylist_get_const(plist, j);
00810             assure(       cpl_property_get_type(p)             == CPL_TYPE_STRING &&
00811                    strcmp(cpl_property_get_name(p), "HISTORY") == 0, 
00812                       CPL_ERROR_ILLEGAL_INPUT, "Error parsing polynomial");
00813             
00814             value = cpl_property_get_string(p);
00815 
00816             
00817             uves_msg_debug("Parsing string '%s'", value);
00818             }
00819         } /* Read coefficients */
00820         } /* string was "'...D'" */
00821     } /* Keyword was HISTORY */
00822     }/* for i... */
00823     
00824     assure( found, CPL_ERROR_ILLEGAL_INPUT, "Could not find '%sD' in property list", 
00825         regression_name);
00826 
00827     /* Create a new polynomial from the cpl_polynomial */
00828     result = uves_polynomial_new(pol);
00829     
00830   cleanup:
00831     uves_free_int(&coeffi);
00832     uves_free_string_const(&coeffi_name);
00833     uves_free_polynomial(&pol);
00834     if (cpl_error_get_code() != CPL_ERROR_NONE) 
00835     {
00836         uves_polynomial_delete(&result);
00837     }
00838 
00839     return result;
00840 }
00841 
00842 
00843 /*----------------------------------------------------------------------------*/
00850 /*----------------------------------------------------------------------------*/
00851 cpl_error_code
00852 uves_frameset_merge(cpl_frameset * set1, const cpl_frameset* set2)
00853 {
00854 
00855     const cpl_frame* frm_tmp=NULL;
00856     cpl_frame* frm_dup=NULL;
00857 
00858   passure(set1 != NULL, "Wrong input set");
00859   passure(set2 != NULL, "Wrong input set");
00860   
00861   for (frm_tmp = cpl_frameset_get_first_const(set2);
00862        frm_tmp != NULL;
00863        frm_tmp = cpl_frameset_get_next_const(set2))
00864       {
00865       frm_dup = cpl_frame_duplicate(frm_tmp);
00866       cpl_frameset_insert(set1, frm_dup);
00867       }
00868   
00869   cleanup:
00870   return cpl_error_get_code();
00871 }
00872 
00873 /*----------------------------------------------------------------------------*/
00881 /*----------------------------------------------------------------------------*/
00882 
00883 cpl_error_code
00884 uves_extract_frames_group_type(const cpl_frameset * set, cpl_frameset** ext, cpl_frame_group type)
00885 {
00886     const cpl_frame* frm_tmp=NULL;
00887   cpl_frame* frm_dup=NULL;
00888   cpl_frame_group g;
00889 
00890   check_nomsg(*ext = cpl_frameset_new());
00891   check_nomsg(frm_tmp = cpl_frameset_get_first_const(set));
00892   while (frm_tmp != NULL)
00893     {
00894       g=cpl_frame_get_group(frm_tmp);
00895       if(g == type) {
00896     frm_dup=cpl_frame_duplicate(frm_tmp);
00897         cpl_frameset_insert(*ext,frm_dup);
00898         uves_msg_debug("group %d insert file %s ",type,cpl_frame_get_filename(frm_dup));
00899       }
00900       frm_tmp = cpl_frameset_get_next_const(set);
00901     }
00902 
00903   cleanup:
00904     return cpl_error_get_code();
00905 }
00906 
00907 /*----------------------------------------------------------------------------*/
00915 /*----------------------------------------------------------------------------*/
00916 cpl_error_code
00917 uves_sflats_get_encoder_steps(const cpl_frameset * set, cpl_table** enc, int* nset)
00918 {
00919   /* Input */
00920     const cpl_frame* frm=NULL;
00921   int x1enc=0;
00922   int x2enc=0;
00923   int ref_x1enc=0;
00924   int ref_x2enc=0;
00925   int i=0;
00926   int ndata=0;
00927   const int threshold=5;
00928   int status=0;
00929   uves_propertylist* plist=NULL;
00930   cpl_table* encoder_tbl=NULL;
00931   ndata = cpl_frameset_get_size(set);
00932   encoder_tbl=cpl_table_new(ndata);
00933   cpl_table_new_column(encoder_tbl,"x1enc",CPL_TYPE_INT);
00934   cpl_table_new_column(encoder_tbl,"x2enc",CPL_TYPE_INT);
00935   cpl_table_new_column(encoder_tbl,"flag",CPL_TYPE_INT);
00936  
00937   for(i=0;i<cpl_frameset_get_size(set);i++)
00938     {
00939     check_nomsg(frm=cpl_frameset_get_frame_const(set,i));
00940     check_nomsg(plist=uves_propertylist_load(cpl_frame_get_filename(frm),0));
00941     check_nomsg(x1enc=uves_pfits_get_slit3_x1encoder(plist));
00942     check_nomsg(x2enc=uves_pfits_get_slit3_x2encoder(plist));
00943     check_nomsg(cpl_table_set_int(encoder_tbl,"x1enc",i,x1enc));
00944     check_nomsg(cpl_table_set_int(encoder_tbl,"x2enc",i,x2enc));
00945     uves_free_propertylist(&plist);
00946     }
00947  
00948   check_nomsg(uves_sort_table_2(encoder_tbl,"x1enc","x2enc",false,true));
00949 
00950   check_nomsg(ref_x1enc=cpl_table_get_int(encoder_tbl,"x1enc",0,&status));
00951   check_nomsg(ref_x2enc=cpl_table_get_int(encoder_tbl,"x2enc",0,&status));
00952   *nset=1;
00953   *enc=cpl_table_new(1);
00954   cpl_table_new_column(*enc,"x1enc",CPL_TYPE_INT);
00955   cpl_table_new_column(*enc,"x2enc",CPL_TYPE_INT);
00956   check_nomsg(cpl_table_set_int(*enc,"x1enc",0,ref_x1enc));
00957   check_nomsg(cpl_table_set_int(*enc,"x2enc",0,ref_x2enc));
00958 
00959   for(i=1;i<cpl_table_get_nrow(encoder_tbl);i++) {
00960      check_nomsg(x1enc=cpl_table_get_int(encoder_tbl,"x1enc",i,&status));
00961      check_nomsg(x2enc=cpl_table_get_int(encoder_tbl,"x2enc",i,&status));
00962      if( (fabs(ref_x1enc -x1enc) > threshold) || 
00963          (fabs(ref_x2enc -x2enc) > threshold) ) {
00964   
00965        ref_x1enc = x1enc;
00966        ref_x2enc = x2enc;
00967        cpl_table_set_size(*enc,(*nset+1));
00968        check_nomsg(cpl_table_set_int(*enc,"x1enc",*nset,ref_x1enc));
00969        check_nomsg(cpl_table_set_int(*enc,"x2enc",*nset,ref_x2enc));
00970        *nset=*nset+1;
00971 
00972      }
00973   }
00974   uves_msg("Number of sets = %d",*nset);
00975 
00976   cleanup:
00977    uves_free_table(&encoder_tbl);
00978     uves_free_propertylist(&plist);
00979     return cpl_error_get_code();
00980 }
00981 
00982 
00983 /*----------------------------------------------------------------------------*/
00989 /*----------------------------------------------------------------------------*/
00990 cpl_error_code
00991 uves_dfs_set_groups(cpl_frameset * set)
00992 {
00993     cpl_frame   *   cur_frame ;
00994     int             nframes ;
00995     
00996     /* Check entries */
00997     assure(set != NULL, CPL_ERROR_NULL_INPUT, "Null input"); 
00998     
00999     /* Initialize */
01000     check( nframes = cpl_frameset_get_size(set), "Could not read frameset size");
01001     
01002     /* Loop on frames */
01003     for (cur_frame = cpl_frameset_get_first(set);
01004      cur_frame != NULL;
01005      cur_frame = cpl_frameset_get_next(set))
01006     {
01007         bool is_raw   = false;
01008         bool is_calib = false;
01009         bool is_recognized = false;
01010         bool blue;
01011         enum uves_chip chip;
01012         const char  *   tag = cpl_frame_get_tag(cur_frame);
01013         
01014         assure( tag != NULL && strcmp(tag, "") != 0, CPL_ERROR_ILLEGAL_INPUT,
01015             "Frame has no tag!");
01016         
01017         blue = false;
01018         do {
01019         bool flames = false;
01020         do {
01021             /* RAW frames */
01022             is_raw   = is_raw   || 
01023             (strcmp(tag, UVES_ORDER_FLAT  (flames,blue)) == 0 ||
01024              strcmp(tag, UVES_BIAS        (blue)) == 0 ||
01025              strcmp(tag, UVES_DARK        (blue)) == 0 ||
01026              strcmp(tag, UVES_PDARK       (blue)) == 0 ||
01027              strcmp(tag, UVES_FLAT        (blue)) == 0 ||
01028              strcmp(tag, UVES_IFLAT       (blue)) == 0 ||
01029              strcmp(tag, UVES_DFLAT       (blue)) == 0 ||
01030              strcmp(tag, UVES_SFLAT       (blue)) == 0 ||
01031              strcmp(tag, UVES_TFLAT       (blue)) == 0 ||
01032              strcmp(tag, UVES_SCREEN_FLAT (blue)) == 0 ||
01033              strcmp(tag, UVES_CD_ALIGN    (blue)) == 0 ||
01034              strcmp(tag, UVES_FORMATCHECK (flames,blue)) == 0 ||
01035              strcmp(tag, UVES_STD_STAR    (blue)) == 0 ||
01036              strcmp(tag, UVES_SCIENCE     (blue)) == 0 ||
01037              strcmp(tag, UVES_SCI_EXTND   (blue)) == 0 ||
01038              strcmp(tag, UVES_SCI_POINT   (blue)) == 0 ||
01039              strcmp(tag, UVES_SCI_SLICER  (blue)) == 0 ||
01040              strcmp(tag, UVES_ARC_LAMP    (flames,blue)) == 0 ||
01041              strcmp(tag, UVES_ECH_ARC_LAMP(blue)) == 0 ||
01042              strcmp(tag, FLAMES_SCI_RED) == 0 ||
01043              strcmp(tag, FLAMES_SCI_SIM_RED) == 0 ||
01044              strcmp(tag, FLAMES_SCI_COM_RED) == 0 ||
01045              strcmp(tag, FLAMES_FIB_FF_ODD) == 0 ||
01046              strcmp(tag, FLAMES_FIB_FF_EVEN) == 0 ||
01047              strcmp(tag, FLAMES_FIB_FF_ALL) == 0);
01048             
01049             /* CALIB frames */
01050             
01051             /* Loop through all (1 or 2) blue or red chips */
01052             for (chip = uves_chip_get_first(blue);
01053              chip != UVES_CHIP_INVALID; 
01054              chip = uves_chip_get_next(chip))
01055             {
01056                 int window;
01057                 
01058                 is_calib = is_calib || 
01059                 (strcmp(tag, UVES_DRS_SETUP(flames, chip)) == 0 ||
01060                  strcmp(tag, UVES_ORDER_TABLE(flames, chip)) == 0 ||
01061                  strcmp(tag, UVES_GUESS_ORDER_TABLE(flames,chip)) == 0 ||
01062                  strcmp(tag, UVES_MASTER_BIAS   (chip)) == 0 ||
01063                  strcmp(tag, UVES_MASTER_DARK   (chip)) == 0 ||
01064                  strcmp(tag, UVES_MASTER_PDARK  (chip)) == 0 ||
01065                  strcmp(tag, UVES_MASTER_FLAT   (chip)) == 0 ||
01066                  strcmp(tag, UVES_MASTER_DFLAT  (chip)) == 0 ||
01067                  strcmp(tag, UVES_MASTER_SFLAT  (chip)) == 0 ||
01068                  strcmp(tag, UVES_MASTER_IFLAT  (chip)) == 0 ||
01069                  strcmp(tag, UVES_MASTER_TFLAT  (chip)) == 0 ||
01070                  strcmp(tag, UVES_REF_TFLAT     (chip)) == 0 ||
01071                  strcmp(tag, UVES_MASTER_SCREEN_FLAT(chip)) == 0 ||
01072                  strcmp(tag, UVES_MASTER_ARC_FORM(chip)) == 0 ||
01073                  strcmp(tag, UVES_WEIGHTS(chip))        == 0 ||
01074                  strcmp(tag, UVES_LINE_TABLE(flames,chip)) == 0 ||
01075                  strcmp(tag, UVES_GUESS_LINE_TABLE(flames,chip)) == 0 ||
01076                  strcmp(tag, UVES_INSTR_RESPONSE(chip)) == 0 ||
01077                  strcmp(tag, UVES_MASTER_RESPONSE(chip)) == 0 ||
01078                  strcmp(tag, UVES_LINE_REFER_TABLE    ) == 0 ||
01079                  strcmp(tag, UVES_LINE_INTMON_TABLE   ) == 0 ||
01080                  strcmp(tag, UVES_FLUX_STD_TABLE      ) == 0 ||
01081                  strcmp(tag, UVES_EXTCOEFF_TABLE      ) == 0 ||
01082                  strcmp(tag, FLAMES_LINE_TABLE(chip)) == 0 ||
01083                  strcmp(tag, FLAMES_SLIT_FF_DT1(chip)) == 0 ||
01084                  strcmp(tag, FLAMES_SLIT_FF_DT2(chip)) == 0 ||
01085                  strcmp(tag, FLAMES_SLIT_FF_DT3(chip)) == 0 ||
01086                  strcmp(tag, FLAMES_SLIT_FF_DTC(chip)) == 0 ||
01087                  strcmp(tag, FLAMES_SLIT_FF_BP1(chip)) == 0 ||
01088                  strcmp(tag, FLAMES_SLIT_FF_BP2(chip)) == 0 ||
01089                  strcmp(tag, FLAMES_SLIT_FF_BP3(chip)) == 0 ||
01090                  strcmp(tag, FLAMES_SLIT_FF_BPC(chip)) == 0 ||
01091                  strcmp(tag, FLAMES_SLIT_FF_BN1(chip)) == 0 ||
01092                  strcmp(tag, FLAMES_SLIT_FF_BN2(chip)) == 0 ||
01093                  strcmp(tag, FLAMES_SLIT_FF_BN3(chip)) == 0 ||
01094                  strcmp(tag, FLAMES_SLIT_FF_BNC(chip)) == 0 ||
01095                  strcmp(tag, FLAMES_SLIT_FF_SG1(chip)) == 0 ||
01096                  strcmp(tag, FLAMES_SLIT_FF_SG2(chip)) == 0 ||
01097                  strcmp(tag, FLAMES_SLIT_FF_SG3(chip)) == 0 ||
01098                  strcmp(tag, FLAMES_SLIT_FF_SGC(chip)) == 0 ||
01099                  strcmp(tag, FLAMES_SLIT_FF_COM(chip)) == 0 ||
01100                  strcmp(tag, FLAMES_SLIT_FF_NOR(chip)) == 0 ||
01101                  strcmp(tag, FLAMES_SLIT_FF_NSG(chip)) == 0 ||
01102                  strcmp(tag, FLAMES_FIB_FF_DT1(chip)) == 0 ||
01103                  strcmp(tag, FLAMES_FIB_FF_DT2(chip)) == 0 ||
01104                  strcmp(tag, FLAMES_FIB_FF_DT3(chip)) == 0 ||
01105                  strcmp(tag, FLAMES_FIB_FF_DTC(chip)) == 0 ||
01106                  strcmp(tag, FLAMES_FIB_FF_BP1(chip)) == 0 ||
01107                  strcmp(tag, FLAMES_FIB_FF_BP2(chip)) == 0 ||
01108                  strcmp(tag, FLAMES_FIB_FF_BP3(chip)) == 0 ||
01109                  strcmp(tag, FLAMES_FIB_FF_BPC(chip)) == 0 ||
01110                  strcmp(tag, FLAMES_FIB_FF_BN1(chip)) == 0 ||
01111                  strcmp(tag, FLAMES_FIB_FF_BN2(chip)) == 0 ||
01112                  strcmp(tag, FLAMES_FIB_FF_BN3(chip)) == 0 ||
01113                  strcmp(tag, FLAMES_FIB_FF_BNC(chip)) == 0 ||
01114                  strcmp(tag, FLAMES_FIB_FF_SG1(chip)) == 0 ||
01115                  strcmp(tag, FLAMES_FIB_FF_SG2(chip)) == 0 ||
01116                  strcmp(tag, FLAMES_FIB_FF_SG3(chip)) == 0 ||
01117                  strcmp(tag, FLAMES_FIB_FF_SGC(chip)) == 0 ||
01118                  strcmp(tag, FLAMES_FIB_FF_COM(chip)) == 0 ||
01119                  strcmp(tag, FLAMES_FIB_FF_NOR(chip)) == 0 ||
01120                  strcmp(tag, FLAMES_FIB_FF_NSG(chip)) == 0 ||
01121                  strcmp(tag, FLAMES_ORDEF(flames,chip)) == 0 ||
01122                  strcmp(tag, FLAMES_CORVEL_MASK) == 0);
01123                 
01124                 for (window = 1; window <= 3; window++)
01125                 {
01126                     is_calib = is_calib || 
01127                     strcmp(tag, UVES_LINE_TABLE_MIDAS(chip, window)) == 0;
01128                 }
01129                 
01130                 if (!flames && strcmp(tag, UVES_BACKGR_TABLE(chip)) == 0)
01131                 {
01132                     uves_msg_warning("Background table %s has been deprecated. "
01133                              "Inter-order positions will be inferred "
01134                              "from the order table %s. "
01135                              "Use recipe parameters to define "
01136                              "measuring method ",
01137                              UVES_BACKGR_TABLE(chip), 
01138                              UVES_ORDER_TABLE(flames, chip));
01139                     
01140                     is_recognized = true;
01141                 }
01142                 
01143                 if (strcmp(tag, UVES_DRS_SETUP(flames, chip)) == 0)
01144                 {
01145                     uves_msg_warning("DRS setup table %s has been deprecated. "
01146                              "Use recipe parameters "
01147                              "to define data reduction parameters ",
01148                              UVES_DRS_SETUP(flames, chip));
01149                     
01150                     is_recognized = true;
01151                 }
01152             }
01153             flames = !flames;
01154         } while (flames);
01155         blue = !blue;
01156         }
01157         while (blue);
01158         
01159         is_recognized = is_recognized || is_raw || is_calib;
01160 
01161         if (is_raw)
01162         {
01163             cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW) ;
01164         }
01165         else if (is_calib)
01166         {
01167             cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_CALIB) ;
01168         }
01169         else if (!is_recognized)
01170         {
01171             uves_msg_warning("Unrecognized tag %s", tag);
01172         }
01173     }
01174     
01175   cleanup:
01176     return cpl_error_get_code();
01177 }
01178 
01179 
01180 /*----------------------------------------------------------------------------*/
01189 /*----------------------------------------------------------------------------*/
01190 static void
01191 remove_pre_over_scan(uves_propertylist *pl)
01192 {
01193     bool blue, new_format;
01194     enum uves_chip chip;
01195     
01196     new_format = false;
01197     do {
01198     blue = false;
01199     do {
01200         for (chip = uves_chip_get_first(blue); 
01201          chip != UVES_CHIP_INVALID;
01202          chip = uves_chip_get_next(chip))
01203         {
01204             int n_erase_px = 0;   /* Number of erased properties */
01205             int n_erase_py = 0;
01206             int n_erase_ox = 0;
01207             int n_erase_oy = 0;
01208             
01209             do {
01210             /* This function erases only one property at a time,
01211              *  therefore call it until it returns 0
01212              */
01213             check( n_erase_px = 
01214                    uves_propertylist_erase(pl, UVES_PRESCANX(new_format, chip)),
01215                    "Error erasing keyword '%s'", UVES_PRESCANX(new_format, chip));
01216             
01217             check( n_erase_py = 
01218                    uves_propertylist_erase(pl, UVES_PRESCANY(new_format, chip)),
01219                    "Error erasing keyword '%s'", UVES_PRESCANY(new_format, chip));
01220             
01221             check( n_erase_ox =
01222                    uves_propertylist_erase(pl, UVES_OVRSCANX(new_format, chip)),
01223                    "Error erasing keyword '%s'", UVES_OVRSCANX(new_format, chip));
01224             
01225             check( n_erase_oy =
01226                    uves_propertylist_erase(pl, UVES_OVRSCANY(new_format, chip)),
01227                    "Error erasing keyword '%s'", UVES_OVRSCANY(new_format, chip));
01228             }
01229             while (n_erase_px > 0 ||
01230                n_erase_py > 0 ||
01231                n_erase_ox > 0 ||
01232                n_erase_oy > 0);
01233         }
01234         blue = !blue;
01235     }
01236     while (blue);
01237     
01238     new_format = !new_format;
01239     }
01240     while (new_format);
01241 
01242   cleanup:
01243     return;
01244 }
01245 
01246 
01247 /*----------------------------------------------------------------------------*/
01257 /*----------------------------------------------------------------------------*/
01258 
01259 void
01260 uves_copy_if_possible(uves_propertylist *to, const uves_propertylist *from,
01261          const char *name)
01262 {
01263     if (!uves_propertylist_contains(to, name) &&
01264     uves_propertylist_contains(from, name))
01265     {
01266         uves_msg_debug("Propagating keyword %s", name);
01267 
01268         check_nomsg( uves_propertylist_copy_property(to, from, name) );
01269     }
01270     else
01271     {
01272         uves_msg_debug("Keyword %s not propagated", name);
01273     }
01274     
01275   cleanup:
01276     return;
01277 }
01278 
01279 /*----------------------------------------------------------------------------*/
01323 /*----------------------------------------------------------------------------*/
01324 cpl_error_code
01325 uves_frameset_insert(cpl_frameset *frames, 
01326                      void *object, 
01327                      cpl_frame_group group, 
01328                      cpl_frame_type type, 
01329                      cpl_frame_level level,
01330                      const char *filename, 
01331                      const char *tag, 
01332                      const uves_propertylist *raw_header,
01333                      const uves_propertylist *primary_header, 
01334                      const uves_propertylist *table_header, 
01335                      const cpl_parameterlist *parameters, 
01336                      const char *recipe, 
01337                      const char *pipeline,
01338                      cpl_table **qc,
01339                      const char *start_time,
01340                      bool dump_paf,
01341                      unsigned stats_mask)
01342 {
01343     cpl_frame *f = NULL;
01344     uves_propertylist *pl = NULL;
01345     const char *origin = "";
01346 
01347     passure( !(type == CPL_FRAME_TYPE_IMAGE && table_header != NULL), " ");
01348     passure( raw_header != NULL, " ");
01349     passure( primary_header != NULL, " ");
01350 
01351     assure( type == CPL_FRAME_TYPE_IMAGE || stats_mask == 0,
01352         CPL_ERROR_INCOMPATIBLE_INPUT,
01353         "Cannot compute image statistics on table product" );
01354 
01355     /* Insert the object (image or table) into frameset */
01356     check(( f = cpl_frame_new(),
01357             cpl_frame_set_filename(f, filename),    /* local filename */
01358             cpl_frame_set_tag     (f, tag),         /* e.g. ORDER_TABLE_BLUE */
01359             cpl_frame_set_type    (f, type),        /* e.g. table */
01360             cpl_frame_set_group   (f, group),       /* e.g. raw/product */
01361             cpl_frame_set_level   (f, level),       /* e.g. temporary/final */
01362             cpl_frameset_insert(frames, f)), "Could not insert frame into frameset");
01363     
01364     /* Pipeline id format is <PACKAGE "/" PACKAGE_VERSION>; */
01365     if (strchr(pipeline, '/') == NULL)
01366     {
01367         uves_msg_warning("Pipeline ID '%s' is not of format: "
01368                  "Pipeline-name/version", pipeline);
01369     }
01370 
01371     /* Copy provided keywords in 'primary_header' to 'pl' */
01372     pl = uves_propertylist_new();
01373     if (!uves_propertylist_is_empty(primary_header))
01374     {
01375         if (0)
01376                 /* This takes (n*m) time */
01377                 {
01378                     /* The regexp "" matches any string (because any string has
01379                        the empty string as a sub-string),
01380                        except on Mac, where it is an illegal regexp (for whatever reason).
01381                        Therefore, use ".*" to match any string */
01382                     
01383                     check( uves_propertylist_copy_property_regexp(pl, primary_header, ".*", 0),
01384                            "Could not copy keywords");
01385                 }
01386             else
01387                 check( uves_propertylist_append(pl, primary_header),
01388                        "Could not copy keywords");
01389     }
01390     
01391     /* Propagate/create DFS keywords */
01392     UVES_TIME_START("cpl_dfs_setup_product_header");
01393     check( uves_dfs_setup_product_header(pl,
01394                     f,
01395                     frames,
01396                     parameters,
01397                     recipe,
01398                     pipeline,
01399                     DICTIONARY),
01400        "Error setting up product header");
01401     UVES_TIME_END;
01402     
01403     /* Change origin to 'ESO' if it says 'ESO-MIDAS'
01404      * NOST-Definition: "The value field shall contain a character string
01405      *                   identifying the organization or institution responsible 
01406      *                   for creating the FITS file."
01407      */
01408     
01409     check( uves_get_property_value(pl, "ORIGIN", CPL_TYPE_STRING, &origin),
01410        "Error reading ORIGIN from product header");
01411 
01412     if (strcmp(origin, "ESO-MIDAS") == 0) 
01413     {
01414         uves_propertylist_set_string(pl, "ORIGIN", "ESO");
01415     }
01416     
01417     /* Set OBJECT = DO category */
01418     check( uves_pfits_set_object(pl, tag), "Error writing object keyword");
01419         
01420     /* Add statistics keywords */
01421     if (type == CPL_FRAME_TYPE_IMAGE && stats_mask != 0)
01422     {
01423         check( uves_dfs_write_statistics((cpl_image *) object, pl, stats_mask),
01424            "Error adding image statistics keywords");
01425     }
01426     
01427     /* Propagate ESO.DET keywords from 'raw_header',
01428      * This is necessary because cpl_dfs_setup_product_header() copies
01429      * only from the primary extension of the first input frames
01430      */
01431     check( uves_propertylist_copy_property_regexp(pl, raw_header, "^ESO DET ", 0),
01432        "Could not propagate 'ESO DET*' keywords");
01433 
01434     /* But remove prescan, overscan keywords. 
01435        (Since these areas are not present in any products.) */
01436     check( remove_pre_over_scan(pl), 
01437        "Error removing pre-, overscan keywords from product header");
01438 
01439     /* Propagate certain keywords from 'raw_header' 
01440        (only if available and if not already present in product header) */
01441     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_AIRMASS) );
01442     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_IMAGETYP) );
01443     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_UT) );
01444     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_ST) );
01445     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_EXPTIME) );
01446     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_EXTNAME) );
01447     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_DATE) );
01448     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_DATAMEAN) );
01449     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_DATAMED) );
01450     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_DATARMS) );
01451     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_OS_EXPOI) );
01452 
01453     /* MIDAS internal(?): check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_TMSTART) ); */
01454 
01455     if (0)
01456         /* uves_propertylist_copy_property_regexp() is slow */
01457         {
01458             check( uves_propertylist_copy_property_regexp(pl, raw_header, "^GRAT[0-9]*$", 0),
01459                    "Could not propagate 'GRATi' keywords");
01460             check( uves_propertylist_copy_property_regexp(pl, raw_header, "^FILTER[0-9]*$", 0),
01461                    "Could not propagate 'FILTERi' keywords");
01462             check( uves_propertylist_copy_property_regexp(pl, raw_header, "^WLEN[0-9]*$", 0),
01463                    "Could not propagate 'WLENi' keywords");
01464         }
01465     else
01466         {
01467             check( uves_propertylist_copy_property_regexp(
01468                        pl, raw_header, "^((GRAT|FILTER|WLEN)[0-9]*)$", 0),
01469                    "Could not propagate GRATi, FILTERi and WLENi keywords");
01470         }
01471 
01472     /* If RA,DEC do not exist, invent them and set to zero, like MIDAS */
01473     if ( !uves_propertylist_contains(pl, UVES_RA) )
01474     {
01475         uves_pfits_set_ra(pl, 0);
01476     }
01477     if ( !uves_propertylist_contains(pl, UVES_DEC) )
01478     {
01479         uves_pfits_set_dec(pl, 0);
01480     }
01481 
01482     /* 
01483      * REDLEVEL and STATUS have been deprecated, so delete them
01484      * along with inherited MIDAS specific keywords
01485      */
01486     {
01487         bool invert = false;
01488         uves_propertylist_erase_regexp(pl, "^("
01489                                        "ESO PRO (REDLEVEL|REC[0-9]+ STATUS)|"
01490                                        "TM-START|MIDASFTP|FILENAME)$", invert);
01491     }
01492 
01493     check( uves_pfits_set_starttime(pl, start_time),
01494        "Could not write recipe start time");
01495 
01496     check( uves_pfits_set_stoptime(pl, qfits_get_datetime_iso8601()),
01497        "Could not write recipe stop time");
01498 
01499     /* Create paf file from each QC table, and transfer
01500        all QC parameters to product header
01501     */
01502     if (qc != NULL)
01503     {
01504         int i;
01505         for (i = 0; qc[i] != NULL; i++)
01506         {
01507             uves_pfits_put_qc(pl, qc[i]);
01508                         
01509             if (dump_paf)
01510             {
01511                 /* Exception! This is a hack */
01512                 if (strcmp(recipe, make_str(UVES_TFLAT_ID)) == 0 && i == 1)
01513                 {
01514                     /* Don't dump the science QC again */
01515                 }
01516                 else
01517                 {
01518                     uves_save_paf(filename, i, recipe, qc[i], 
01519                           pl, raw_header, tag);
01520                 }
01521             }
01522         } 
01523     }
01524 
01525     UVES_TIME_START("save product");
01526 
01527     /* Now save with the correct header */
01528     if (type == CPL_FRAME_TYPE_IMAGE)
01529     {
01530         bool use_bitpix16_for_int = (strcmp(recipe, make_str(FLAMES_CAL_ORDERPOS)) == 0);
01531         
01532         check( uves_save_image((cpl_image *) object, filename, pl, 
01533                                use_bitpix16_for_int, true), 
01534            "Error saving image to file %s", filename);
01535     }
01536     else if (type == CPL_FRAME_TYPE_TABLE)                           /* Table */
01537     {
01538         check( uves_table_save((cpl_table *) object,
01539                   pl,                                /* Primary header */
01540                   table_header,                      /* Table header */
01541                   filename,
01542                   CPL_IO_DEFAULT),                   /* Create new file */
01543            "Error saving table to file '%s'", filename);
01544     }
01545     else
01546     {
01547         assure(false, CPL_ERROR_UNSUPPORTED_MODE, "Unsupported frame type");
01548     }
01549 
01550     UVES_TIME_END;
01551     
01552   cleanup:
01553     uves_free_propertylist(&pl);
01554     
01555     return cpl_error_get_code();
01556 }
01557 
01558 
01559 /*----------------------------------------------------------------------------*/
01568 /*----------------------------------------------------------------------------*/
01569 void
01570 uves_dfs_write_statistics(const cpl_image *image, uves_propertylist *header,
01571          unsigned stats_mask)
01572 {
01573     cpl_stats *stats = NULL;
01574 
01575     /* Only these bits are supported, all others must be zero */
01576     assure( (stats_mask & (CPL_STATS_MEAN | CPL_STATS_STDEV | CPL_STATS_MEDIAN |
01577               CPL_STATS_MIN  | CPL_STATS_MAX)) == stats_mask,
01578         CPL_ERROR_UNSUPPORTED_MODE, "Cannot compute mask %d",
01579         stats_mask );
01580 
01581     UVES_TIME_START("calculate stats");
01582 
01583     check( stats = cpl_stats_new_from_image(
01584            image, stats_mask),
01585        "Error reading image statistics");
01586     
01587     UVES_TIME_END;
01588     
01589     if (stats_mask & CPL_STATS_MEDIAN)
01590     {
01591         check( uves_pfits_set_data_median (header, cpl_stats_get_median(stats) ), 
01592            "Could not write median flux");
01593     }
01594     if (stats_mask & CPL_STATS_MEAN)
01595     {
01596         check( uves_pfits_set_data_average(header, cpl_stats_get_mean  (stats) ), 
01597            "Could not write average flux");
01598     }
01599     if (stats_mask & CPL_STATS_STDEV)
01600     {
01601         check( uves_pfits_set_data_stddev (header, cpl_stats_get_stdev (stats) ), 
01602            "Could not write flux stdev");
01603     }
01604     if (stats_mask & CPL_STATS_MIN)
01605     {
01606         check( uves_pfits_set_data_min    (header, cpl_stats_get_min   (stats) ), 
01607            "Could not write min flux");
01608     }
01609     if (stats_mask & CPL_STATS_MIN)
01610     {
01611         check( uves_pfits_set_data_max    (header, cpl_stats_get_max   (stats) ), 
01612            "Could not write max flux");
01613     }
01614 
01615   cleanup:
01616     uves_free_stats(&stats);
01617     return;
01618 }
01619 
01620 
01621 /*----------------------------------------------------------------------------*/
01656 /*----------------------------------------------------------------------------*/
01657 void *
01658 uves_read_midas_array(const uves_propertylist *plist, const char *name, 
01659                       int *length, cpl_type *type, int *ncards)
01660 {
01661     void *result = NULL;
01662     unsigned result_size;
01663     int N = strlen(name);
01664     bool found = false;
01665     const char *value;
01666     int size;
01667     int i;
01668     const long int plist_size = uves_propertylist_get_size(plist);
01669    
01670     assure_nomsg( length != NULL, CPL_ERROR_NULL_INPUT );
01671     assure_nomsg(   type != NULL, CPL_ERROR_NULL_INPUT );
01672     for (i = 0; !found && i < plist_size; i++)
01673     {
01674       const cpl_property *p = uves_propertylist_get_const(plist, i);
01675       value = cpl_property_get_name(p);
01676       
01677       if (strcmp(value, "HISTORY") == 0)
01678         {
01679           
01680           check( value = cpl_property_get_string(p),
01681          "Error reading property value");
01682           
01683           /* match the string  "'<name>','t"  */
01684           
01685           if ((int)strlen(value) >= 1+N+4 &&
01686           value[0]     == '\'' &&
01687           value[N+1]   == '\'' && 
01688           value[N+2]   == ','  && 
01689           value[N+3]   == '\'' && 
01690           strncmp(value+1, name, N) == 0
01691           )
01692         { 
01693           switch(value[N+4]) {
01694           case 'R':
01695         /* Distinguish between 
01696            "'<name>','R*4'" and
01697            "'<name>','R*8'"
01698         */
01699         *type = CPL_TYPE_DOUBLE;
01700 
01701         if ((int)strlen(value) >= 1+N+4+2 && value[N+4+1] == '*')
01702           {
01703             switch(value[N+4+2]) {
01704             case '4': *type = CPL_TYPE_FLOAT; break;
01705             case '8': *type = CPL_TYPE_DOUBLE; break; 
01706             default:
01707               assure( false, CPL_ERROR_ILLEGAL_INPUT,
01708                   "Unrecognized MIDAS type: 'R*%c'",
01709                   value[N+4+2]);
01710               break;
01711             }
01712           }
01713         break;
01714           case 'I': *type = CPL_TYPE_INT   ; size = sizeof(int);    break;
01715           case 'C': *type = CPL_TYPE_STRING; size = sizeof(char);   break;
01716           default:
01717         assure( false, CPL_ERROR_UNSUPPORTED_MODE,
01718             "Unrecognized type '%c'", value[N+4]);
01719         break;
01720           }
01721           found = true;
01722         }
01723         }
01724     }
01725     
01726     assure( found, CPL_ERROR_ILLEGAL_INPUT, "Could not find '%s' in property list", name);
01727     
01728     /* 'i' is now the row immediately after first occurence of 'HISTORY   '<name>...  */
01729     result_size = sizeof(double) * 100;  /* realloc when/if out of memory */
01730     result = cpl_malloc(result_size);
01731 
01732     *length = 0;
01733     if (ncards != NULL) *ncards = 2; /* First HISTORY entry + termination HISTORY entry */
01734     do {
01735       const cpl_property *p;
01736 
01737       if (ncards != NULL) *ncards += 1;
01738 
01739       assure(i < plist_size, 
01740          CPL_ERROR_ILLEGAL_INPUT, "Missing header data");
01741       p = uves_propertylist_get_const(plist, i);
01742       assure(       cpl_property_get_type(p)             == CPL_TYPE_STRING &&
01743             strcmp(cpl_property_get_name(p), "HISTORY") == 0, 
01744             CPL_ERROR_ILLEGAL_INPUT, "Error parsing array");
01745       value = cpl_property_get_string(uves_propertylist_get_const(plist, i));
01746     
01747       uves_msg_debug("Parsing '%s'", value);
01748 
01749       if (*type == CPL_TYPE_STRING)
01750     {
01751       assure( strlen(value) < 100, CPL_ERROR_UNSUPPORTED_MODE, 
01752           "String too long. Max size is 100");
01753 
01754       /* Remove any blanks from the string
01755          (e.g. convert "0 1 2" to "012")
01756       */
01757       {
01758         int len = strlen(value);
01759         int j = 0;
01760         int k;
01761         for (k = 0; k <= len; k++)  /* including final '\0' */
01762           {
01763         //if (value[k] != ' '){
01764         ((char*)result)[j] = value[k];
01765         j++;
01766         //      }
01767           }
01768         *length = j-1;
01769       }
01770 
01771       uves_msg_debug("Converted '%s' to '%s'",
01772              value, (char*)result);
01773                 
01774       /* done parsing */
01775       value = "";
01776     }
01777         
01778       else { /* numerical types */
01779     if (strcmp(value, "") != 0) {
01780       double numberd = -1; /* suppres warning */
01781       int numberi = -1;
01782       float numberf = -1;
01783       const int base = 10;
01784       char *next = (char *) value;
01785 
01786       do {
01787             /* ignore OUTPUTI(1)- N,no.of data, */
01788         switch(*type) {
01789         case CPL_TYPE_DOUBLE:
01790           numberd = strtod(value, &next);
01791           uves_msg_debug("Got %g, remaining: '%s'", numberd, next);
01792           break;
01793         case CPL_TYPE_FLOAT:
01794           numberf = strtod(value, &next); // C99: strtof(value, &next);
01795           uves_msg_debug("Got %g, remaining: '%s'", numberf, next);
01796           break;
01797         case CPL_TYPE_INT:
01798           numberi = strtol(value, &next, base);
01799           uves_msg_debug("Got %d, remaining: '%s'", numberi, next);
01800           break;
01801         default:
01802           passure(false, " ");
01803         }
01804                     
01805             if (next != value)
01806           {
01807                 /* A prefix of the string could be converted */
01808                 (*length)++;
01809         if (*length * sizeof(double) > result_size)
01810           {
01811             result_size *= 2;
01812             result = cpl_realloc(result, result_size);
01813           }
01814 
01815         switch(*type) {
01816         case CPL_TYPE_DOUBLE:
01817           ((double *)result)[*length-1] = numberd;
01818           break;
01819         case CPL_TYPE_FLOAT:
01820           ((float *)result)[*length-1] = numberf;
01821           break;
01822         case CPL_TYPE_INT:
01823           ((int    *)result)[*length-1] = numberi;
01824           break;
01825         default:
01826           passure(false, " ");
01827         }
01828 
01829                 value = next;
01830                             
01831         switch(*type) {
01832         case CPL_TYPE_DOUBLE:
01833           numberd = strtod(value, &next);
01834           uves_msg_debug("Got %g, remaining: '%s'", numberd, next);
01835           break;
01836         case CPL_TYPE_FLOAT:
01837           numberf = strtod(value, &next); // C99: strtof(value, &next);
01838           uves_msg_debug("Got %g, remaining: '%s'", numberf, next);
01839           break;
01840         case CPL_TYPE_INT:
01841           numberi = strtol(value, &next, base);
01842           uves_msg_debug("Got %d, remaining: '%s'", numberi, next);
01843           break;
01844         default:
01845           passure(false, " ");
01846         }
01847           }
01848       } while (next != value);
01849         }
01850       }/* if numerical type */
01851         
01852       i++;
01853 
01854       assure( strcmp(value, "") == 0, CPL_ERROR_ILLEGAL_INPUT,
01855           "Cannot parse %s descriptor %s, remaining string: '%s'", 
01856           uves_tostring_cpl_type(*type), name, value);
01857     
01858       /* Find out if we can continue parsing the next HISTORY keyword */
01859       if (i < plist_size)
01860         {
01861       p = uves_propertylist_get_const(plist, i);
01862       if (cpl_property_get_type(p) == CPL_TYPE_STRING &&
01863           strcmp(cpl_property_get_name(p), "HISTORY") == 0)
01864             {
01865           value = cpl_property_get_string(
01866                           uves_propertylist_get_const(plist, i));
01867 
01868           if (*type == CPL_TYPE_STRING)
01869         {
01870           if (strcmp(value, "") != 0) {
01871             uves_msg_debug("String array %s with length > 1 found. Ignoring remaining values", name);
01872             while (strcmp(value, "") != 0 && i+1 < plist_size) {
01873               i++;
01874               p = uves_propertylist_get_const(plist, i);
01875               value = cpl_property_get_string(
01876                               uves_propertylist_get_const(plist, i));
01877               if (ncards != NULL) *ncards += 1;
01878             }
01879           }
01880         }
01881         }
01882     }
01883       
01884     } while (strcmp(value, "") != 0);
01885     
01886  cleanup:
01887     if (cpl_error_get_code() != CPL_ERROR_NONE)
01888       {
01889     cpl_free(result); result = NULL;
01890       }
01891     return result;
01892 }
01893 
01894 
01895 /*----------------------------------------------------------------------------*/
01913 /*----------------------------------------------------------------------------*/
01914 cpl_error_code
01915 uves_save_table_local(const char *description, const char *filename_prefix,
01916               const cpl_table *table, 
01917               enum uves_chip chip, int trace, int window,
01918               const uves_propertylist *pheader, const uves_propertylist *eheader)
01919 {
01920     char *filename = NULL;
01921 
01922     check( filename = uves_local_filename(filename_prefix, chip, trace, window),
01923        "Error getting filename");
01924 
01925     check( uves_table_save(table, pheader, eheader, filename, CPL_IO_DEFAULT), 
01926        "Error saving table to file '%s'", filename);
01927     
01928     if (description != NULL) uves_msg("%s saved to '%s'", description, filename);
01929     
01930   cleanup:
01931     cpl_free(filename);
01932     return cpl_error_get_code();
01933 }
01934 
01935 /*----------------------------------------------------------------------------*/
01956 /*----------------------------------------------------------------------------*/
01957 cpl_error_code
01958 uves_save_image_local(const char *description, const char *filename_prefix, 
01959                       const cpl_image *image, 
01960                       enum uves_chip chip, int trace, int window,
01961                       const uves_propertylist *plist,
01962                       bool use_bitpix16_for_int)
01963 {
01964     char *filename = NULL;
01965     
01966     check( filename = uves_local_filename(filename_prefix, chip, trace, window),
01967        "Error getting filename");
01968     
01969     check( uves_save_image(image, filename, plist, use_bitpix16_for_int, true),
01970            "Error saving image to file '%s'", filename);
01971     if (description != NULL) uves_msg("%s saved to '%s'", description, filename);
01972     
01973   cleanup:
01974     cpl_free(filename);
01975     return cpl_error_get_code();
01976 }
01977 
01978 
01979 /*----------------------------------------------------------------------------*/
01989 /*----------------------------------------------------------------------------*/
01990 cpl_image *uves_load_image(const cpl_frame *f,
01991                int plane,
01992                int extension,
01993                uves_propertylist **header)
01994 {
01995     cpl_image *image = NULL;
01996     uves_propertylist *plist = NULL;
01997     const char *filename;
01998     int bitpix;
01999     cpl_type type;
02000     int naxis=0;
02001     cpl_vector * vector=NULL;
02002 
02003     
02004     assure_nomsg( f != NULL, CPL_ERROR_NULL_INPUT );
02005     assure( cpl_frame_get_type(f) == CPL_FRAME_TYPE_IMAGE,
02006         CPL_ERROR_TYPE_MISMATCH, "Wrong type: %s",
02007         uves_tostring_cpl_frame_type(cpl_frame_get_type(f)));
02008 
02009     filename = cpl_frame_get_filename(f);
02010 
02011     check( plist = uves_propertylist_load(filename, extension),
02012        "Could not load header from %s extension %d", 
02013        filename, extension);
02014     
02015     check( bitpix = uves_pfits_get_bitpix(plist),
02016        "Could not read BITPIX from %s extension %d",
02017        filename, extension);
02018     
02019     if      (bitpix == -32) type = CPL_TYPE_FLOAT;
02020     else if (bitpix == -64) type = CPL_TYPE_DOUBLE;
02021     else if (bitpix ==  32) type = CPL_TYPE_INT;
02022     else if (bitpix ==  16) type = CPL_TYPE_INT;
02023     else
02024     {
02025         assure( false, CPL_ERROR_UNSUPPORTED_MODE,
02026             "No CPL type to represent BITPIX = %d", bitpix);
02027     }
02028 
02029     check( naxis = uves_pfits_get_naxis(plist),
02030            "could not get NAXIS" );
02031 
02032     if( naxis == 1) {
02033 
02034       check( vector = cpl_vector_load(filename,extension),
02035              "Could not load vector from extension %d of file '%s' ",
02036              extension, filename);
02037       cknull(image=uves_vector_to_image(vector,type),
02038          "could not convert vector to image");
02039     } else {
02040 
02041 
02042       check( image = cpl_image_load(filename,
02043                     type,
02044                     plane,
02045                     extension),
02046          "Could not load image from extension %d of file '%s' ", 
02047          extension, filename);
02048 
02049     }
02050 
02051     if (header != NULL)
02052     {
02053         *header = uves_propertylist_duplicate(plist);
02054     }
02055 
02056   cleanup:
02057     uves_free_vector(&vector);
02058     uves_free_propertylist(&plist);
02059     return image;
02060 }
02061 /*----------------------------------------------------------------------------*/
02065 /*----------------------------------------------------------------------------*/
02066 
02067 cpl_image *uves_load_image_file(const char *filename,
02068                                 int plane,
02069                                 int extension,
02070                                 uves_propertylist **header)
02071 {
02072     cpl_image *i;
02073     cpl_frame *f = cpl_frame_new();
02074     cpl_frame_set_filename(f, filename);
02075     cpl_frame_set_type(f, CPL_FRAME_TYPE_IMAGE);
02076 
02077     i = uves_load_image(f, plane, extension, header);
02078     
02079     uves_free_frame(&f);
02080 
02081     return i;
02082 }
02083 
02084 /*----------------------------------------------------------------------------*/
02109 /*----------------------------------------------------------------------------*/
02110 void
02111 uves_save_image(const cpl_image *image, const char *filename, const uves_propertylist *plist,
02112                 bool use_bitpix16_for_int, bool save1d)
02113 {
02114     cpl_type_bpp bpp;
02115     cpl_type t;
02116     const cpl_vector *image_1d = NULL;
02117     uves_propertylist *header = NULL;
02118     cpl_image *thresholded = NULL;
02119     cpl_image *thresholded_double = NULL;
02120     
02121     if (image == NULL) {
02122         check( uves_image_save(image, filename, CPL_BPP_IEEE_FLOAT, plist, CPL_IO_DEFAULT), 
02123                "Error saving NULL image to file '%s'", filename);
02124     }
02125     else {
02126         check( t = cpl_image_get_type(image), "Error reading image type");
02127         if      (t == CPL_TYPE_FLOAT ) bpp = CPL_BPP_IEEE_FLOAT;
02128         else if (t == CPL_TYPE_DOUBLE) bpp = CPL_BPP_IEEE_FLOAT;
02129         /* Internal computations in double precision,
02130            save as single precision */
02131 #if CPL_VERSION_CODE >= CPL_VERSION(3, 0, 1)
02132         /* Some FLAMES images are BITPIX=16 (ORDEF), 
02133            some are 32 SLIT_FF_COM_REDL
02134         */
02135         else if (t == CPL_TYPE_INT   ) {
02136             if (use_bitpix16_for_int) bpp = CPL_BPP_16_UNSIGNED;
02137             else bpp = CPL_BPP_32_SIGNED;
02138         }
02139 #else
02140         else if (t == CPL_TYPE_INT   ) bpp = CPL_BPP_16_SIGNED;
02141 #endif
02142         else assure(false, CPL_ERROR_UNSUPPORTED_MODE,
02143                     "Unsupported image type '%s'", uves_tostring_cpl_type(t));
02144 
02145 
02146         thresholded = cpl_image_duplicate(image);
02147         assure_mem( thresholded );
02148 
02149         if (t == CPL_TYPE_DOUBLE)
02150             {
02151                 passure( bpp == CPL_BPP_IEEE_FLOAT, "%d", bpp);
02152 
02153                 /* Avoid infinities that would happen when casting
02154                    double -> float
02155                    by thresholding the image to +-FLT_MAX (or, better
02156                    a little less than FLT_MAX just to be sure).
02157         
02158                    (This is not a really nice solution because it solves the
02159                    problem (too large/small values) after it is introduced
02160                    (rather than avoiding it), but a general solution of the
02161                    problem would probably mean guarding every arithmetic
02162                    operation with range checks.)
02163                 */
02164         
02165                 check_nomsg( cpl_image_threshold(thresholded,
02166                                                  -FLT_MAX, FLT_MAX,
02167                                                  -FLT_MAX, FLT_MAX) );
02168 
02169                 /* Also get rid of NaN, set to zero (what else?) */
02170                 {
02171                     double *data = cpl_image_get_data_double(thresholded);
02172                     int nx = cpl_image_get_size_x(thresholded);
02173                     int ny = cpl_image_get_size_y(thresholded);
02174                     int x, y;
02175         
02176                     for (y = 0; y < ny; y++)
02177                         for (x = 0; x < nx; x++)
02178                             {
02179                                 if (irplib_isnan(data[x + y*nx]))
02180                                     {
02181                                         data[x + y*nx] = 0;
02182                                     }
02183                             }
02184                 }
02185             }
02186 
02187         if (save1d && 
02188             cpl_image_get_size_y(thresholded) == 1 &&
02189             (t == CPL_TYPE_DOUBLE ||
02190              t == CPL_TYPE_FLOAT)) {
02191             
02192             bool invert = false;
02193             if (plist != NULL)
02194                 {
02195                     header = uves_propertylist_duplicate(plist);
02196             
02197                     uves_propertylist_erase_regexp(header, "^CDELT2$", invert);
02198                     uves_propertylist_erase_regexp(header, "^CRPIX2$", invert);
02199                     uves_propertylist_erase_regexp(header, "^CRVAL2$", invert);
02200                     uves_propertylist_erase_regexp(header, "^CTYPE2$", invert);
02201                 }
02202             else
02203                 {
02204                     header = NULL;
02205                 }
02206         
02207             /* Image type must be double, before wrapping it
02208                in a vector */
02209             if (t == CPL_TYPE_FLOAT) {
02210                 thresholded_double = cpl_image_cast(thresholded, CPL_TYPE_DOUBLE);
02211             }
02212             else {
02213                 thresholded_double = cpl_image_duplicate(thresholded);
02214             }
02215         
02216             passure( cpl_image_get_type(thresholded_double) == CPL_TYPE_DOUBLE, "%d",
02217                      cpl_image_get_type(thresholded_double));
02218         
02219             image_1d = cpl_vector_wrap(
02220                 cpl_image_get_size_x(thresholded_double),
02221                 cpl_image_get_data_double_const(thresholded_double));
02222         
02223             check( uves_vector_save(image_1d, filename, bpp, header, CPL_IO_DEFAULT),
02224                    "Error saving vector to file '%s'", filename );
02225         }
02226         else
02227             {
02228                 check( uves_image_save(thresholded, filename, bpp, plist, CPL_IO_DEFAULT), 
02229                        "Error saving image to file '%s'", filename);
02230             }
02231     }
02232     
02233   cleanup:
02234     uves_unwrap_vector_const(&image_1d);
02235     uves_free_propertylist(&header);
02236     uves_free_image(&thresholded);
02237     uves_free_image(&thresholded_double);
02238     
02239     return;
02240 }
02241 
02242 
02243 /*----------------------------------------------------------------------------*/
02263 /*----------------------------------------------------------------------------*/
02264 void
02265 uves_save_imagelist(const cpl_imagelist *iml, const char *filename, const uves_propertylist *plist)
02266 {
02267     const cpl_image* img=NULL;
02268     cpl_type_bpp bpp;
02269     cpl_type t;
02270     const cpl_vector *image_1d = NULL;
02271     uves_propertylist *header = NULL;
02272     cpl_imagelist *thresholded = NULL;
02273 
02274     int nx = 0;
02275     int ny = 0;
02276     int nz = 0;
02277 
02278     
02279     cknull(iml,"Null input image");
02280     check(img=cpl_imagelist_get_const(iml,0),"error reading image");
02281 
02282     check_nomsg( nx = cpl_image_get_size_x(img));
02283     check_nomsg( ny = cpl_image_get_size_y(img));
02284     check_nomsg( nz = cpl_imagelist_get_size(iml));
02285 
02286     check( t = cpl_image_get_type(img), "Error reading image type");
02287     if      (t == CPL_TYPE_FLOAT ) bpp = CPL_BPP_IEEE_FLOAT;
02288     else if (t == CPL_TYPE_DOUBLE) bpp = CPL_BPP_IEEE_FLOAT;
02289     /* Internal computations in double precision,
02290        save as single precision */
02291 #if CPL_VERSION_CODE >= CPL_VERSION(3, 0, 1)
02292     else if (t == CPL_TYPE_INT   ) bpp = CPL_BPP_16_UNSIGNED;
02293 #else
02294     else if (t == CPL_TYPE_INT   ) bpp = CPL_BPP_16_SIGNED;
02295 #endif
02296     else assure(false, CPL_ERROR_UNSUPPORTED_MODE,
02297         "Unsupported image type '%s'", uves_tostring_cpl_type(t));
02298 
02299 
02300     thresholded = cpl_imagelist_duplicate(iml);
02301     assure_mem( thresholded );
02302 
02303     if (t == CPL_TYPE_DOUBLE)
02304     {
02305         passure( bpp == CPL_BPP_IEEE_FLOAT, "%d", bpp);
02306 
02307         /* Avoid infinities that would happen when casting
02308                double -> float
02309            by thresholding the image to +-FLT_MAX (or, better
02310            a little less than FLT_MAX just to be sure).
02311         
02312            (This is not a really nice solution because it solves the
02313            problem (too large/small values) after it is introduced
02314            (rather than avoiding it), but a general solution of the
02315            problem would probably mean guarding every arithmetic
02316            operation with range checks.)
02317         */
02318         
02319         check_nomsg( cpl_imagelist_threshold(thresholded,
02320                          -FLT_MAX, FLT_MAX,
02321                          -FLT_MAX, FLT_MAX) );
02322 
02323 
02324 
02325         /* Also get rid of NaN, set to zero (what else?) */
02326         {
02327         int x, y, z;
02328         double* data=NULL;
02329         cpl_image* ima=NULL;
02330         for (z = 0; z < nz; z++) {
02331           ima=cpl_imagelist_get(thresholded,z);
02332           data = cpl_image_get_data_double(ima);
02333 
02334           for (y = 0; y < ny; y++) {
02335             for (x = 0; x < nx; x++) {
02336               if (irplib_isnan(data[x + y*nx])) {
02337             data[x + y*nx] = 0;    
02338               }
02339             }
02340           }
02341         }
02342         }
02343     }
02344     if (nz == 1 && t == CPL_TYPE_DOUBLE)
02345     /* To support other types (float, int) we would
02346        need to convert to double first */
02347     {
02348         bool invert = false;
02349         if (plist != NULL)
02350         {
02351             header = uves_propertylist_duplicate(plist);
02352             
02353             uves_propertylist_erase_regexp(header, "^CDELT3$", invert);
02354             uves_propertylist_erase_regexp(header, "^CRPIX3$", invert);
02355             uves_propertylist_erase_regexp(header, "^CRVAL3$", invert);
02356             uves_propertylist_erase_regexp(header, "^CTYPE3$", invert);
02357         }
02358         else
02359         {
02360             header = NULL;
02361         }
02362         /*
02363         image_1d = cpl_vector_wrap(nx,
02364                         cpl_image_get_data_double_const(thresholded));
02365         
02366         check( uves_vector_save(image_1d, filename, bpp, header, CPL_IO_DEFAULT),
02367            "Error saving vector to file '%s'", filename );
02368         */
02369         
02370     }
02371     else
02372     {
02373         check( uves_imagelist_save(thresholded, filename, bpp, plist, CPL_IO_DEFAULT), 
02374            "Error saving image to file '%s'", filename);
02375     }
02376     
02377   cleanup:
02378     uves_unwrap_vector_const(&image_1d);
02379     uves_free_propertylist(&header);
02380     uves_free_imagelist(&thresholded);
02381 
02382     return;
02383 }
02384 
02385 /*----------------------------------------------------------------------------*/
02399 /*----------------------------------------------------------------------------*/
02400 cpl_error_code
02401 uves_save_polynomial(polynomial *p, const char *filename, const uves_propertylist *header)
02402 {
02403     cpl_table *t = NULL;
02404 
02405     check( t = uves_polynomial_convert_to_table(p), "Error converting polynomial to table");
02406     
02407     check( uves_table_save(t, 
02408               NULL,                       /* Primary header, ignored when 
02409                              mode = CPL_IO_EXTEND */
02410               header,                     /* Table header */
02411               filename,
02412               CPL_IO_EXTEND),             /* Append to existing file */
02413        "Error saving table to file '%s'", filename);
02414     
02415   cleanup:
02416     uves_free_table(&t);
02417     return cpl_error_get_code();
02418 }
02419 
02420 
02421 /*----------------------------------------------------------------------------*/
02429 /*----------------------------------------------------------------------------*/
02430 static polynomial *
02431 load_polynomial(const char* filename, int extension)
02432 {
02433     polynomial *p = NULL;  /* Result */
02434     cpl_table  *t = NULL;
02435     
02436     check(t = cpl_table_load(filename,
02437                  extension,
02438                  1),                   /* Mark identified 
02439                               invalid null values (1=yes) */
02440       "Error loading polynomial from extension %d of file '%s'", extension, filename);
02441 
02442     assure( uves_erase_invalid_table_rows(t, NULL) == 0, 
02443         CPL_ERROR_ILLEGAL_INPUT, "Table contains invalid rows");
02444     
02445     check(p = uves_polynomial_convert_from_table(t), "Error converting table to polynomial");
02446 
02447   cleanup:
02448     uves_free_table(&t);
02449     if (cpl_error_get_code() != CPL_ERROR_NONE)
02450     uves_polynomial_delete(&p);
02451     return p;
02452 }
02453 /*----------------------------------------------------------------------------*/
02468 /*----------------------------------------------------------------------------*/
02469 static const char *
02470 identify_arm(const cpl_frameset *frames, const char *blue_tag, const char *red_tag,
02471          bool *blue)
02472 {
02473     const char *tag = NULL; /* Result */
02474     
02475     const cpl_frame *frame = NULL;
02476     
02477     passure( frames != NULL, "");
02478     assure (!cpl_frameset_is_empty(frames), CPL_ERROR_ILLEGAL_INPUT, "No input frames");
02479     
02480     /* Identify blue/red arm */
02481     frame = cpl_frameset_find_const(frames, blue_tag);
02482     *blue = (frame != NULL);
02483     
02484     if (frame == NULL)
02485     {
02486         frame = cpl_frameset_find_const(frames, red_tag);
02487     }
02488     
02489     assure( frame != NULL, CPL_ERROR_ILLEGAL_INPUT, 
02490         "No valid input frames "
02491         "('%s' or '%s') in frame set",
02492         blue_tag, red_tag);
02493     
02494     assure( cpl_frameset_find_const(frames, blue_tag) == NULL ||
02495         cpl_frameset_find_const(frames, red_tag)  == NULL,
02496         CPL_ERROR_INCOMPATIBLE_INPUT,
02497         "Multiple types of input frames ('%s' and '%s') in frame set",
02498         blue_tag, red_tag);
02499     
02500     tag = cpl_frame_get_tag(frame);
02501     
02502     uves_msg("Input frames are '%s'", tag);
02503     
02504 
02505   cleanup:
02506     return tag;
02507 }
02508 
02509 /*----------------------------------------------------------------------------*/
02527 /*----------------------------------------------------------------------------*/
02528 cpl_image *
02529 uves_crop_and_rotate(const cpl_image *image, const uves_propertylist *header,
02530              enum uves_chip chip,
02531              const uves_propertylist *redl_header, 
02532              bool new_format, uves_propertylist **out_header)
02533 {
02534     cpl_image *result = NULL;
02535     int prescanx, ovrscanx;
02536     int nx, ny;
02537     int x_0, y_0, x_1, y_1; /* Extracted area (inclusive) in 
02538                    FITS convention (i.e. counting from 1) */
02539 
02540     const char *ctype1, *ctype2; /* Geometry */
02541     const char *bunit;
02542     double crval1, crval2;
02543     double crpix1, crpix2;
02544     double cdelt1, cdelt2;
02545 
02546 
02547     passure( image != NULL, " ");
02548     passure( header != NULL, " ");
02549     passure( out_header != NULL, " ");
02550     
02551     nx = cpl_image_get_size_x(image);
02552     ny = cpl_image_get_size_y(image);
02553 
02554 
02555     /* Determine pre- and overscan areas */
02556     check( prescanx = uves_pfits_get_prescanx(header, chip), "Could not read x-prescan info" );
02557     check( ovrscanx = uves_pfits_get_ovrscanx(header, chip), "Could not read x-overscan info");
02558   
02559     /* Don't try to read the y pre- and overscan regions, which should be zero for UVES.
02560        The keywords are not present in older UVES data. */
02561 
02562     /* Read geometry */
02563     check( ctype1 = uves_pfits_get_ctype1(header), "Error reading keyword");
02564     check( ctype2 = uves_pfits_get_ctype2(header), "Error reading keyword");
02565     check( crval1 = uves_pfits_get_crval1(header), "Error reading keyword");
02566     check( crval2 = uves_pfits_get_crval2(header), "Error reading keyword");
02567     check( crpix1 = uves_pfits_get_crpix1(header), "Error reading keyword");
02568     check( crpix2 = uves_pfits_get_crpix2(header), "Error reading keyword");
02569     check( cdelt1 = uves_pfits_get_cdelt1(header), "Error reading keyword");
02570     check( cdelt2 = uves_pfits_get_cdelt2(header), "Error reading keyword");
02571     if (uves_propertylist_contains(header, UVES_BUNIT))
02572     {
02573         bunit = uves_pfits_get_bunit(header);
02574     }
02575     else
02576     {
02577         bunit = " ";
02578     }
02579     
02580 
02581     /* Crop the image */
02582     {
02583     y_0 = 1;
02584     y_1 = ny;
02585     if (new_format || chip == UVES_CHIP_BLUE)
02586         {
02587         x_0 = prescanx + 1;
02588         x_1 = nx - ovrscanx;
02589         }
02590     else /* red, old format */
02591         {
02592         if (chip == UVES_CHIP_REDU)
02593             {
02594             x_0 = prescanx + 1;
02595             x_1 = nx/2 - ovrscanx;
02596             }
02597         else
02598             { /* lower */
02599             x_0 = nx/2 + prescanx + 1;
02600             x_1 = nx - ovrscanx;
02601             }
02602         }
02603     
02604     check( result = cpl_image_extract(image, x_0, y_0, x_1, y_1), "Could not crop image");
02605     crpix1 = crpix1 - (x_0 - 1);
02606     crpix2 = crpix2 - (y_0 - 1);
02607     nx = (x_1 - x_0) + 1;
02608     ny = (y_1 - y_0) + 1;
02609     }
02610 
02611     UVES_TIME_START("Rotation");
02612     /* ... is a bit slow, and there's probably nothing to
02613        do about as it involves moving data between remote
02614        places in memory.
02615     */
02616 
02617     /* Rotate the image into standard orientation */
02618     {
02619     int crpix1_old = crpix1;
02620     int crpix2_old = crpix2;
02621     int crval1_old = crval1;
02622     int crval2_old = crval2;
02623     int cdelt1_old = cdelt1;
02624     int cdelt2_old = cdelt2;
02625     const char *ctype1_old = ctype1;
02626     const char *ctype2_old = ctype2;
02627 
02628     if (chip == UVES_CHIP_BLUE)
02629         {
02630         /* 90 deg counterclockwise rotation */
02631         check( cpl_image_turn(result, -1), "Could not turn image");
02632         
02633         crpix1 = ny - (crpix2_old - 1); /* Note: old value of ny */
02634         crpix2 = crpix1_old;
02635         crval1 = crval2_old;
02636         crval2 = crval1_old;
02637         }
02638     else 
02639         {
02640         /* Red */
02641         /* Flip image around y=-x */
02642         check( cpl_image_flip(result, 3), "Could not flip image");
02643 
02644         crpix1 = ny - (crpix2_old - 1); /* Note: old value of nx, ny */
02645         crpix2 = nx - (crpix1_old - 1);
02646         crval1 = crval2_old;
02647         crval2 = crval1_old;
02648         }
02649 
02650 
02651     /* Always swap these ones */
02652     ctype1 = ctype2_old;
02653     ctype2 = ctype1_old;
02654     cdelt1 = cdelt2_old;
02655     cdelt2 = cdelt1_old;
02656     }
02657 
02658     UVES_TIME_END;
02659 
02660     /* Here we should use the CROTAi keywords to 
02661        properly describe the new rotation */
02662     
02663     /* Instead, redefine CRVAL as in the following, on request from DFO */
02664 
02665     crpix1 = 1;
02666     crpix2 = 1;
02667     if (chip == UVES_CHIP_BLUE || chip == UVES_CHIP_REDL)
02668     {
02669         crval1 = 1;
02670         crval2 = 1;
02671     }
02672     else 
02673     {
02674             int physical_gap_between_chips = 64; /* Pixels. Unbinned. Hardcoded. */
02675 
02676 
02677         passure( chip == UVES_CHIP_REDU , "%d", chip );
02678         
02679         crval1 = 1;
02680         
02681         /* Set CRVAL2 = REDL_height - REDL_overscan - REDL_prescan + gap. */
02682         if (new_format)
02683         {
02684 
02685             check( crval2 = 1 +
02686                (uves_pfits_get_naxis1(redl_header) -
02687                 uves_pfits_get_ovrscanx(redl_header, UVES_CHIP_REDL) -
02688                 uves_pfits_get_prescanx(redl_header, UVES_CHIP_REDL)) *
02689                uves_pfits_get_cdelt1(redl_header) +
02690                            physical_gap_between_chips,
02691                "Error reading REDL chip geometry");
02692 
02693             uves_msg_debug("Setting CRVAL2 = 1 + (%d - %d - %d) * %f + %d = %f",
02694                    uves_pfits_get_naxis1(redl_header),
02695                    uves_pfits_get_ovrscanx(redl_header, UVES_CHIP_REDL),
02696                    uves_pfits_get_prescanx(redl_header, UVES_CHIP_REDL),
02697                    uves_pfits_get_cdelt1(redl_header),
02698                                    physical_gap_between_chips, crval2);
02699         }
02700         else
02701         {
02702 
02703             /* old format */
02704             check( crval2 = 1 +
02705                (uves_pfits_get_naxis1(header)/2 -
02706                 uves_pfits_get_ovrscanx(redl_header, UVES_CHIP_REDL) -
02707                 uves_pfits_get_prescanx(redl_header, UVES_CHIP_REDL)) *
02708                uves_pfits_get_cdelt1(redl_header) +
02709                            physical_gap_between_chips,
02710                "Error reading REDL chip geometry");
02711 
02712             uves_msg_debug("Setting CRVAL2 = 1 + (%d - %d - %d) * %f + %d = %f",
02713                    uves_pfits_get_naxis1(header)/2, 
02714                    uves_pfits_get_ovrscanx(redl_header, UVES_CHIP_REDL),
02715                    uves_pfits_get_prescanx(redl_header, UVES_CHIP_REDL),
02716                    uves_pfits_get_cdelt1(redl_header),
02717                                    physical_gap_between_chips, crval2);
02718         }
02719 
02720     }
02721 
02722 
02723     /* Update header with new geometry */
02724     check( *out_header = uves_initialize_image_header(ctype1, ctype2, bunit,
02725                               crval1, crval2,
02726                               crpix1, crpix2,
02727                               cdelt1, cdelt2),
02728        "Error initializing header");
02729 
02730     uves_msg("Raw image cropped and rotated from %dx%d to %dx%d",
02731          nx, ny,
02732          cpl_image_get_size_x(result),
02733          cpl_image_get_size_y(result));     
02734 
02735   cleanup:
02736     if (cpl_error_get_code() != CPL_ERROR_NONE)
02737     {
02738         uves_free_image(&result);
02739         if (out_header != NULL)
02740         {
02741             uves_free_propertylist(out_header);
02742         }
02743     }
02744 
02745     return result;
02746 }
02747 
02748 /*----------------------------------------------------------------------------*/
02762 /*----------------------------------------------------------------------------*/
02763 void
02764 uves_warn_if_chip_names_dont_match(const uves_propertylist *calib_header, 
02765                   const char *raw_chip_name, enum uves_chip chip)
02766 {
02767     const char *calib_chip_name;
02768     bool mismatch = false;
02769 
02770     check( calib_chip_name = uves_pfits_get_chipid(calib_header, chip),
02771        "Could not read chip name of calibration data");
02772 
02773 
02774     /* Ignore leading/trailing blanks when comparing name strings.
02775      * (The following is O(n^2) where n is the string length, 
02776      * but that's ok because the strings stored in a FITS card are short).
02777      */
02778     {
02779     unsigned int calib_first, calib_last;  /* inclusive */
02780     unsigned int raw_first, raw_last;
02781     
02782     calib_first = 0;
02783     raw_first = 0;
02784     while (calib_chip_name[calib_first] == ' ' && calib_first < strlen(calib_chip_name) - 1)
02785         {
02786         calib_first++;
02787         }
02788     while (raw_chip_name[raw_first] == ' ' && raw_first < strlen(raw_chip_name) - 1)
02789         {
02790         raw_first++;
02791         }
02792 
02793     calib_last = strlen(calib_chip_name) - 1;
02794     raw_last = strlen(raw_chip_name) - 1;
02795     while (calib_chip_name[calib_last] == ' ' && calib_last > 0)
02796         {
02797         calib_last--;
02798         }
02799     while (raw_chip_name[raw_last] == ' ' && raw_last > 0)
02800         {
02801         raw_last--;
02802         }
02803 
02804     /* Compare substrings */
02805     if (calib_last - calib_first != raw_last - raw_first)
02806         {
02807         mismatch = true;
02808         }
02809     else
02810         {
02811         unsigned int i;
02812         
02813         for (i = 0; i <= (calib_last - calib_first); i++)
02814             {
02815             if (raw_chip_name[raw_first + i] != 
02816                 calib_chip_name[calib_first + i])
02817                 {
02818                 mismatch = true;
02819                 }
02820             }
02821         }
02822     }
02823 
02824 
02825     if (mismatch)
02826     {
02827         uves_msg_warning("Calibration frame chip ID '%s' does "
02828                  "not match raw frame chip ID '%s'",
02829                  calib_chip_name, raw_chip_name);
02830     }
02831 
02832   cleanup:
02833     return;
02834 }
02835 
02836 
02837 /*----------------------------------------------------------------------------*/
02859 /*----------------------------------------------------------------------------*/
02860 
02861 static cpl_error_code
02862 load_raw_image(const char *filename, 
02863            cpl_type type,
02864            bool flames,
02865            bool blue,
02866            cpl_image *raw_image[2],
02867            uves_propertylist *raw_header[2], 
02868                uves_propertylist *rotated_header[2])
02869 {
02870 
02871  
02872     cpl_image *image = NULL;
02873     uves_propertylist *primary_header = NULL;
02874     uves_propertylist *ext_header = NULL;
02875     int extension, nextensions;
02876     bool new_format;
02877     int plane = 0;   /* Only one plane in FLAMES/UVES raw files */
02878 
02879     /* Initialize parameters */
02880     raw_image[0] = NULL;
02881     raw_image[1] = NULL;
02882     raw_header[0] = NULL;
02883     raw_header[1] = NULL;
02884     rotated_header[0] = NULL;
02885     rotated_header[1] = NULL;
02886 
02887     check( nextensions = uves_get_nextensions(filename),
02888        "Error reading number of extensions of file '%s'", filename);
02889 
02890     /* Find out if new/old format */
02891     extension = 0;
02892     check( primary_header = uves_propertylist_load(filename,
02893                           extension),
02894        "Could not load header from extension %d of file '%s'", 
02895        extension, filename);
02896 
02897     check( new_format = uves_format_is_new(primary_header),
02898        "Error determining new/old format of file %s", filename);
02899  
02900     uves_msg_low("Raw frame is %s, %s format, file '%s' has %d extensions", 
02901          (blue) ? "blue" : "red", (new_format) ? "new" : "old", 
02902          filename, nextensions);
02903 
02904     /* If the raw frame is blue, or if it's an old format red frame */
02905     if (blue || !new_format)
02906     {
02907         enum uves_chip chip;
02908         
02909         uves_msg_debug("Frame is blue or old format");
02910 
02911         assure( nextensions == 0 || (flames && nextensions == 2),
02912             CPL_ERROR_ILLEGAL_INPUT, 
02913             "Unrecognized format of file '%s'. %d extensions expected. %d found.",
02914             filename, 
02915             flames ? 2 : 0, nextensions);
02916         /* FLAMES: the 2 extensions contain OzPoz table and FLAMES FIBRE table */
02917 
02918         extension = 0;
02919 
02920         check( image = cpl_image_load(filename,
02921                       type,
02922                       plane,   
02923                       extension
02924                ), "Could not load image from extension %d of file '%s' ", 
02925            extension, filename);
02926 
02927         /* Load the header */
02928         check( raw_header[0] = uves_propertylist_load(filename,
02929                              extension),
02930            "Could not load header from extension %d of file '%s'", 
02931            extension, filename);
02932 
02933         /* Get blue (or lower red) chip */
02934         chip = (blue) ? UVES_CHIP_BLUE : UVES_CHIP_REDL;
02935         check( raw_image[0] = uves_crop_and_rotate(image, raw_header[0], 
02936                                chip, raw_header[0],
02937                                new_format, 
02938                                &rotated_header[0]),
02939            "Error splitting image");
02940         
02941         if (!blue)
02942         {
02943             const uves_propertylist *redl_header;
02944 
02945             /* Upper red chip, use again the primary header */
02946             check( raw_header[1] = uves_propertylist_duplicate(raw_header[0]),
02947                "Error duplicating FITS header");
02948             
02949             /* Get upper red chip */
02950             chip = UVES_CHIP_REDU;
02951             redl_header = raw_header[0];
02952             check( raw_image[1] = uves_crop_and_rotate(image, raw_header[1],
02953                                    chip, redl_header,
02954                                    new_format,
02955                                    &rotated_header[1]),
02956                "Error splitting red image");
02957         }
02958         else
02959         {
02960             raw_image[1] = NULL;
02961             raw_header[1] = NULL;
02962             rotated_header[1] = NULL;
02963         }
02964     }
02965     else
02966     /* New red format. UVES must have 2 extensions,
02967      * FLAMES must have 2 or more extensions
02968      */
02969     {
02970         uves_msg_debug("Frame is red, new format");
02971         
02972         assure( nextensions >= 2, CPL_ERROR_UNSUPPORTED_MODE,
02973             "File '%s' (red frame) has %d extensions. 2+ extensions expected "
02974                     "for new format",
02975             filename, nextensions);
02976         
02977         uves_msg_debug("New red format, %s frame",
02978                (nextensions > 2) ? "FLAMES" : "FLAMES/UVES");
02979         
02980 
02981         /* Images always in extension 1 and 2. First load just the headers */
02982         for (extension = 1; extension <= 2; extension++)
02983         {
02984             /* In the FITS file, REDU is stored
02985                in extension 1, and REDL is stored in
02986                extension 2 */
02987             enum uves_chip chip = (extension == 1) ? UVES_CHIP_REDU : UVES_CHIP_REDL;
02988             int indx = uves_chip_get_index(chip);
02989 
02990             /* Load the extension header */
02991             uves_free_propertylist(&ext_header);
02992             check( ext_header = uves_propertylist_load(filename,
02993                                   extension),
02994                "Could not load header from extension %d of file '%s'", 
02995                extension, filename);
02996             
02997             /* Merge with primary header */
02998             check( raw_header[indx] = uves_propertylist_duplicate(primary_header),
02999                "Error cloning primary header");
03000             
03001             if (!uves_propertylist_is_empty(ext_header))
03002             {
03003                 check( uves_propertylist_copy_property_regexp(raw_header[indx],
03004                                      ext_header, ".*", 0),
03005                    "Error merging primary header with extension %d header", 
03006                    extension);
03007             }
03008         }
03009 
03010 
03011         /* Remove pre-, overscan areas (we needed to load both image headers for this) */
03012         for (extension = 1; extension <= 2; extension++)
03013         {
03014             enum uves_chip chip = (extension == 1) ? UVES_CHIP_REDU : UVES_CHIP_REDL;
03015             int indx      = uves_chip_get_index(chip);
03016             int indx_redl = uves_chip_get_index(UVES_CHIP_REDL);
03017             
03018             const uves_propertylist *redl_header = raw_header[indx_redl];
03019             
03020             uves_free_image(&image);
03021             check( image = cpl_image_load(filename,
03022                           type,
03023                           plane,               
03024                           extension),
03025                "Could not load image from extension %d of file '%s' ", 
03026                extension, filename);
03027             
03028             check( raw_image[indx] = uves_crop_and_rotate(image, 
03029                                   raw_header[indx],
03030                                   chip, redl_header,
03031                                   new_format,
03032                                   &rotated_header[indx]),
03033                "Error splitting red image");
03034         }
03035 
03036         
03037     }/* if new format */
03038  
03039 
03040   cleanup:
03041     uves_free_image(&image);
03042     uves_free_propertylist(&primary_header);
03043     uves_free_propertylist(&ext_header);
03044 
03045     if (cpl_error_get_code() != CPL_ERROR_NONE)
03046     {
03047         uves_free_image       (&raw_image[0]);
03048         uves_free_image       (&raw_image[1]);
03049         uves_free_propertylist(&raw_header[0]);
03050         uves_free_propertylist(&raw_header[1]);
03051         uves_free_propertylist(&rotated_header[0]);
03052         uves_free_propertylist(&rotated_header[1]);
03053     }
03054     
03055     return cpl_error_get_code();
03056 }
03057 
03058 
03059 /*----------------------------------------------------------------------------*/
03087 /*----------------------------------------------------------------------------*/
03088 cpl_error_code
03089 uves_load_raw_imagelist(const cpl_frameset *frames,
03090             bool flames,
03091             const char *blue_tag, const char *red_tag, cpl_type type, 
03092             cpl_imagelist *images[2],
03093             uves_propertylist **raw_headers[2], uves_propertylist *rotated_header[2],
03094             bool *blue)
03095 {
03096     const char *tag           = NULL;
03097     const cpl_frame *frame    = NULL;
03098     cpl_image *temp_image[2]  = {NULL, NULL};
03099     uves_propertylist *temp_header[2] = {NULL, NULL};
03100     int number_of_frames = 0;
03101     int frameset_size = 0;   /* Keeps track of number of raw_header pointers allocated */
03102     int nchips;
03103     int chip;
03104     
03105     raw_headers[0] = NULL;
03106     raw_headers[1] = NULL;
03107 
03108     check( frameset_size = cpl_frameset_get_size(frames),
03109        "Error reading frameset size");
03110 
03111     check( tag = identify_arm(frames, blue_tag, red_tag, blue),
03112        "Could not identify chip type");
03113     
03114     nchips = (*blue) ? 1 : 2;
03115     for(chip = 0; chip < nchips; chip++)
03116     {
03117         images[chip] = NULL;
03118         rotated_header[chip] = NULL;
03119         
03120         images[chip] = cpl_imagelist_new();
03121         raw_headers[chip] = cpl_calloc(frameset_size, sizeof(uves_propertylist *));
03122     }
03123 
03124     /* Load all input images with correct tag,
03125        split,
03126        insert into image list(s) */  
03127 
03128     number_of_frames = 0;
03129     for(frame = cpl_frameset_get_first_const(frames);
03130     frame != NULL;
03131     frame = cpl_frameset_get_next_const(frames))
03132     {
03133         /* If match */
03134         if ( strcmp(cpl_frame_get_tag(frame), tag) == 0)
03135         {
03136             const char *filename = cpl_frame_get_filename(frame);
03137             
03138             /* Load image + header */
03139             uves_free_propertylist(&rotated_header[0]);
03140             uves_free_propertylist(&rotated_header[1]);
03141             
03142             check( load_raw_image(filename,
03143                       type,
03144                       flames,
03145                       *blue,
03146                       temp_image,
03147                       temp_header,
03148                       rotated_header),
03149                "Could not load image from file '%s'", filename);
03150             
03151             /* Append to image lists */
03152             for(chip = 0; chip < nchips; chip++)
03153             {
03154                 raw_headers[chip][number_of_frames] = temp_header[chip];
03155                 temp_header[chip] = NULL;
03156                 
03157                 check( cpl_imagelist_set(images[chip],
03158                              temp_image[chip],
03159                              /* Position */
03160                              cpl_imagelist_get_size(images[chip])
03161                        ),
03162                    "Could not insert image into image list");
03163                 
03164                 /* Don't deallocate image or header */
03165                 temp_image[chip] = NULL;
03166             }
03167             
03168             number_of_frames += 1;
03169         }
03170     }
03171 
03172     /* Check that image sizes are identical */
03173     
03174     for(chip = 0; chip < nchips; chip++)
03175     {
03176         /* This function returns zero iff the list is uniform */
03177         assure (cpl_imagelist_is_uniform(images[chip]) == 0,
03178             CPL_ERROR_INCOMPATIBLE_INPUT, 
03179             "Input images are not of same size and type");
03180         
03181         passure( cpl_imagelist_get_size(images[chip]) == number_of_frames, 
03182              "%d %d", cpl_imagelist_get_size(images[0]), number_of_frames);
03183 
03184     }
03185 
03186     
03187     /* Check central wavelengths (not bias/dark) */
03188     if ( strcmp(UVES_BIAS (*blue), tag) != 0 &&
03189      strcmp(UVES_DARK (*blue), tag) != 0 &&
03190      strcmp(UVES_PDARK(*blue), tag) != 0) {
03191     enum uves_chip chip_id;
03192     int i;
03193     double wlen = 0;
03194     
03195     for (chip_id = uves_chip_get_first(*blue); 
03196          chip_id != UVES_CHIP_INVALID;
03197          chip_id = uves_chip_get_next(chip_id)) {
03198         for (i = 0; i < number_of_frames; i++) {
03199         if (i == 0) {
03200             check( wlen = uves_pfits_get_gratwlen(
03201                    raw_headers[uves_chip_get_index(chip_id)][i], chip_id),
03202                "Error reading central wavelength of input frame number %d", i+1);
03203         }
03204         else {
03205             double w;
03206             
03207             check( w = uves_pfits_get_gratwlen(
03208                    raw_headers[uves_chip_get_index(chip_id)][i], chip_id),
03209                "Error reading central wavelength of input frame number %d", i+1);
03210             
03211             assure( fabs((w-wlen)/wlen) < 0.01, CPL_ERROR_INCOMPATIBLE_INPUT,
03212                 "Mis-matching input frame central wavelengths: "
03213                 "%e (frame 1) != %e (frame %d)", wlen, w, i+1);
03214         }
03215         }
03216     }
03217     }
03218     
03219   cleanup:
03220     uves_free_image(&temp_image[0]);
03221     uves_free_image(&temp_image[1]);
03222     uves_free_propertylist(&temp_header[0]);
03223     uves_free_propertylist(&temp_header[1]);
03224     
03225     if (cpl_error_get_code() != CPL_ERROR_NONE) {
03226     if (raw_headers[0] != NULL) {
03227         int i;
03228         for (i = 0; i < frameset_size; i++)    {
03229         if (raw_headers[0] != NULL) uves_free_propertylist(&raw_headers[0][i]);
03230         if (raw_headers[1] != NULL) uves_free_propertylist(&raw_headers[1][i]);
03231         }
03232     }
03233     cpl_free(raw_headers[0]); raw_headers[0] = NULL;
03234     cpl_free(raw_headers[1]); raw_headers[1] = NULL;
03235     
03236     uves_free_imagelist(&images[0]);
03237     uves_free_imagelist(&images[1]);
03238     
03239     uves_free_propertylist(&rotated_header[0]);
03240     uves_free_propertylist(&rotated_header[1]);
03241     }
03242 
03243     return cpl_error_get_code();
03244 }
03245 
03246 
03247 /*----------------------------------------------------------------------------*/
03264 /*----------------------------------------------------------------------------*/
03265 cpl_error_code
03266 uves_load_orderpos(const cpl_frameset *frames,
03267            bool flames,
03268            const char **raw_filename,
03269            cpl_image *raw_image[2],
03270            uves_propertylist *raw_header[2], 
03271            uves_propertylist *rotated_header[2], bool *blue)
03272 {
03273     const char *tags[4];
03274 
03275     int number_of_tags = sizeof(tags) / sizeof(char *);
03276     int indx;
03277 
03278     /* Warning: Duplicate logic. The number of tags must match the size of the
03279        tags array defined above */
03280     tags[0] = UVES_ORDER_FLAT(flames, false); /* red */
03281     tags[1] = UVES_ORDER_FLAT(flames, true);  /* blue */
03282     tags[2] = UVES_STD_STAR(false);
03283     tags[3] = UVES_STD_STAR(true);
03284 
03285     if (flames)
03286     {
03287         *blue = false;
03288         number_of_tags = 1;
03289 
03290         check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx,
03291                            NULL),
03292            "Could not find raw frame (%s) in SOF", 
03293            tags[0]);
03294         
03295     }
03296     else
03297     {    
03298         check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx,
03299                            NULL),
03300            "Could not find raw frame (%s, %s, %s, or %s) in SOF", 
03301            tags[0], tags[1], tags[2], tags[3]);
03302         
03303         *blue = (indx == 1) || (indx == 3);
03304     }
03305 
03306     /* Load the image */
03307     check( load_raw_image(*raw_filename,
03308               CPL_TYPE_DOUBLE,
03309               flames,
03310               *blue,
03311               raw_image,
03312               raw_header,
03313               rotated_header),
03314        "Error loading image from file '%s'", *raw_filename);
03315     
03316     passure( !flames || !(*blue), "%d %d",
03317          flames, *blue );
03318 
03319   cleanup:
03320     if (cpl_error_get_code() != CPL_ERROR_NONE)
03321     {
03322         *raw_filename = NULL;
03323     }
03324     
03325     return cpl_error_get_code();
03326 }
03327 
03328 /*----------------------------------------------------------------------------*/
03344 /*----------------------------------------------------------------------------*/
03345 cpl_error_code
03346 uves_load_formatcheck(const cpl_frameset *frames,
03347               bool flames,
03348               const char **raw_filename,
03349               cpl_image *raw_image[2],
03350               uves_propertylist *raw_header[2], 
03351               uves_propertylist *rotated_header[2], bool *blue)
03352 {
03353     const char *tags[2];
03354     int number_of_tags = sizeof(tags) / sizeof(char *);
03355     int indx;
03356 
03357     tags[0] = UVES_FORMATCHECK(flames, false);   /* red */
03358     tags[1] = UVES_FORMATCHECK(flames, true);    /* blue */
03359     if (flames)
03360     {
03361         *blue = false;
03362         number_of_tags = 1;
03363 
03364         check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
03365            "Could not find raw frame (%s) in SOF",
03366            tags[0]);
03367     }
03368     else
03369     {
03370         check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
03371            "Could not find raw frame (%s or %s) in SOF", 
03372            tags[0], tags[1]);
03373         
03374         *blue = (indx == 1);
03375     }
03376 
03377     /* Load the image */
03378     check( load_raw_image(*raw_filename,
03379               CPL_TYPE_DOUBLE,
03380               flames,
03381               *blue,
03382               raw_image,
03383               raw_header,
03384               rotated_header),
03385        "Error loading image from file '%s'", *raw_filename);
03386    
03387   cleanup:
03388     if (cpl_error_get_code() != CPL_ERROR_NONE) 
03389     {
03390         *raw_filename = NULL;
03391     }
03392     return cpl_error_get_code();
03393 }
03394 
03395 /*----------------------------------------------------------------------------*/
03414 /*----------------------------------------------------------------------------*/
03415 void uves_load_cd_align(const cpl_frameset *frames,
03416             const char **raw_filename1,
03417             const char **raw_filename2,
03418             cpl_image *raw_image1[2],
03419             cpl_image *raw_image2[2],
03420             uves_propertylist *raw_header1[2], 
03421             uves_propertylist *raw_header2[2], 
03422             uves_propertylist *rotated_header1[2], 
03423             uves_propertylist *rotated_header2[2], 
03424             bool *blue)
03425 {
03426     const char *tags[2];
03427     int number_of_tags = sizeof(tags) / sizeof(char *);
03428     int indx;
03429     bool flames = false;
03430     const cpl_frame *frame;
03431 
03432     tags[0] = UVES_CD_ALIGN(false);   /* red */
03433     tags[1] = UVES_CD_ALIGN(true);    /* blue */
03434 
03435     check( *raw_filename1 = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
03436        "Could not find raw frame (%s or %s) in SOF", 
03437        tags[0], tags[1]);
03438     
03439     *blue = (indx == 1);
03440 
03441     assure( cpl_frameset_count_tags(frames, tags[indx]) == 2,
03442         CPL_ERROR_ILLEGAL_INPUT,
03443         "%d %s frames found. Exactly 2 required",
03444         cpl_frameset_count_tags(frames, tags[indx]), tags[indx] );
03445 
03446     /* Load the two frames */
03447     {
03448     int n = 1;
03449     for (frame = cpl_frameset_get_first_const(frames);
03450          frame != NULL;
03451          frame = cpl_frameset_get_next_const(frames))
03452         {
03453         if (strcmp(cpl_frame_get_tag(frame), tags[indx]) == 0)
03454             {
03455             if (n == 1)
03456                 {
03457                 *raw_filename1 = cpl_frame_get_filename(frame);
03458                 }
03459             else
03460                 {
03461                 *raw_filename2 = cpl_frame_get_filename(frame);
03462                 }
03463             
03464             check( load_raw_image(n == 1 ? 
03465                           *raw_filename1 :
03466                           *raw_filename2,
03467                           CPL_TYPE_DOUBLE,
03468                           flames,
03469                           *blue,
03470                           n == 1 ?
03471                           raw_image1 :
03472                           raw_image2,
03473                           n == 1 ?
03474                           raw_header1 :
03475                           raw_header2,
03476                           n == 1 ?
03477                           rotated_header1 :
03478                           rotated_header2),
03479                    "Error loading image from file '%s'",
03480                    n == 1 ? *raw_filename1 : *raw_filename2);
03481 
03482             n++;
03483             }
03484         }
03485     }
03486     
03487   cleanup:
03488     if (cpl_error_get_code() != CPL_ERROR_NONE) 
03489     {
03490         *raw_filename1 = NULL;
03491         *raw_filename2 = NULL;
03492     }
03493     
03494     return;
03495 }
03496 
03497 
03498 /*----------------------------------------------------------------------------*/
03519 /*----------------------------------------------------------------------------*/
03520 void
03521 uves_load_arclamp(const cpl_frameset *frames,
03522           bool flames,
03523           const char **raw_filename, 
03524           cpl_image *raw_image[2], uves_propertylist *raw_header[2],
03525           uves_propertylist *rotated_header[2], bool *blue,
03526           bool *sim_cal)
03527 {
03528     const char *tags[4];
03529 
03530     int number_of_tags = sizeof(tags) / sizeof(char *);
03531     int indx;
03532 
03533     /* Warning: duplicate logic. Array size above must match */
03534     if (flames)
03535     {
03536         assure_nomsg( sim_cal != NULL, CPL_ERROR_NULL_INPUT );
03537 
03538         tags[0] = UVES_ARC_LAMP(flames, true);  /* blue flag not used */
03539         tags[1] = FLAMES_FIB_SCI_SIM;
03540 
03541         number_of_tags = 2;
03542         *blue = false;
03543 
03544         check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
03545            "Could not find raw frame (%s or %s) in SOF", 
03546            tags[0], tags[1]);
03547         
03548         *sim_cal = (indx == 1);
03549     }
03550     else
03551     {
03552         tags[0] = UVES_ARC_LAMP(flames, true);
03553         tags[1] = UVES_ARC_LAMP(flames, false);
03554         tags[2] = UVES_ECH_ARC_LAMP(true);
03555         tags[3] = UVES_ECH_ARC_LAMP(false);
03556 
03557         check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
03558            "Could not find raw frame (%s, %s, %s or %s) in SOF", 
03559            tags[0], tags[1], tags[2], tags[3]);
03560         
03561         *blue = (indx == 0 || indx == 2);
03562     }
03563     
03564     /* Load the image */
03565     check( load_raw_image(*raw_filename,
03566               CPL_TYPE_DOUBLE,
03567               flames,
03568               *blue,
03569               raw_image,
03570               raw_header,
03571               rotated_header),
03572        "Error loading image from file '%s'", *raw_filename);
03573 
03574   cleanup:
03575     if (cpl_error_get_code() != CPL_ERROR_NONE) {
03576     *raw_filename = NULL;
03577     uves_free_image       (raw_image);
03578     uves_free_propertylist(raw_header);
03579     }
03580     return;
03581 }
03582 
03583 /*----------------------------------------------------------------------------*/
03598 /*----------------------------------------------------------------------------*/
03599 cpl_error_code
03600 uves_load_science(const cpl_frameset *frames, const char **raw_filename, 
03601           cpl_image *raw_image[2], 
03602           uves_propertylist *raw_header[2], 
03603           uves_propertylist *rotated_header[2], 
03604           bool *blue,
03605           const char **sci_type)
03606 {
03607     /* Note: the two following arrays must match */
03608     const char *tags[] = 
03609     { 
03610         UVES_SCIENCE(true), UVES_SCIENCE(false),
03611         UVES_SCI_EXTND(true), UVES_SCI_EXTND(false),
03612         UVES_SCI_POINT(true), UVES_SCI_POINT(false),
03613         UVES_SCI_SLICER(true), UVES_SCI_SLICER(false),
03614         UVES_TFLAT(true), UVES_TFLAT(false) 
03615     };
03616 
03617     const char *type[] = 
03618     {
03619         "SCIENCE", "SCIENCE",
03620         "SCI_EXTND", "SCI_EXTND",
03621         "SCI_POINT", "SCI_POINT",
03622         "SCI_SLICER", "SCI_SLICER",
03623         "TFLAT", "TFLAT",
03624     };
03625 
03626     int number_of_tags = sizeof(tags) / sizeof(char *);
03627     int indx;
03628     bool flames = false;
03629 
03630     check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
03631        "No science frame (%s, %s, %s, %s, %s, %s, %s, %s, %s or %s) in SOF", 
03632        tags[0], tags[1], tags[2], tags[3], 
03633        tags[4], tags[5], tags[6], tags[7], tags[7], tags[8]);
03634 
03635     *blue = (indx % 2 == 0);
03636     *sci_type = type[indx];
03637     
03638     /* Load the image */
03639     check( load_raw_image(*raw_filename,
03640               CPL_TYPE_DOUBLE,
03641               flames,
03642               *blue,
03643               raw_image,
03644               raw_header,
03645               rotated_header),
03646        "Error loading image from file '%s'", *raw_filename);
03647   cleanup:
03648     if (cpl_error_get_code() != CPL_ERROR_NONE)
03649     {
03650         *raw_filename = NULL;
03651         uves_free_image       (raw_image);
03652         uves_free_propertylist(raw_header);
03653     }
03654     return cpl_error_get_code();
03655 }
03656 
03657 /*----------------------------------------------------------------------------*/
03674 /*----------------------------------------------------------------------------*/
03675 cpl_error_code
03676 uves_load_standard(const cpl_frameset *frames, const char **raw_filename, 
03677            cpl_image *raw_image[2],
03678            uves_propertylist *raw_header[2], 
03679            uves_propertylist *rotated_header[2], bool *blue)
03680 {
03681     const char *tags[] = { UVES_STD_STAR(true), UVES_STD_STAR(false) };
03682     int number_of_tags = sizeof(tags) / sizeof(char *);
03683     int indx;
03684     bool flames = false;
03685     
03686     check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
03687        "Could not identify raw frame (%s or %s) in SOF", tags[0], tags[1]);
03688 
03689     *blue = (indx == 0);
03690     
03691     /* Load the image */
03692     check( load_raw_image(*raw_filename,
03693               CPL_TYPE_DOUBLE,
03694               flames,
03695               *blue,
03696               raw_image,
03697               raw_header,
03698               rotated_header),
03699        "Error loading image from file '%s'", *raw_filename);
03700 
03701   cleanup:
03702     if (cpl_error_get_code() != CPL_ERROR_NONE)
03703     {
03704         *raw_filename = NULL;
03705         uves_free_image       (raw_image);
03706         uves_free_propertylist(raw_header);
03707     }
03708     return cpl_error_get_code();
03709 }
03710 
03711 /*----------------------------------------------------------------------------*/
03727 /*----------------------------------------------------------------------------*/
03728 
03729 cpl_error_code
03730 uves_load_drs(const cpl_frameset *frames, 
03731           bool flames,
03732           const char *chip_name,
03733           const char **drs_filename, 
03734           uves_propertylist **drs_header,
03735           enum uves_chip chip)
03736 {
03737     const char *tags[1];
03738     int number_of_tags = sizeof(tags) / sizeof(char *);
03739     int extension;
03740     int indx;
03741     
03742     *drs_header = NULL;
03743     tags[0]   = UVES_DRS_SETUP(flames, chip);
03744     extension = UVES_DRS_SETUP_EXTENSION(chip);
03745 
03746     check( *drs_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
03747        "Could not find DRS table (%s) in SOF", tags[0]);
03748     
03749     /* Load the header */
03750     check( *drs_header = uves_propertylist_load(*drs_filename,
03751                            extension),
03752        "Could not load header from extension %d of file '%s'", extension, *drs_filename);
03753 
03754     check_nomsg( uves_warn_if_chip_names_dont_match(*drs_header, chip_name, chip) );
03755 
03756   cleanup:
03757     if (cpl_error_get_code() != CPL_ERROR_NONE) {
03758     *drs_filename = NULL;
03759     uves_free_propertylist(drs_header);
03760     }
03761     return cpl_error_get_code();
03762 }
03763 
03764 /*----------------------------------------------------------------------------*/
03772 /*----------------------------------------------------------------------------*/
03773 cpl_image *
03774 uves_load_weights(const cpl_frameset *frames, const char **weights_filename,
03775                   enum uves_chip chip)
03776 {
03777     cpl_image *weights = NULL;
03778     const char *tags[1];
03779     int number_of_tags = sizeof(tags) / sizeof(char *);
03780     int extension = 0;
03781     int indx;
03782 
03783     assure( weights_filename != NULL, CPL_ERROR_NULL_INPUT, "Null filename");
03784     
03785     tags[0]   = UVES_WEIGHTS(chip);
03786 
03787     check( *weights_filename = uves_find_frame(frames, 
03788                                                tags, number_of_tags, &indx, NULL), 
03789            "Could not find '%s' in frame set", tags[0]);
03790     
03791     check( weights = cpl_image_load(*weights_filename,
03792                                     CPL_TYPE_DOUBLE,           /* Convert to this type */
03793                                     0,                         /* plane number */
03794                                     extension                  /* Extension number */
03795                ),
03796            "Could not load master bias from extension %d of file '%s'", 
03797            extension, *weights_filename);
03798 
03799   cleanup:
03800     return weights;
03801 }
03802 
03803 
03804 /*----------------------------------------------------------------------------*/
03820 /*----------------------------------------------------------------------------*/
03821 
03822 cpl_error_code
03823 uves_load_mbias(const cpl_frameset *frames, const char *chip_name,
03824         const char **mbias_filename, 
03825         cpl_image **mbias, uves_propertylist **mbias_header, enum uves_chip chip)
03826 {
03827     const char *tags[1];
03828     int number_of_tags = sizeof(tags) / sizeof(char *);
03829     int extension;
03830     int indx;
03831     
03832     *mbias        = NULL;
03833     *mbias_header = NULL;
03834 
03835     tags[0]   = UVES_MASTER_BIAS          (chip);
03836     extension = UVES_MASTER_BIAS_EXTENSION(chip);
03837     
03838     check( *mbias_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
03839        "Could not find '%s' in frame set", tags[0]);
03840     
03841     /* Load the mbias image */
03842     check( *mbias = cpl_image_load(*mbias_filename,
03843                    CPL_TYPE_DOUBLE,           /* Convert to this type */
03844                    0,                         /* plane number */
03845                    extension                  /* Extension number */
03846            ),
03847        "Could not load master bias from extension %d of file '%s'", 
03848        extension, *mbias_filename);
03849 
03850     /* Load the header */
03851     check( *mbias_header = uves_propertylist_load(*mbias_filename,
03852                          extension),
03853        "Could not load header from extension %d of file '%s'", 
03854        extension, *mbias_filename);
03855 
03856     check_nomsg( uves_warn_if_chip_names_dont_match(*mbias_header, chip_name, chip) );
03857 
03858   cleanup:
03859     if (cpl_error_get_code() != CPL_ERROR_NONE) 
03860     {
03861         *mbias_filename = NULL;
03862         uves_free_image(mbias);
03863         uves_free_propertylist(mbias_header);
03864     }
03865     return cpl_error_get_code();
03866 }
03867 
03868 
03869 /*----------------------------------------------------------------------------*/
03885 /*----------------------------------------------------------------------------*/
03886 
03887 cpl_error_code
03888 uves_load_master_formatcheck(const cpl_frameset *frames, const char *chip_name,
03889         const char **mform_filename, 
03890         cpl_image **mform, uves_propertylist **mform_header, enum uves_chip chip)
03891 {
03892     const char *tags[1];
03893     int number_of_tags = sizeof(tags) / sizeof(char *);
03894     int extension;
03895     int indx;
03896     
03897     *mform        = NULL;
03898     *mform_header = NULL;
03899 
03900     tags[0]   = UVES_MASTER_ARC_FORM          (chip);
03901     extension = UVES_MASTER_ARC_FORM_EXTENSION(chip);
03902     
03903     check( *mform_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
03904        "Could not find '%s' in frame set", tags[0]);
03905     
03906     /* Load the mbias image */
03907     check( *mform = cpl_image_load(*mform_filename,
03908                    CPL_TYPE_DOUBLE,           /* Convert to this type */
03909                    0,                         /* plane number */
03910                    extension                  /* Extension number */
03911            ),
03912        "Could not load master formatcheck from extension %d of file '%s'", 
03913        extension, *mform_filename);
03914 
03915     /* Load the header */
03916     
03917     check( *mform_header = uves_propertylist_load(*mform_filename,
03918                          extension),
03919        "Could not load header from extension %d of file '%s'", 
03920        extension, *mform_filename);
03921 
03922     check_nomsg( uves_warn_if_chip_names_dont_match(*mform_header, chip_name, chip) );
03923 
03924   cleanup:
03925     if (cpl_error_get_code() != CPL_ERROR_NONE) 
03926     {
03927         *mform_filename = NULL;
03928         uves_free_image(mform);
03929         uves_free_propertylist(mform_header);
03930     }
03931     return cpl_error_get_code();
03932 }
03933 
03934 /*----------------------------------------------------------------------------*/
03950 /*----------------------------------------------------------------------------*/
03951 
03952 cpl_error_code
03953 uves_load_mdark(const cpl_frameset *frames, const char *chip_name,
03954         const char **mdark_filename, cpl_image **mdark,
03955         uves_propertylist **mdark_header, enum uves_chip chip)
03956 {
03957     const char *tags[2];
03958     int number_of_tags = sizeof(tags) / sizeof(char *);
03959     int extension;
03960     int indx;
03961     
03962     *mdark        = NULL;
03963     *mdark_header = NULL;
03964 
03965     tags[0]   = UVES_MASTER_DARK          (chip);
03966     tags[1]   = UVES_MASTER_PDARK         (chip);
03967     extension = UVES_MASTER_DARK_EXTENSION(chip);
03968     
03969     check( *mdark_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
03970        "Could not find %s or %s in frame set", tags[0], tags[1]);
03971     
03972     /* Load the mdark image */
03973     check( *mdark = cpl_image_load(*mdark_filename,
03974                    CPL_TYPE_DOUBLE,           /* Convert to this type */
03975                    0,                         /* plane number */
03976                    extension                  /* Extension number */
03977            ),
03978        "Could not load master dark from extension %d of file '%s'", 
03979        extension, *mdark_filename);
03980 
03981     /* Load the header */
03982     check( *mdark_header = uves_propertylist_load(*mdark_filename,
03983                          extension),
03984        "Could not load header from extension %d of file '%s'", 
03985        extension, *mdark_filename);
03986 
03987     check_nomsg( uves_warn_if_chip_names_dont_match(*mdark_header, chip_name, chip) );
03988 
03989   cleanup:
03990     if (cpl_error_get_code() != CPL_ERROR_NONE) 
03991     {
03992         *mdark_filename = NULL;
03993         uves_free_image(mdark);
03994         uves_free_propertylist(mdark_header);
03995     }
03996     return cpl_error_get_code();
03997 }
03998 /*----------------------------------------------------------------------------*/
04014 /*----------------------------------------------------------------------------*/
04015 void
04016 uves_load_ref_flat(const cpl_frameset *frames, const char *chip_name,
04017            const char **filename, cpl_image **rflat,
04018            uves_propertylist **rflat_header, enum uves_chip chip)
04019 {
04020     const char *tags[1];
04021     int number_of_tags = sizeof(tags) / sizeof(char *);
04022     int extension;
04023     int indx;
04024     
04025     *rflat        = NULL;
04026     *rflat_header = NULL;
04027 
04028     tags[0]   = UVES_REF_TFLAT(chip);
04029     extension = UVES_MASTER_FLAT_EXTENSION(chip);
04030 
04031     check( *filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
04032        "Could not find %s in frame set", tags[0]);
04033     
04034     check( *rflat = cpl_image_load(*filename,
04035                    CPL_TYPE_DOUBLE,           /* Convert to this type */
04036                    0,                         /* plane number */
04037                    extension                  /* Extension number */
04038            ),
04039        "Could not load reference dark from extension %d of file '%s'", 
04040        extension, *filename);
04041 
04042     check( *rflat_header = uves_propertylist_load(*filename,
04043                          extension),
04044        "Could not load header from extension %d of file '%s'", 
04045        extension, *filename);
04046 
04047     check_nomsg( uves_warn_if_chip_names_dont_match(*rflat_header, chip_name, chip) );
04048 
04049   cleanup:
04050     if (cpl_error_get_code() != CPL_ERROR_NONE) 
04051     {
04052         *filename = NULL;
04053         uves_free_image(rflat);
04054         uves_free_propertylist(rflat_header);
04055     }
04056 
04057     return;
04058 }
04059 
04060 /*----------------------------------------------------------------------------*/
04076 /*----------------------------------------------------------------------------*/
04077 
04078 cpl_error_code
04079 uves_load_mflat_const(const cpl_frameset *frames, const char *chip_name,
04080               const char **mflat_filename, 
04081               cpl_image **mflat, uves_propertylist **mflat_header, 
04082               enum uves_chip chip,
04083               const cpl_frame **mflat_frame)
04084 {
04085     const char *tags[6];
04086     int number_of_tags = sizeof(tags) / sizeof(char *);
04087     int extension;
04088     int indx;
04089     
04090     *mflat        = NULL;
04091     *mflat_header = NULL;
04092 
04093     tags[0]   = UVES_REF_TFLAT            (chip);   /* Use REF TFLAT, rather than MASTER_TFLAT */
04094     tags[1]   = UVES_MASTER_FLAT          (chip);
04095     tags[2]   = UVES_MASTER_DFLAT         (chip);
04096     tags[3]   = UVES_MASTER_IFLAT         (chip);
04097     tags[4]   = UVES_MASTER_TFLAT         (chip);
04098     tags[5]   = UVES_MASTER_SCREEN_FLAT   (chip);
04099     extension = UVES_MASTER_FLAT_EXTENSION(chip);
04100     
04101     check( *mflat_filename = uves_find_frame(frames, tags, number_of_tags, &indx,
04102                          mflat_frame), 
04103        "Could not find '%s', '%s', '%s', '%s' or '%s' in frame set", 
04104        tags[0], tags[1], tags[2], tags[3], tags[4]);
04105     
04106     /* Load the mflat image */
04107     check( *mflat = cpl_image_load(*mflat_filename,
04108                    CPL_TYPE_DOUBLE,           /* Convert to this type */
04109                    0,                         /* plane number */
04110                    extension                  /* Extension number */
04111            ),
04112        "Could not load master flat from extension %d of file '%s'", 
04113        extension, *mflat_filename);
04114 
04115     /* Load the header */
04116     check( *mflat_header = uves_propertylist_load(*mflat_filename,
04117                          extension),
04118        "Could not load header from extension %d of file '%s'", 
04119        extension, *mflat_filename);
04120 
04121     check_nomsg( uves_warn_if_chip_names_dont_match(*mflat_header, chip_name, chip) );
04122 
04123   cleanup:
04124     if (cpl_error_get_code() != CPL_ERROR_NONE) 
04125     {
04126         *mflat_filename = NULL;
04127         uves_free_image(mflat);
04128         uves_free_propertylist(mflat_header);
04129     }
04130     return cpl_error_get_code();
04131 }
04132 
04133 /*----------------------------------------------------------------------------*/
04148 /*----------------------------------------------------------------------------*/
04149 cpl_error_code
04150 uves_load_mflat(cpl_frameset *frames, const char *chip_name,
04151         const char **mflat_filename, 
04152         cpl_image **mflat, uves_propertylist **mflat_header, enum uves_chip chip,
04153         cpl_frame **mflat_frame)
04154 {
04155     return uves_load_mflat_const((const cpl_frameset *)frames,
04156                  chip_name,
04157                  mflat_filename,
04158                  mflat, mflat_header, chip,
04159                  (const cpl_frame **) mflat_frame);
04160 }
04161 
04162 /*----------------------------------------------------------------------------*/
04194 /*----------------------------------------------------------------------------*/
04195 cpl_error_code
04196 uves_load_ordertable(const cpl_frameset *frames, 
04197                      bool flames,
04198                      const char *chip_name,
04199                      const char **ordertable_filename, 
04200                      cpl_table **ordertable, 
04201                      uves_propertylist **ordertable_header, 
04202                      uves_propertylist **ordertable_xheader, 
04203                      polynomial **order_locations, 
04204                      cpl_table **traces, 
04205                      int *tab_in_out_oshift,
04206                      double *tab_in_out_yshift,
04207                      int ** fib_msk,
04208                      double ** fib_pos,
04209                      enum uves_chip chip,
04210                      bool guess_table)
04211 {
04212     uves_propertylist *midas_header = NULL;      /* Table header if midas format */
04213     uves_propertylist *prime_header = NULL;      /* Prime header if flames  */
04214     const char *tags[1];
04215     int number_of_tags = sizeof(tags) / sizeof(char *);
04216     bool format_is_midas;
04217     int *tioo = NULL;
04218     double *tioy = NULL;
04219     int indx;
04220 
04221     double *fibre_pos = NULL;
04222     int *fibre_mask = NULL;
04223 
04224     if (guess_table)
04225     {
04226         tags[0] = UVES_GUESS_ORDER_TABLE(flames, chip);
04227     }
04228     else
04229     {
04230         tags[0] = UVES_ORDER_TABLE(flames, chip);
04231     }
04232 
04233     check( *ordertable_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
04234        "No order table (%s) found in SOF", tags[0]);
04235     
04236     check( *ordertable = cpl_table_load(*ordertable_filename,
04237                     UVES_ORDER_TABLE_EXTENSION,
04238                     1),                /* Mark identified 
04239                                   invalid values? (1=yes) */
04240        "Error loading order table from extension %d of file '%s'", 
04241        UVES_ORDER_TABLE_EXTENSION, *ordertable_filename);
04242     
04243     assure(ordertable_header != NULL,CPL_ERROR_NULL_INPUT,
04244            "NULL primary header uves_propertylist variable header");
04245     check( *ordertable_header = uves_propertylist_load(*ordertable_filename, 0),
04246        "Could not load header from extension 0 of '%s'", *ordertable_filename);
04247 
04248     if(ordertable_xheader != NULL) {
04249 
04250     check( *ordertable_xheader = uves_propertylist_load(*ordertable_filename, 1),
04251        "Could not load header from extension 1 of '%s'", *ordertable_filename);
04252 
04253 
04254 
04255     }
04256     check_nomsg( uves_warn_if_chip_names_dont_match(*ordertable_header, chip_name, chip) );
04257     
04258     check(uves_check_if_format_is_midas(*ordertable_header,&format_is_midas),
04259       "Error getting FITS format");
04260 
04261 
04262     if (!format_is_midas && !flames)
04263     {
04264             /* The format check and order position recipes create order tables
04265                with different column names. Rename if necessary. 
04266 
04267                This is a workaround for the problem that different recipes
04268                create the same products (order tables and line tables).
04269                The true solution would be to remove the format check recipe from
04270                the recution cascade, and use the theoretical physical model to
04271                bootstrap the order definition and wavelength calibration.
04272             */
04273             if (cpl_table_has_column(*ordertable, "ORDER"))
04274                 {
04275                     cpl_table_name_column(*ordertable, "ORDER", "Order");
04276                 }
04277             if (cpl_table_has_column(*ordertable, "YFIT"))
04278                 {
04279                     cpl_table_name_column(*ordertable, "YFIT", "Yfit");
04280                 }
04281 
04282         if (order_locations != NULL)
04283         {
04284             check( *order_locations = 
04285                load_polynomial(*ordertable_filename, UVES_ORDER_TABLE_EXTENSION_POLY),
04286                "Could not read polynomial from extension %d of file '%s'",
04287                UVES_ORDER_TABLE_EXTENSION_POLY, *ordertable_filename);
04288         }
04289 
04290         if (traces != NULL)
04291         {
04292             check( *traces = cpl_table_load(*ordertable_filename,
04293                             UVES_ORDER_TABLE_EXTENSION_FIBRE,
04294                             1),    /* Mark identified 
04295                                   invalid values? (1=yes) */
04296                "Error loading fibre table from extension %d of file '%s'", 
04297                UVES_ORDER_TABLE_EXTENSION_FIBRE, *ordertable_filename);
04298         }
04299     }
04300     else
04301         /* MIDAS format, or FLAMES */
04302     {
04303         /* Rename */
04304         check(( cpl_table_cast_column (*ordertable, "ORDER", "Order", CPL_TYPE_INT),
04305                 cpl_table_erase_column(*ordertable, "ORDER")),
04306               "Error casting and renaming column 'ORDER'");
04307         
04308         check( cpl_table_name_column(*ordertable, "YFIT", "Yfit"),
04309                "Error renaming column 'YFIT'");
04310                 
04311         //check( midas_header = uves_propertylist_load(*ordertable_filename, 1),
04312     //      "Could not load header from extension 1 of '%s'", 
04313     //     *ordertable_filename);
04314       check(midas_header = uves_propertylist_load(*ordertable_filename, 1),
04315          "Could not load header from extension 1 of '%s'",
04316          *ordertable_filename);
04317 
04318     if(flames) {
04319           check(prime_header = uves_propertylist_load(*ordertable_filename, 0),
04320          "Could not load header from extension 0 of '%s'",
04321          *ordertable_filename);
04322       check_nomsg(uves_propertylist_append(midas_header,prime_header));
04323         }
04324 
04325         /* Load polynomial named 'COEFF' from descriptors in extension 1 */
04326         if (order_locations != NULL)
04327         {
04328             check( *order_locations = 
04329            uves_polynomial_convert_from_plist_midas(midas_header, "COEFF",-1),
04330                    "Error reading polynomial from %s", *ordertable_filename);
04331         }
04332 
04333 
04334         if (flames && tab_in_out_oshift != NULL )
04335         {
04336             /* Get tab_in_out_oshift */
04337             int tioo_length;
04338                     cpl_type tioo_type;
04339 
04340             check( tioo = uves_read_midas_array(
04341                    midas_header, "TAB_IN_OUT_OSHIFT", &tioo_length,
04342                                &tioo_type, NULL),
04343                "Error reading TAB_IN_OUT_OSHIFT from MIDAS header");
04344 
04345                     assure( tioo_type == CPL_TYPE_INT, CPL_ERROR_TYPE_MISMATCH,
04346                             "Type of TAB_IN_OUT_OSHIFT is %s, double expected",
04347                             uves_tostring_cpl_type(tioo_type));
04348 
04349             if (tioo_length != 1)
04350             {
04351                 uves_msg_warning("Length of TAB_IN_OUT_OSHIFT array is %d; "
04352                          "%d expected", tioo_length, 1);
04353             }
04354 
04355             *tab_in_out_oshift = tioo[0];
04356             
04357             uves_msg_debug("TAB_IN_OUT_OSHIFT = %d", *tab_in_out_oshift);
04358 
04359         }
04360         
04361         if (flames && tab_in_out_yshift != NULL)
04362         {
04363             /* Get tab_in_out_yshift */
04364             int tioy_length;
04365                     cpl_type tioy_type;
04366 
04367             check( tioy = uves_read_midas_array(
04368                    midas_header, "TAB_IN_OUT_YSHIFT", &tioy_length,
04369                                &tioy_type, NULL),
04370                "Error reading TAB_IN_OUT_YSHIFT from MIDAS header");
04371 
04372                     assure( tioy_type == CPL_TYPE_DOUBLE, CPL_ERROR_TYPE_MISMATCH,
04373                             "Type of TAB_IN_OUT_YSHIFT is %s, double expected",
04374                             uves_tostring_cpl_type(tioy_type));
04375 
04376             if (tioy_length != 1)
04377             {
04378                 uves_msg_warning("Length of TAB_IN_OUT_YSHIFT array is %d; "
04379                          "%d expected", tioy_length, 1);
04380             }
04381 
04382             *tab_in_out_yshift = tioy[0];
04383 
04384             uves_msg_debug("TAB_IN_OUT_YSHIFT = %f", *tab_in_out_yshift);
04385         }
04386         
04387         if (traces != NULL)
04388         {
04389             *traces = uves_ordertable_traces_new();
04390             
04391             if (!flames)
04392             /* UVES: one trace with zero offset */
04393             {
04394                 int fibre_ID = 0;
04395                 double fibre_offset = 0.0;
04396                 int fibre_msk = 1;
04397                 uves_ordertable_traces_add(*traces, 
04398                                fibre_ID,
04399                                fibre_offset,
04400                                fibre_msk);
04401             }
04402             else
04403             /* FLAMES */
04404             {
04405 
04406                 int fibre_pos_length;
04407                 int fibre_mask_length;
04408                             cpl_type fibre_pos_type;
04409                             cpl_type fibre_mask_type;
04410                 int fibre_ID;
04411 
04412                 check( fibre_pos = uves_read_midas_array(
04413                        midas_header, "FIBREPOS", &fibre_pos_length,
04414                                        &fibre_pos_type, NULL),
04415                    "Error reading FIBREPOS from MIDAS header");
04416 
04417                             assure( fibre_pos_type == CPL_TYPE_DOUBLE, CPL_ERROR_TYPE_MISMATCH,
04418                                     "Type of FIBREPOS is %s, double expected",
04419                                     uves_tostring_cpl_type(fibre_pos_type));
04420 
04421                 check( fibre_mask = uves_read_midas_array(
04422                        midas_header, "FIBREMASK", &fibre_mask_length,
04423                                        &fibre_mask_type, NULL),
04424                    "Error reading FIBREMASK from MIDAS header");
04425 
04426                             assure( fibre_mask_type == CPL_TYPE_INT, CPL_ERROR_TYPE_MISMATCH,
04427                                     "Type of FIBREMASK is %s, double expected",
04428                                     uves_tostring_cpl_type(fibre_mask_type));
04429                             
04430                 assure( fibre_pos_length == fibre_mask_length,
04431                     CPL_ERROR_INCOMPATIBLE_INPUT,
04432                     "FIBREMASK has length %d, but "
04433                     "FIBREPOS has length %d",
04434                     fibre_mask_length, fibre_pos_length );
04435             
04436                 *fib_pos= cpl_malloc(sizeof(double) * fibre_pos_length);
04437                 *fib_msk= cpl_malloc(sizeof(int) * fibre_mask_length);
04438 
04439                 for (fibre_ID = 0; fibre_ID < fibre_mask_length; fibre_ID++)
04440                 {
04441                     uves_msg_debug("Found trace %d, position %f (%s)",
04442                            fibre_ID, fibre_pos[fibre_ID],
04443                            fibre_mask[fibre_ID] ? 
04444                            "enabled" : "disabled");
04445                     uves_ordertable_traces_add(*traces, 
04446                                    fibre_ID,
04447                                    fibre_pos[fibre_ID],
04448                                    fibre_mask[fibre_ID]);
04449                     (*fib_pos)[fibre_ID]=fibre_pos[fibre_ID];
04450                     (*fib_msk)[fibre_ID]=fibre_mask[fibre_ID];
04451                 }
04452             }
04453         }
04454     }
04455 
04456   cleanup:
04457     uves_free_propertylist(&midas_header);
04458     uves_free_double(&fibre_pos);
04459     uves_free_int(&fibre_mask);
04460     uves_free_int(&tioo);
04461     uves_free_double(&tioy);
04462     uves_free_propertylist(&prime_header);
04463 
04464     if (cpl_error_get_code() != CPL_ERROR_NONE) 
04465     {
04466         *ordertable_filename = NULL;
04467         uves_free_table       (ordertable);
04468         uves_free_propertylist(ordertable_header);
04469         if (order_locations != NULL) uves_polynomial_delete(order_locations);
04470         if (traces != NULL)          uves_free_table       (traces);
04471     }
04472     return cpl_error_get_code();
04473 }
04474 
04475 
04476 
04477 /*--------------------------------------------------------------------------*/
04486 /*--------------------------------------------------------------------------*/
04487 
04488 
04489 cpl_error_code
04490 uves_check_if_format_is_midas(uves_propertylist* header, bool* format_is_midas)
04491 {
04492  
04493   /* Determine format of order table and read the polynomial */
04494   if (uves_propertylist_contains(header, UVES_DRS_ID)) {
04495 
04496 
04497     const char* drs_id=NULL;
04498 
04499     check( drs_id = uves_pfits_get_drs_id(header), "Error reading DRS ID");
04500     if (strstr(drs_id, "CPL") != NULL || 
04501     strstr(drs_id, "cpl") != NULL) {
04502       *format_is_midas = false;
04503       uves_msg_debug("Order table was written by CPL");
04504     } else if (strstr(drs_id, "MIDAS") != NULL || 
04505                strstr(drs_id, "midas") != NULL) {
04506       *format_is_midas = true;
04507       uves_msg_low("Order table was written by MIDAS");
04508     } else {
04509       assure ( false, CPL_ERROR_ILLEGAL_INPUT, 
04510            "Unrecognized order table format, DRS_ID = '%s'", drs_id);
04511     }
04512   } else {
04513 
04514     *format_is_midas = true;
04515     uves_msg_debug("No '%s' keyword found. Assuming MIDAS format", UVES_DRS_ID);
04516   }
04517  
04518  cleanup:
04519   return cpl_error_get_code();
04520 
04521 }
04522 
04523 /*--------------------------------------------------------------------------*/
04533 /*--------------------------------------------------------------------------*/
04534 
04535 static cpl_error_code
04536 create_column_pixelsize(cpl_table *linetable)
04537 {
04538     polynomial *p = NULL;
04539     cpl_table *t = NULL;
04540     double d1, d2;
04541     int i;
04542     int degree = 3;
04543     
04544     /* Remove rows with Ident = 0 (unidentified lines) */
04545     check( t = uves_extract_table_rows(linetable, "Ident", CPL_GREATER_THAN, 0.1),
04546        "Error deleting rows with Ident=0");
04547     
04548     /* Create column Aux := Ident * Order  */
04549     check(( cpl_table_duplicate_column(t, "Aux", t, "Ident"),
04550         cpl_table_multiply_columns(t, "Aux", "Order")),
04551       "Error creating 'Aux' column");
04552     
04553     check( p = uves_polynomial_regression_1d(t, 
04554                          "X", "Aux", NULL,
04555                          degree,
04556                          NULL, NULL,
04557                          NULL,
04558                          -1),
04559        "Regression failed");
04560     
04561     check( d1 = uves_polynomial_get_coeff_1d(p, 1),
04562        "Error reading polynomial coefficient");
04563     
04564     check( d2 = uves_polynomial_get_coeff_1d(p, 2),
04565        "Error reading polynomial coefficient");
04566     
04567     cpl_table_new_column(linetable, LINETAB_PIXELSIZE, CPL_TYPE_DOUBLE);
04568     
04569     for (i = 0; i < cpl_table_get_nrow(linetable); i++)
04570     {
04571         int x;
04572         int order;
04573         double pixelsize;
04574         double ident;
04575         
04576         check(( x     = cpl_table_get_double(linetable, "X", i, NULL),
04577             order = cpl_table_get_int   (linetable, "Order", i, NULL),
04578             ident = cpl_table_get_double(linetable, "Ident", i, NULL)),
04579           "Error reading line table");
04580         
04581         assure( order != 0, CPL_ERROR_ILLEGAL_INPUT, "Illegal order number: %d", order);
04582         
04583         /* 
04584          * MIDAS approximates
04585          * d(lambda m)/dx (x,m)   =  d1 + 2*d2*x
04586          *
04587          * where the polynomial itself is ... + d1*x + d2*x^2 + ...
04588          */
04589         pixelsize = (d1 + 2*d2* x) / order;
04590 //        pixelsize = uves_polynomial_derivative_2d(dispersion_relation, x, order, 1)/order;
04591         
04592         if (ident > 0.01)
04593         {
04594             cpl_table_set_double(linetable, LINETAB_PIXELSIZE, i, pixelsize);
04595         }
04596         else
04597         {
04598             cpl_table_set_invalid(linetable, LINETAB_PIXELSIZE, i);
04599         }
04600     }
04601     
04602   cleanup:
04603     uves_free_table(&t);
04604     uves_polynomial_delete(&p);
04605     return cpl_error_get_code();
04606 }
04607 
04608 
04609 
04610 /*----------------------------------------------------------------------------*/
04637 /*----------------------------------------------------------------------------*/
04638 static void
04639 align_order_line_table(cpl_table *linetable, const polynomial *absolute_order,
04640                uves_propertylist **linetable_header,
04641                const polynomial *order_locations, int minorder, int maxorder)
04642 {
04643     polynomial *absord = NULL;
04644 
04645     assure ( order_locations  != NULL, CPL_ERROR_NULL_INPUT, 
04646              "Null order locations polynomial!");
04647 
04648     assure ( absolute_order  != NULL, CPL_ERROR_NULL_INPUT, 
04649              "Null absolute order pllynomial!");
04650     assure( cpl_table_has_column(linetable, "X"   ), CPL_ERROR_DATA_NOT_FOUND, 
04651         "Missing line table column 'X'");
04652     assure( cpl_table_has_column(linetable, "Ynew"), CPL_ERROR_DATA_NOT_FOUND, 
04653         "Missing line table column 'Ynew'");
04654     assure( cpl_table_has_column(linetable, "Order"), CPL_ERROR_DATA_NOT_FOUND, 
04655         "Missing line table column 'Order'");
04656     
04657     assure( cpl_table_get_column_type(linetable, "X") == CPL_TYPE_DOUBLE,
04658         CPL_ERROR_TYPE_MISMATCH, "Line table column 'X' has type %s (double expected))",
04659         uves_tostring_cpl_type(cpl_table_get_column_type(linetable, "X")) );
04660     
04661     assure( cpl_table_get_column_type(linetable, "Ynew") == CPL_TYPE_DOUBLE,
04662         CPL_ERROR_TYPE_MISMATCH, "Line table column 'Ynew' has type %s (double expected))",
04663         uves_tostring_cpl_type(cpl_table_get_column_type(linetable, "Ynew")) );
04664     
04665     assure( cpl_table_get_column_type(linetable, "Y") == CPL_TYPE_INT,
04666         CPL_ERROR_TYPE_MISMATCH, "Line table column 'Y' has type %s (integer expected))",
04667         uves_tostring_cpl_type(cpl_table_get_column_type(linetable, "Y")) );
04668 
04669 
04670     if (linetable_header != NULL)
04671     /* then correct first/abs order keywords */
04672     {
04673         int line_first, line_last;
04674         int ord_first, ord_last;
04675             {
04676 
04677                 int maxx;
04678                 int minx;
04679                 int x, y, order, absorder;  /* At chip center */
04680                 int coeff;
04681                 
04682 
04683                 maxx = uves_round_double(cpl_table_get_column_max(linetable, "X"));
04684 
04685                 minx = uves_round_double(cpl_table_get_column_min(linetable, "X"));
04686                 
04687                 assure( 1 <= minx && minx <= maxx, CPL_ERROR_ILLEGAL_INPUT,
04688                         "Illegal min/max line x positions: %d/%d, must be > 1", 
04689                         minx, maxx);
04690         
04691                 /* Center of chip */
04692                 x = (minx + maxx) / 2;
04693                 order = (minorder + maxorder) / 2;
04694 
04695                 y = uves_polynomial_evaluate_2d(order_locations, x, order);
04696                 if (uves_polynomial_derivative_2d(absolute_order, x, y, 2) > 0) {
04697                     coeff = +1;
04698                 }
04699                 else {
04700                     coeff = -1;
04701                 } 
04702 
04703     assure ( order_locations  != NULL, CPL_ERROR_NULL_INPUT, 
04704              "Null order locations polynomial!");
04705 
04706 
04707                 absorder = uves_round_double(uves_polynomial_evaluate_2d(absolute_order, x, y));
04708 
04709 
04710                 uves_msg_debug("Absolute order polynomial at (%d, %d) = %f, "
04711                                "rounding to %d", x, y, 
04712                                uves_polynomial_evaluate_2d(absolute_order, x, y), absorder);
04713 
04714                 ord_first = absorder + (minorder - order) * coeff;
04715                 ord_last  = absorder + (maxorder - order) * coeff;
04716             }
04717 
04718             check( line_first =
04719            uves_pfits_get_firstabsorder(*linetable_header),
04720            "Could not read order number from line table header");
04721         
04722         check( line_last  =
04723            uves_pfits_get_lastabsorder (*linetable_header),
04724            "Could not read order number from line table header");
04725         
04726         uves_msg_debug("Order table range: %d - %d. Line table range: %d - %d",
04727                ord_first, ord_last, line_first, line_last);
04728         
04729         if (line_first != ord_first ||
04730         line_last  != ord_last)
04731         {
04732             uves_msg_warning("Provided line and order tables are incompatible. "
04733                      "Line table contains orders %d - %d. "
04734                      "Order table contains orders %d - %d. "
04735                      "Correcting on the fly",
04736                      line_first, line_last, ord_first, ord_last);
04737             
04738             check( uves_pfits_set_firstabsorder(*linetable_header,
04739                             ord_first),
04740                "Could not write corrected first absolute order number");
04741             check( uves_pfits_set_lastabsorder(*linetable_header,
04742                                ord_last),
04743                "Could not write corrected first absolute order number");
04744 
04745             uves_msg_debug("Setting line table order range = %d - %d",
04746                    ord_first, ord_last);
04747         }
04748     }
04749     /* This 'Y' column is the relative order number in linetables
04750        but the absolute order number (and therefore equal to
04751        the 'order' column) in line guess tables (!!) 
04752     */
04753 
04754     {
04755     double epsilon = 0.01; /* Must be larger than machine precision but
04756                   less than the typical difference between
04757                   absolute/relative numbering (~100) 
04758                    */
04759 
04760     if (fabs(cpl_table_get_column_median(linetable, "Y") - 
04761          cpl_table_get_column_median(linetable, "Order")) > epsilon)
04762 
04763         /* If column 'Y' is different from 'Order', 
04764            then 'Y' is the relative order number and
04765            should be corrected (if there is an inconsistency).
04766 
04767            For now, simply delete the 'Y' column because it is
04768            not used later. If the 'Y' column will be used later,
04769            it must be corrected at this place.
04770         */
04771         {
04772         uves_msg_debug("Removing line table column 'Y'");
04773         cpl_table_erase_column(linetable, "Y");
04774         }
04775     }
04776     
04777   cleanup:
04778     uves_polynomial_delete(&absord);
04779 }
04780 
04781 
04782 /*----------------------------------------------------------------------------*/
04821 /*----------------------------------------------------------------------------*/
04822 void
04823 uves_load_linetable(const cpl_frameset *frames, 
04824                     bool flames,
04825                     const char *chip_name,
04826                     const polynomial *order_locations, int minorder, int maxorder,
04827                     const char **linetable_filename,
04828                     cpl_table **linetable,
04829                     uves_propertylist **linetable_header,
04830                     polynomial **dispersion_relation,
04831                     polynomial **absolute_order,
04832                     enum uves_chip chip, int trace_id, int window)
04833 {
04834     uves_propertylist *primary_header = NULL;
04835     uves_propertylist *header         = NULL;
04836     uves_propertylist *midas_header   = NULL;       /* MIDAS extension header */
04837     int *absorders                   = NULL;       /* Absolute order numbers */
04838     cpl_table *temp                  = NULL;
04839     polynomial *absolute_order_local = NULL;
04840     const char *tags[3];
04841     int number_of_tags = sizeof(tags) / sizeof(char *);
04842     const char *drs_id;
04843     bool format_is_midas;               /* Was file written by CPL or MIDAS? */
04844     int base_extension;                 /* Last extension (e.g. 0) before 
04845                        extension with line table */
04846     int indx;
04847 
04848     if (flames)
04849     {
04850         tags[0] = UVES_GUESS_LINE_TABLE(flames, chip);
04851         tags[1] = UVES_LINE_TABLE(flames, chip);
04852         tags[2] = UVES_LINE_TABLE(flames, chip);
04853         number_of_tags = 3;
04854         
04855         check( *linetable_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
04856            "No line table (%s, %s or %s) found in SOF", tags[0], tags[1], tags[2]);
04857     }
04858     else
04859     {
04860         tags[0] = UVES_LINE_TABLE(flames, chip);
04861         tags[1] = UVES_LINE_TABLE(flames, chip);
04862         tags[2] = UVES_GUESS_LINE_TABLE(flames, chip);
04863         
04864         /* For backwards compatibility with MIDAS, 
04865            also look for LINE_TABLE_chip%d */
04866         if (cpl_frameset_find_const(frames, tags[0]) == NULL &&
04867             cpl_frameset_find_const(frames, tags[1]) == NULL &&
04868             cpl_frameset_find_const(frames, tags[2]) == NULL)
04869         {
04870             uves_msg_debug("No %s", tags[0]);
04871             
04872             if (window >= 1)
04873             {
04874                 /* Look for LINE_TABLE_BLUEwindow */
04875                 
04876                 tags[0] = UVES_LINE_TABLE_MIDAS(chip, window);
04877                 tags[1] = UVES_LINE_TABLE_MIDAS(chip, window);
04878                 tags[2] = UVES_LINE_TABLE_MIDAS(chip, window);
04879                 
04880                 uves_msg_debug("Trying %s", tags[0]);
04881             }
04882             if (window <= 0)
04883             {
04884                 /* Look for any LINE_TABLE_BLUEi */
04885                 tags[0] = UVES_LINE_TABLE_MIDAS(chip, 1);
04886                 tags[1] = UVES_LINE_TABLE_MIDAS(chip, 2);
04887                 tags[2] = UVES_LINE_TABLE_MIDAS(chip, 3);
04888                 
04889                 uves_msg_debug("Trying %s, %s or %s", tags[0], tags[1], tags[2]);
04890             }
04891         }
04892         
04893         check( *linetable_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
04894            "No line table (%s, %s or %s) found in SOF", tags[0], tags[1], tags[2]);
04895     }
04896     
04897     /* Read primary header */
04898     check( primary_header = uves_propertylist_load(*linetable_filename, 0),
04899        "Could not load primary header of '%s'", *linetable_filename);  
04900 
04901     check_nomsg( uves_warn_if_chip_names_dont_match(primary_header, chip_name, chip) );
04902     
04903     /* Determine format of line table */
04904     if (uves_propertylist_contains(primary_header, UVES_DRS_ID))
04905     {
04906         check( drs_id = uves_pfits_get_drs_id(primary_header), "Error reading DRS ID");
04907         if (strstr(drs_id, "CPL") != NULL || strstr(drs_id, "cpl") != NULL)
04908         {
04909             format_is_midas = false;
04910             uves_msg_debug("Line table was written by CPL");
04911         }
04912         else if (strstr(drs_id, "MIDAS") != NULL || strstr(drs_id, "midas") != NULL)
04913         {
04914             format_is_midas = true;
04915             uves_msg_debug("Line table was written by MIDAS");
04916         }
04917         else
04918         {
04919             assure ( false,
04920                  CPL_ERROR_ILLEGAL_INPUT,
04921                  "Unrecognized line table format, DRS_ID = '%s'", drs_id);
04922         }
04923     }
04924     else
04925     {
04926         format_is_midas = true;
04927         uves_msg_debug("No '%s' keyword found. Assuming MIDAS format", UVES_DRS_ID);
04928     }
04929 
04930     if (format_is_midas || flames)
04931     {
04932         if (!flames)
04933         {
04934             assure( trace_id == 0 && (window == -1 || (1 <= window && window <= 3)), 
04935                 CPL_ERROR_UNSUPPORTED_MODE,
04936                 "Cannot read (fibre, window) = (%d, %d) from MIDAS line table", 
04937                 trace_id, window);
04938             
04939             base_extension = 0;
04940         }
04941         else
04942         {
04943 
04944       if(trace_id > 0) {
04945 
04946             assure( ((1<= trace_id && trace_id <= 9) && (window == -1)), 
04947                 CPL_ERROR_UNSUPPORTED_MODE,
04948                 "Cannot read (fibre, window) = (%d, %d) from MIDAS line table", 
04949                 trace_id, window);
04950             
04951             base_extension = 0;
04952 
04953 
04954       } else {
04955 
04956             uves_msg_warning("Assuming line table is guess table");
04957             base_extension = 0;
04958       }
04959         }
04960     }
04961     else
04962     /* Find table extension containing the line table for the specified trace and window */
04963     {
04964         int nextensions;
04965         bool found;
04966         
04967         check( nextensions = uves_get_nextensions(*linetable_filename),
04968            "Error reading number of extensions of file '%s'", *linetable_filename);
04969         header = NULL;
04970         found = false;
04971 
04972             uves_msg_debug("Number of extensions = %d", nextensions);
04973 
04974         for (base_extension = 1; base_extension < nextensions && !found; base_extension++)
04975         {
04976             int header_trace;
04977             int header_window;
04978             
04979             /* Read header trace & window info */
04980             check(( uves_free_propertylist(&header),
04981                header = uves_propertylist_load(*linetable_filename, base_extension)),
04982                "Could not header of extension %d of '%s'", 
04983               base_extension, *linetable_filename);
04984             
04985             check( header_trace  = uves_pfits_get_traceid     (header),
04986                "Error reading trace ID from header of extension %d of '%s'",
04987                base_extension, *linetable_filename);
04988             
04989             check( header_window = uves_pfits_get_windownumber(header),
04990                "Error reading window number from header of extension %d of '%s'",
04991                base_extension, *linetable_filename);
04992             
04993                     uves_msg_debug("Found (trace, window) = (%d, %d), need (%d, %d)",
04994                                    header_trace, header_window,
04995                                    trace_id, window);
04996 
04997             found = ( (trace_id == header_trace) && 
04998                   (window == -1 || window == header_window) );
04999         }
05000         
05001         assure( found,
05002             CPL_ERROR_ILLEGAL_INPUT,
05003             "Line table (trace, window) = (%d, %d) is not present in file '%s'",
05004             trace_id, window, *linetable_filename);
05005 
05006         /* Let 'base_extension' be the first extension before 
05007            the proper extension was found (0, 3, 6, ...) */
05008         base_extension -= 2;
05009         /* ...and incremented in for-loop */
05010     }
05011 
05012     check( *linetable = cpl_table_load(*linetable_filename,
05013                        base_extension + UVES_LINE_TABLE_EXTENSION,
05014                        1),              /* Mark identified 
05015                                invalid values? (1=yes) */
05016        "Error loading line table from extension %d of file '%s'", 
05017        base_extension + UVES_LINE_TABLE_EXTENSION, *linetable_filename);
05018 
05019     /* Read header of table extension if requested */
05020     if (linetable_header != NULL)
05021     {
05022         check( *linetable_header = 
05023            uves_propertylist_load(*linetable_filename, 
05024                      base_extension + UVES_LINE_TABLE_EXTENSION),
05025            "Could not load header of extension %d of '%s'", 
05026            base_extension + UVES_LINE_TABLE_EXTENSION, *linetable_filename);
05027 
05028         if (format_is_midas)
05029         {
05030             int size = 0;
05031                     cpl_type type;
05032             absorders = uves_read_midas_array(*linetable_header, "ORDER", &size,
05033                                                       &type, NULL);
05034                     
05035                     assure( type == CPL_TYPE_INT, CPL_ERROR_TYPE_MISMATCH,
05036                             "Type of ORDER is %s, int expected",
05037                             uves_tostring_cpl_type(type));
05038 
05039             assure( size == 2, 
05040                 CPL_ERROR_ILLEGAL_INPUT,
05041                 "'ORDER' array has size %d. Size 2 expected.", size);
05042             check(( uves_pfits_set_firstabsorder(*linetable_header, absorders[0]),
05043                 uves_pfits_set_lastabsorder(*linetable_header, absorders[1])),
05044               "Error updating table header");
05045         }        
05046     }
05047     
05048     /* Read the polynomials if requested */
05049     if (format_is_midas)
05050     {
05051         /* Rename & cast order/ident/X columns */
05052         check(( cpl_table_cast_column(*linetable, "X", "xxxx", CPL_TYPE_DOUBLE),
05053             cpl_table_erase_column(*linetable, "X"),
05054             cpl_table_name_column(*linetable, "xxxx", "X")),
05055           "Error casting and renaming column 'X'");
05056         
05057         check(( cpl_table_cast_column(*linetable, "YNEW", "xxxx", CPL_TYPE_DOUBLE),
05058             cpl_table_erase_column(*linetable, "YNEW"),
05059             cpl_table_name_column(*linetable, "xxxx", "Ynew")),
05060           "Error casting and renaming column 'YNEW'");
05061         
05062         check(( cpl_table_cast_column(*linetable, "Y", "xxxx", CPL_TYPE_INT),
05063             cpl_table_erase_column(*linetable, "Y"),
05064             cpl_table_name_column(*linetable, "xxxx", "Y")),
05065            "Error casting and renaming column 'Y'");
05066 
05067         check(( cpl_table_cast_column(*linetable, "ORDER", "Order", CPL_TYPE_INT),
05068             cpl_table_erase_column(*linetable, "ORDER")),
05069            "Error casting and renaming column 'ORDER'");
05070            
05071         check( cpl_table_name_column(*linetable, "IDENT", "Ident"),
05072            "Error renaming column 'IDENT'");
05073 
05074         check( midas_header = uves_propertylist_load(
05075                *linetable_filename, 
05076                base_extension + UVES_LINE_TABLE_EXTENSION),
05077            "Could not load header of extension %d of '%s'",
05078            base_extension + UVES_LINE_TABLE_EXTENSION, *linetable_filename);
05079         
05080         if (dispersion_relation != NULL) {
05081             if (trace_id > 0) {
05082                 check( *dispersion_relation = 
05083                        uves_polynomial_convert_from_plist_midas(midas_header,
05084                                                                 "REGR", trace_id),
05085                        "Error reading polynomial 'REGR%d' from '%s'",
05086                        trace_id,
05087                        *linetable_filename);
05088             }
05089             else {
05090                 check( *dispersion_relation = 
05091                        uves_polynomial_convert_from_plist_midas(midas_header,
05092                                                                 "REGR", -1),
05093                        "Error reading polynomial 'REGR' from '%s'",
05094                        *linetable_filename);
05095             }
05096         }
05097         
05098     
05099       check( absolute_order_local = 
05100              uves_polynomial_convert_from_plist_midas(midas_header, "RORD",-1),
05101              "Error reading polynomial 'RORD' from '%s'", *linetable_filename);
05102       
05103       /* For FLAMES data, it seems that the polynomial is half an order shifted
05104          (for unknown reasons) */
05105         if (flames)
05106             {
05107                 check_nomsg( uves_polynomial_shift(absolute_order_local, 0, 0.5) );
05108             }
05109     }
05110     else
05111     /* CPL format */
05112     {
05113         /* physmod + wavecal recipes use different naming conventions,
05114            workaround for this:
05115         */
05116         if (cpl_table_has_column(*linetable, "YNEW"))
05117         {
05118             cpl_table_name_column(*linetable, "YNEW", "Ynew");
05119         }
05120 
05121         if (dispersion_relation != NULL)
05122         {
05123             check( *dispersion_relation = load_polynomial(
05124                    *linetable_filename,
05125                    base_extension + UVES_LINE_TABLE_EXTENSION_DISPERSION),
05126                "Could not read polynomial from extension %d of file '%s'", 
05127                base_extension + UVES_LINE_TABLE_EXTENSION_DISPERSION,
05128                *linetable_filename);
05129         }
05130 
05131         check( absolute_order_local =
05132            load_polynomial(*linetable_filename, 
05133                    base_extension + UVES_LINE_TABLE_EXTENSION_ABSORDER),
05134            "Could not read polynomial from extension %d of file '%s'",
05135            base_extension + UVES_LINE_TABLE_EXTENSION_ABSORDER, *linetable_filename);
05136     }
05137         
05138     if (absolute_order != NULL)
05139     {
05140         *absolute_order = uves_polynomial_duplicate(absolute_order_local);
05141     }
05142     
05143 
05144     check( align_order_line_table(
05145            *linetable, absolute_order_local, linetable_header, 
05146            order_locations, minorder, maxorder),
05147        "Error while aligning line/order tables");
05148 
05149 
05150     /* Remove all other columns than 'Ident', 'Order', 'X', 'Pixelsize' */
05151     {
05152     const char *colname;
05153 
05154     /* Loop through all columns */
05155 
05156     /* It is undefined behaviour (for a reason!) to loop through
05157        columns while deleting some of them. Therefore, copy the
05158        structure of the linetable to another (empty) table */
05159     
05160     uves_free_table(&temp);
05161     check(( temp = cpl_table_new(0),
05162         cpl_table_copy_structure(temp, *linetable)),
05163            "Error duplicating line table column structure");
05164     
05165     colname = cpl_table_get_column_name(temp);
05166     while (colname != NULL)
05167         {
05168         if (!(strcmp(colname, "X"        ) == 0 ||
05169               strcmp(colname, "Order"    ) == 0 ||
05170               strcmp(colname, "Ident"    ) == 0 ||
05171           strcmp(colname, "FIBRE"    ) == 0 ||
05172           strcmp(colname, "Fibre"    ) == 0 ||
05173               strcmp(colname, LINETAB_PIXELSIZE) == 0))
05174             {
05175             cpl_table_erase_column(*linetable, colname);
05176             uves_msg_debug("Removing unused column '%s'", colname);
05177             }
05178         
05179         /* Call with NULL argument to get the next column name */
05180         colname = cpl_table_get_column_name(NULL);
05181         }
05182     }
05183     
05184     /* support MIDAS
05185      * Calculate 'Pixel' column (lower case) for MIDAS tables 
05186      */
05187     if ( !cpl_table_has_column(*linetable, LINETAB_PIXELSIZE) )
05188     {
05189         check( create_column_pixelsize(*linetable),
05190            "Error adding 'Pixelsize' column");
05191     }
05192 
05193     /* Remove un-identified lines (where Ident = invalid or Ident = zero) ... */
05194     check( uves_erase_invalid_table_rows(*linetable, "Ident"),
05195        "Error deleting rows with illegal 'Ident' value");
05196 
05197     check( uves_erase_table_rows(*linetable, "Ident", CPL_LESS_THAN, 0.01),
05198        "Error deleting rows with illegal 'Ident' value");
05199     
05200     /* Check for any other invalid value */
05201     assure( uves_erase_invalid_table_rows(*linetable, NULL) == 0, CPL_ERROR_ILLEGAL_INPUT,
05202         "After deleting rows with invalid 'Ident' values, "
05203         "the table in extension %d of file '%s' still contains invalid rows",
05204         base_extension + UVES_LINE_TABLE_EXTENSION, *linetable_filename);
05205     
05206     /* Sort line table by 'Order' (ascending), then 'X' (ascending) */
05207     check( uves_sort_table_2(*linetable, "Order", "X", false, false), "Error sorting line table");
05208     
05209   cleanup:
05210     uves_free_propertylist(&primary_header);
05211     uves_free_propertylist(&header);
05212     uves_free_propertylist(&midas_header);
05213     uves_free_table(&temp);
05214     uves_polynomial_delete(&absolute_order_local);
05215     cpl_free(absorders);
05216     if (cpl_error_get_code() != CPL_ERROR_NONE) {
05217     *linetable_filename = NULL;
05218     uves_free_table(linetable);
05219     if (dispersion_relation != NULL) uves_polynomial_delete(dispersion_relation);
05220     if (absolute_order      != NULL) uves_polynomial_delete(absolute_order);
05221     }
05222     return;
05223 }
05224 
05225 /*----------------------------------------------------------------------------*/
05229 /*----------------------------------------------------------------------------*/
05230 void
05231 uves_load_linetable_const(const cpl_frameset *frames, 
05232                           bool flames,
05233                           const char *chip_name,
05234                           const polynomial *order_locations, int minorder, int maxorder,
05235                           const char **linetable_filename,
05236                           const cpl_table **linetable,
05237                           const uves_propertylist **linetable_header,
05238                           const polynomial **dispersion_relation,
05239                           polynomial **absolute_order,
05240                           enum uves_chip chip, int trace_id, int window)
05241 {
05242     uves_load_linetable(frames, flames, chip_name, order_locations, 
05243                         minorder, maxorder, 
05244                         linetable_filename, 
05245                         (cpl_table **)linetable, 
05246                         (uves_propertylist **)linetable_header,
05247                         (polynomial **)dispersion_relation, 
05248                         absolute_order,
05249                         chip, trace_id, window);
05250 }
05251 
05252 
05253 /*----------------------------------------------------------------------------*/
05268 /*----------------------------------------------------------------------------*/
05269 
05270 cpl_error_code
05271 uves_load_response_curve(const cpl_frameset *frames, const char *chip_name,
05272              const char **response_filename, 
05273              cpl_image **response_curve,
05274              cpl_table **master_response,
05275              uves_propertylist **response_header, enum uves_chip chip)
05276 {
05277     const char *tags[2];
05278     int number_of_tags = sizeof(tags) / sizeof(char *);
05279     int extension;
05280     int indx;
05281     
05282     *response_curve  = NULL;
05283     *response_header = NULL;
05284     *master_response = NULL;
05285     
05286     tags[0]   = UVES_INSTR_RESPONSE (chip);
05287     tags[1]   = UVES_MASTER_RESPONSE(chip);
05288     
05289     check( *response_filename = uves_find_frame(frames, tags, number_of_tags, &indx, 
05290                         NULL), 
05291        "Could not find '%s' in frame set", tags[0]);
05292     
05293     if (indx == 0)
05294     {
05295         extension = UVES_INSTR_RESPONSE_EXTENSION(chip);
05296         
05297         /* Load the response image
05298            
05299         Note: Even if the response curve was saved as
05300         a FITS file with NAXIS=1, cpl_image_load() will
05301         create an image of size nx1, which is just
05302         what we want
05303         */
05304         check( *response_curve = cpl_image_load(*response_filename,
05305                             CPL_TYPE_DOUBLE, /* Convert to this type */
05306                             0,               /* plane number */
05307                             extension        /* Extension number */
05308                ),
05309            "Could not load response curve from extension %d of file '%s'", 
05310            extension, *response_filename);
05311 
05312         /* Load the header */
05313         check( *response_header = uves_propertylist_load(*response_filename,
05314                                 extension),
05315            "Could not load header from extension %d of file '%s'", 
05316            extension, *response_filename);
05317 
05318         check_nomsg( uves_warn_if_chip_names_dont_match(*response_header, chip_name, chip) );
05319     }
05320     else
05321     /* Master response */
05322     {
05323         extension = UVES_MASTER_RESPONSE_EXTENSION(chip);
05324         
05325         check( *master_response = cpl_table_load(*response_filename,
05326                              UVES_LINE_INTMON_TABLE_EXTENSION,
05327                              1),   /* Mark identified 
05328                                   invalid values? (1=yes) */
05329            "Error master response curve from extension %d of file '%s'", 
05330            extension, *response_filename);           
05331 
05332         /* Convert columns to double */
05333         check(( cpl_table_cast_column(*master_response, "LAMBDA", "LAMBDA_double", 
05334                       CPL_TYPE_DOUBLE),
05335             cpl_table_erase_column(*master_response, "LAMBDA"),
05336             cpl_table_name_column(*master_response, "LAMBDA_double", "LAMBDA")),
05337           "Could not cast column 'LAMBDA'");
05338 
05339         check(( cpl_table_cast_column(*master_response, "FLUX_CONV", "FLUX_CONV_double", 
05340                       CPL_TYPE_DOUBLE),
05341             cpl_table_erase_column(*master_response, "FLUX_CONV"),
05342             cpl_table_name_column(*master_response, "FLUX_CONV_double", "FLUX_CONV")),
05343           "Could not cast column 'FLUX_CONV'");
05344 
05345         /* Do not need the header, which also does not contain 
05346            keywords needed for uves_warn_if_chip_names_dont_match() */
05347     }
05348     
05349   cleanup:
05350     if (cpl_error_get_code() != CPL_ERROR_NONE) 
05351     {
05352         *response_filename = NULL;
05353         uves_free_image(response_curve);
05354         uves_free_propertylist(response_header);
05355     }
05356     return cpl_error_get_code();
05357 }
05358 
05359 
05360 /*----------------------------------------------------------------------------*/
05370 /*----------------------------------------------------------------------------*/
05371 cpl_error_code uves_load_lineintmon(const cpl_frameset *frames, 
05372                     const char **line_intmon_filename, 
05373                     cpl_table **line_intmon)
05374 {
05375     const char *tags[1] = {UVES_LINE_INTMON_TABLE};    
05376 
05377     int number_of_tags = sizeof(tags) / sizeof(char *);
05378     int indx;
05379     
05380     /* Get filename */
05381     check( *line_intmon_filename = uves_find_frame(frames, tags, number_of_tags, 
05382                            &indx, NULL),
05383        "No line intensity table (%s) found in SOF", tags[0]);
05384     
05385     /* Load table */
05386     check( *line_intmon = cpl_table_load(*line_intmon_filename,
05387                      UVES_LINE_INTMON_TABLE_EXTENSION,
05388                      1),         /* Mark identified 
05389                             invalid values? (1=yes) */
05390        "Error loading line reference table from extension %d of file '%s'", 
05391        UVES_LINE_INTMON_TABLE_EXTENSION, *line_intmon_filename);
05392 
05393     check(( cpl_table_cast_column(*line_intmon, "WAVE", "Wave", CPL_TYPE_DOUBLE),
05394         cpl_table_erase_column(*line_intmon, "WAVE")),
05395       "Could not cast and rename column");
05396     
05397     /* Sort table by 'Wave' (ascending) */
05398     check(  uves_sort_table_1(*line_intmon, "Wave", false), "Error sorting table");
05399     
05400   cleanup:
05401     if (cpl_error_get_code() != CPL_ERROR_NONE) 
05402     {
05403         *line_intmon_filename = NULL;
05404         uves_free_table(line_intmon);
05405     }
05406     return cpl_error_get_code();
05407 }
05408 
05409 
05410 /*----------------------------------------------------------------------------*/
05423 /*----------------------------------------------------------------------------*/
05424 void
05425 uves_load_corvel(const cpl_frameset *frames,
05426          enum uves_chip chip,
05427          cpl_table **corvel,
05428          uves_propertylist **corvel_header,
05429          const char **corvel_filename)
05430 {
05431     const char *tags[1];
05432     int number_of_tags = sizeof(tags) / sizeof(char *);
05433     int indx;
05434     int extension;
05435 
05436     tags[0] = FLAMES_CORVEL(chip);
05437 
05438     assure_nomsg( corvel != NULL, CPL_ERROR_NULL_INPUT );
05439     assure_nomsg( corvel_filename != NULL, CPL_ERROR_NULL_INPUT );
05440 
05441     /* Get filename */
05442     check( *corvel_filename = uves_find_frame(frames, tags, number_of_tags, 
05443                           &indx, NULL),
05444        "No velocity correction table (%s) found in SOF", tags[0]);
05445     
05446     /* Load table */
05447     extension = 1;
05448     check( *corvel = cpl_table_load(*corvel_filename,
05449                     extension,
05450                     1),         /* Mark identified 
05451                            invalid values? (1=yes) */
05452        "Error loading line reference table from extension %d of file '%s'",
05453        extension, *corvel_filename);
05454 
05455     /* Load header */
05456     if (corvel_header != NULL)
05457     {
05458         extension = 0;
05459         check( *corvel_header = uves_propertylist_load(*corvel_filename,
05460                               extension),
05461            "Could not load header from extension %d of file %s",
05462            extension, *corvel_filename);
05463 
05464     }
05465     
05466   cleanup:
05467     if (cpl_error_get_code() != CPL_ERROR_NONE) 
05468     {
05469         *corvel_filename = NULL;
05470         uves_free_table(corvel);
05471     }
05472     return;
05473 }
05474 
05475 /*----------------------------------------------------------------------------*/
05491 /*----------------------------------------------------------------------------*/
05492 cpl_error_code
05493 uves_load_linerefertable(const cpl_frameset *frames, 
05494              const char **line_refer_filename, 
05495              cpl_table **line_refer, uves_propertylist **line_refer_header)
05496 {
05497     const char *tags[1] = {UVES_LINE_REFER_TABLE};    
05498 
05499     int number_of_tags = sizeof(tags) / sizeof(char *);
05500     int indx;
05501     
05502     /* Get filename */
05503     check( *line_refer_filename = uves_find_frame(frames, tags, number_of_tags, 
05504                           &indx, NULL),
05505        "No line reference table (%s) found in SOF", tags[0]);
05506     
05507     /* Load table */
05508     check( *line_refer = cpl_table_load(*line_refer_filename,
05509                        UVES_LINE_REFER_TABLE_EXTENSION,
05510                        1),         /* Mark identified 
05511                               invalid values? (1=yes) */
05512        "Error loading line reference table from extension %d of file '%s'", 
05513        UVES_LINE_REFER_TABLE_EXTENSION, *line_refer_filename);
05514 
05515     /* Load header if requested */
05516     if (line_refer_header != NULL)
05517     {
05518         check( *line_refer_header = uves_propertylist_load(*line_refer_filename, 0),
05519            "Could not load header of line_refer table in '%s'", *line_refer_filename);
05520     }
05521 
05522     assure( uves_erase_invalid_table_rows(*line_refer, NULL) == 0, CPL_ERROR_ILLEGAL_INPUT,
05523         "Table in extension %d of file '%s' contains invalid rows", 
05524         UVES_LINE_REFER_TABLE_EXTENSION, *line_refer_filename);
05525 
05526     check(( cpl_table_cast_column(*line_refer, "WAVE", "Wave", CPL_TYPE_DOUBLE),
05527         cpl_table_erase_column(*line_refer, "WAVE")),
05528        "Could not cast and rename column");
05529     
05530     /* Write uncertainties of wavelengths.
05531        The value 0.002 is finetuned/retro-fitted to get a chi_sq ~ 1 when
05532        using the new catalogue from
05533 
05534        M. T. Murphy, P. Tzanavaris, J. K. Webb, C. Lovis
05535        "Selection of ThAr lines for wavelength calibration of echelle
05536        spectra and implications for variations in the fine-structure constant",
05537        Submitted to MNRAS
05538     */
05539 
05540 #if 0
05541      check(( cpl_table_duplicate_column(*line_refer, "dWave", *line_refer, "Wave"),
05542            cpl_table_divide_scalar   (*line_refer, "dWave", 300000*10)),
05543        "Error writing wavelength uncertainties");
05544 #else
05545      /* we should do this */
05546     check(( cpl_table_new_column(*line_refer, "dWave", CPL_TYPE_DOUBLE),
05547             cpl_table_fill_column_window(*line_refer,
05548                                          "dWave",
05549                                          0,
05550                                          cpl_table_get_nrow(*line_refer), 0.002)),
05551           "Error writing wavelength uncertainties");
05552 #endif
05553     
05554     /* Sort table by 'Wave' (ascending) */
05555     check(  uves_sort_table_1(*line_refer, "Wave", false), "Error sorting table");
05556     
05557   cleanup:
05558     if (cpl_error_get_code() != CPL_ERROR_NONE) {
05559     *line_refer_filename = NULL;
05560     uves_free_table       (line_refer);
05561     if (line_refer_header != NULL) uves_free_propertylist(line_refer_header);
05562     }
05563     return cpl_error_get_code();
05564 }
05565 
05566 /*----------------------------------------------------------------------------*/
05580 /*----------------------------------------------------------------------------*/
05581 cpl_error_code
05582 uves_load_flux_table(const cpl_frameset *frames, const char **flux_table_filename, 
05583              cpl_table **flux_table)
05584 {
05585     const char *tags[1] = {UVES_FLUX_STD_TABLE};
05586 
05587     int number_of_tags = sizeof(tags) / sizeof(char *);
05588     int indx;
05589     
05590     /* Get filename */
05591     check( *flux_table_filename = uves_find_frame(frames, tags, number_of_tags, 
05592                           &indx, NULL), 
05593        "No standard star flux table (%s) in SOF", tags[0]);
05594 
05595     /* Load table */
05596     check( *flux_table = cpl_table_load(*flux_table_filename,
05597                     UVES_FLUX_STD_TABLE_EXTENSION,
05598                     1),         /* Mark identified 
05599                                invalid values? (1=yes) */
05600        "Error loading flux table from extension %d of file '%s'",
05601        UVES_FLUX_STD_TABLE_EXTENSION, *flux_table_filename);
05602 
05603     if (false)
05604         /* Don't do this, it will remove one std (LTT2415) from the table which has TYPE = NULL.
05605            Instead, set type to "NULL" (this is only used for messages) 
05606         */
05607         {
05608             if (uves_erase_invalid_table_rows(*flux_table, NULL) != 0)
05609                 {
05610                     uves_msg_warning("Table in extension %d of file '%s' contains null values",
05611                                      UVES_FLUX_STD_TABLE_EXTENSION, *flux_table_filename);
05612                 }
05613         }
05614     else
05615         {
05616             int i;
05617             for (i = 0; i < cpl_table_get_nrow(*flux_table); i++)
05618                 {
05619                     if (cpl_table_get_string(*flux_table, "TYPE", i) == NULL)
05620                         {
05621                             cpl_table_set_string(*flux_table, "TYPE", i, "NULL");
05622                         }
05623                 }
05624         }
05625     
05626         
05627   cleanup:
05628     if (cpl_error_get_code() != CPL_ERROR_NONE) 
05629     {
05630         *flux_table_filename = NULL;
05631         uves_free_table(flux_table);
05632     }
05633     return cpl_error_get_code();
05634 }
05635 
05636 
05637 /*----------------------------------------------------------------------------*/
05651 /*----------------------------------------------------------------------------*/
05652 cpl_error_code
05653 uves_load_atmo_ext(const cpl_frameset *frames, const char **atmext_table_filename, 
05654            cpl_table **atmext_table)
05655 {
05656     const char *tags[1] = {UVES_EXTCOEFF_TABLE};
05657     
05658     int number_of_tags = sizeof(tags) / sizeof(char *);
05659     int indx;
05660     
05661     /* Get filename */
05662     check( *atmext_table_filename = uves_find_frame(frames, tags, number_of_tags, 
05663                             &indx, NULL), 
05664        "No atmospheric extinction table (%s) found in SOF", tags[0]);
05665 
05666     /* Load table */
05667     check( *atmext_table = cpl_table_load(*atmext_table_filename,
05668                       UVES_EXTCOEFF_TABLE_EXTENSION,
05669                       1),          /* Mark identified 
05670                               invalid values? (1=yes) */
05671        "Error loading atmospheric extinction table from extension %d of file '%s'",
05672        UVES_EXTCOEFF_TABLE_EXTENSION, *atmext_table_filename);
05673     
05674     assure( uves_erase_invalid_table_rows(*atmext_table, NULL) == 0, CPL_ERROR_ILLEGAL_INPUT,
05675         "Table in extension %d of file '%s' contains invalid rows",
05676         UVES_EXTCOEFF_TABLE_EXTENSION, *atmext_table_filename);
05677     
05678     check( uves_sort_table_1(*atmext_table, "LAMBDA", false),
05679        "Error sorting table");
05680     
05681     /* Convert columns to double */
05682     check(( cpl_table_cast_column(*atmext_table, "LAMBDA", "LAMBDA_double", CPL_TYPE_DOUBLE),
05683         cpl_table_erase_column(*atmext_table, "LAMBDA"),
05684         cpl_table_name_column(*atmext_table, "LAMBDA_double", "LAMBDA")),
05685       "Could not cast column 'LAMBDA'");
05686     
05687     check(( cpl_table_cast_column(*atmext_table, "LA_SILLA", "LA_SILLA_double", CPL_TYPE_DOUBLE),
05688         cpl_table_erase_column(*atmext_table, "LA_SILLA"),
05689         cpl_table_name_column(*atmext_table, "LA_SILLA_double", "LA_SILLA")),
05690       "Could not cast column 'LA_SILLA'");
05691     
05692   cleanup:
05693     if (cpl_error_get_code() != CPL_ERROR_NONE) 
05694     {
05695         *atmext_table_filename = NULL;
05696         uves_free_table(atmext_table);
05697     }
05698     return cpl_error_get_code();
05699 }
05700 /*----------------------------------------------------------------------------*/
05708 /*----------------------------------------------------------------------------*/
05709 char *
05710 uves_guess_order_table_filename(enum uves_chip chip) 
05711 {
05712     return uves_local_filename("orderguesstable", chip, -1, -1);
05713 }
05714 
05715 /*----------------------------------------------------------------------------*/
05723 /*----------------------------------------------------------------------------*/
05724 char *
05725 uves_order_table_filename(enum uves_chip chip) 
05726 {
05727     return uves_local_filename("ordertable", chip, -1, -1);
05728 }
05729 
05730 /*----------------------------------------------------------------------------*/
05737 /*----------------------------------------------------------------------------*/
05738 char *uves_ordef_filename(enum uves_chip chip)
05739 {
05740     return uves_local_filename("order_def", chip, -1, -1);
05741 }
05742 
05743 /*----------------------------------------------------------------------------*/
05751 /*----------------------------------------------------------------------------*/
05752 char *
05753 uves_masterdark_filename(enum uves_chip chip) 
05754 {
05755     return uves_local_filename("masterdark", chip, -1, -1);
05756 }
05757 
05758 
05759 /*----------------------------------------------------------------------------*/
05765 /*----------------------------------------------------------------------------*/
05766 char *
05767 uves_flat_ratio_filename(enum uves_chip chip) 
05768 {
05769     return uves_local_filename("ratio", chip, -1, -1);
05770 }
05771 
05772 /*----------------------------------------------------------------------------*/
05779 /*----------------------------------------------------------------------------*/
05780 char *uves_cd_align_filename(enum uves_chip chip)
05781 {
05782     return uves_local_filename("cd_align", chip, -1, -1);
05783 }
05784 
05785 /*----------------------------------------------------------------------------*/
05793 /*----------------------------------------------------------------------------*/
05794 char *
05795 uves_masterflat_filename(enum uves_chip chip) 
05796 {
05797     return uves_local_filename("masterflat", chip, -1, -1);
05798 }
05799 /*----------------------------------------------------------------------------*/
05807 /*----------------------------------------------------------------------------*/
05808 char *
05809 uves_masterflat_bkg_filename(enum uves_chip chip) 
05810 {
05811     return uves_local_filename("masterflat_bkg", chip, -1, -1);
05812 }
05813 
05814 /*----------------------------------------------------------------------------*/
05822 /*----------------------------------------------------------------------------*/
05823 char *
05824 uves_masterbias_filename(enum uves_chip chip) 
05825 {
05826     return uves_local_filename("masterbias", chip, -1, -1);
05827 }
05828 
05829 /*----------------------------------------------------------------------------*/
05837 /*----------------------------------------------------------------------------*/
05838 char *
05839 uves_guess_line_table_filename(enum uves_chip chip)
05840 {
05841     return uves_local_filename("lineguesstable", chip, -1, -1);
05842 }
05843 /*----------------------------------------------------------------------------*/
05851 /*----------------------------------------------------------------------------*/
05852 char *
05853 uves_line_table_filename(enum uves_chip chip)
05854 {
05855     return uves_local_filename("linetable", chip, -1, -1);
05856 }
05857 
05858 /*----------------------------------------------------------------------------*/
05866 /*----------------------------------------------------------------------------*/
05867 char *
05868 uves_line_table_filename_paf(enum uves_chip chip)
05869 {
05870     return uves_local_filename("linetable_paf", chip, -1, -1);
05871 }
05872 
05873 /*----------------------------------------------------------------------------*/
05881 /*----------------------------------------------------------------------------*/
05882 char *
05883 uves_response_curve_filename(enum uves_chip chip)
05884 {
05885     return uves_local_filename("response", chip, -1, -1);
05886 }
05887 
05888 /*----------------------------------------------------------------------------*/
05896 /*----------------------------------------------------------------------------*/
05897 char *
05898 uves_response_curve_2d_filename(enum uves_chip chip)
05899 {
05900     return uves_local_filename("response_2d", chip, -1, -1);
05901 }
05902 
05903 /*----------------------------------------------------------------------------*/
05911 /*----------------------------------------------------------------------------*/
05912 char *
05913 uves_response_red_standard_filename(enum uves_chip chip)
05914 {
05915     return uves_local_filename("red_std", chip, -1, -1);
05916 }
05917 
05918 /*----------------------------------------------------------------------------*/
05926 /*----------------------------------------------------------------------------*/
05927 char *
05928 uves_response_bkg_standard_filename(enum uves_chip chip)
05929 {
05930     return uves_local_filename("bkg_std", chip, -1, -1);
05931 }
05932 
05933 /*----------------------------------------------------------------------------*/
05941 /*----------------------------------------------------------------------------*/
05942 char *
05943 uves_response_efficiency_filename(enum uves_chip chip)
05944 {
05945     return uves_local_filename("efficiency", chip, -1, -1);
05946 }
05947 
05948 /*----------------------------------------------------------------------------*/
05956 /*----------------------------------------------------------------------------*/
05957 
05958 char *
05959 uves_scired_red_2d_science_filename(enum uves_chip chip)
05960 {
05961     return uves_local_filename("red_2d_science", chip, -1, -1);
05962 }
05963 
05971 /*----------------------------------------------------------------------------*/
05972 
05973 
05974 
05975 char *
05976 uves_scired_red_science_filename(enum uves_chip chip)
05977 {
05978     return uves_local_filename("red_science", chip, -1, -1);
05979 }
05980 /*----------------------------------------------------------------------------*/
05988 /*----------------------------------------------------------------------------*/
05989 char *
05990 uves_scired_red_error_filename(enum uves_chip chip)
05991 {
05992     return uves_local_filename("error_red_science", chip, -1, -1);
05993 }
05994 
05995 /*----------------------------------------------------------------------------*/
06003 /*----------------------------------------------------------------------------*/
06004 char *
06005 uves_scired_red_2d_error_filename(enum uves_chip chip)
06006 {
06007     return uves_local_filename("error_2d_science", chip, -1, -1);
06008 }
06009 
06010 
06011 /*----------------------------------------------------------------------------*/
06019 /*----------------------------------------------------------------------------*/
06020 char *
06021 uves_scired_fluxcal_science_filename(enum uves_chip chip)
06022 {
06023     return uves_local_filename("fluxcal_science", chip, -1, -1);
06024 }
06025 /*----------------------------------------------------------------------------*/
06033 /*----------------------------------------------------------------------------*/
06034 char *
06035 uves_scired_fluxcal_error_filename(enum uves_chip chip)
06036 {
06037     return uves_local_filename("fluxcal_error_science", chip, -1, -1);
06038 }
06039 
06040 
06041 
06049 /*----------------------------------------------------------------------------*/
06050 char *
06051 uves_scired_fluxcal_science_2d_filename(enum uves_chip chip)
06052 {
06053     return uves_local_filename("fluxcal_2d_science", chip, -1, -1);
06054 }
06055 /*----------------------------------------------------------------------------*/
06063 /*----------------------------------------------------------------------------*/
06064 char *
06065 uves_scired_fluxcal_error_2d_filename(enum uves_chip chip)
06066 {
06067     return uves_local_filename("fluxcal_error_2d_science", chip, -1, -1);
06068 }
06069 /*----------------------------------------------------------------------------*/
06077 /*----------------------------------------------------------------------------*/
06078 char *
06079 uves_scired_ff_variance_filename(enum uves_chip chip)
06080 {
06081     return uves_local_filename("variance_ff_science", chip, -1, -1);
06082 }
06083 
06084 /*----------------------------------------------------------------------------*/
06092 /*----------------------------------------------------------------------------*/
06093 char *
06094 uves_scired_ff_variance_2d_filename(enum uves_chip chip)
06095 {
06096     return uves_local_filename("variance_ff_2d_science", chip, -1, -1);
06097 }
06098 
06099 /*----------------------------------------------------------------------------*/
06106 /*----------------------------------------------------------------------------*/
06107 char *
06108 uves_scired_merged_2d_science_filename(enum uves_chip chip)
06109 {
06110     return uves_local_filename("merged_2d_science", chip, -1, -1);
06111 }
06112 
06120 /*----------------------------------------------------------------------------*/
06121 char *
06122 uves_scired_merged_science_filename(enum uves_chip chip)
06123 {
06124     return uves_local_filename("merged_science", chip, -1, -1);
06125 }
06126 /*----------------------------------------------------------------------------*/
06134 /*----------------------------------------------------------------------------*/
06135 char *
06136 uves_scired_merged_sky_filename(enum uves_chip chip)
06137 {
06138     return uves_local_filename("merged_sky", chip, -1, -1);
06139 }
06140 
06141 /*----------------------------------------------------------------------------*/
06149 /*----------------------------------------------------------------------------*/
06150 char *
06151 uves_scired_background_filename(enum uves_chip chip)
06152 {
06153     return uves_local_filename("background", chip, -1, -1);
06154 }
06155 
06156 /*----------------------------------------------------------------------------*/
06164 /*----------------------------------------------------------------------------*/
06165 char *
06166 uves_scired_resampled_filename(enum uves_chip chip)
06167 {
06168     return uves_local_filename("resampled_science", chip, -1, -1);
06169 }
06170 
06171 /*----------------------------------------------------------------------------*/
06179 /*----------------------------------------------------------------------------*/
06180 char *
06181 uves_scired_resampledmf_filename(enum uves_chip chip)
06182 {
06183     return uves_local_filename("resampled_mflat", chip, -1, -1);
06184 }
06185 
06186 /*----------------------------------------------------------------------------*/
06195 /*----------------------------------------------------------------------------*/
06196 char *
06197 uves_scired_rebinned_filename(enum uves_chip chip)
06198 {
06199     return uves_local_filename("resampled_ff_science", chip, -1, -1);
06200 }
06201 
06202 
06211 /*----------------------------------------------------------------------------*/
06212 char *
06213 uves_scired_rebinned_2d_filename(enum uves_chip chip)
06214 {
06215     return uves_local_filename("resampled_ff_2d_science", chip, -1, -1);
06216 }
06217 /*----------------------------------------------------------------------------*/
06225 /*----------------------------------------------------------------------------*/
06226 char *
06227 uves_scired_ordertrace_filename(enum uves_chip chip)
06228 {
06229     return uves_local_filename("ordertrace", chip, -1, -1);
06230 }
06231 
06232 /*----------------------------------------------------------------------------*/
06240 /*----------------------------------------------------------------------------*/
06241 char *
06242 uves_scired_crmask_filename(enum uves_chip chip)
06243 {
06244     return uves_local_filename("cr_mask", chip, -1, -1);
06245 }
06246 
06247 
06248 /*----------------------------------------------------------------------------*/
06256 /*----------------------------------------------------------------------------*/
06257 char *uves_scired_ext2d_filename(enum uves_chip chip)
06258 {
06259     return uves_local_filename("ext_2d_science", chip, -1, -1);
06260 }
06261 
06262 /*----------------------------------------------------------------------------*/
06270 /*----------------------------------------------------------------------------*/
06271 char *uves_scired_ff2d_filename(enum uves_chip chip)
06272 {
06273     return uves_local_filename("ff_2d_science", chip, -1, -1);
06274 }
06275 
06276 /*----------------------------------------------------------------------------*/
06297 /*----------------------------------------------------------------------------*/
06298 static char *
06299 uves_local_filename(const char *prefix, enum uves_chip chip, int trace, int window)
06300 {
06301     char *result = NULL;
06302     const char *chip_string;
06303     const char *suffix = ".fits";     /* Always */
06304     char *t = NULL;
06305     char *w = NULL;
06306 
06307     assure( (trace < 0 && window < 0) ||           /* Empty suffix          */
06308         (trace < 0 && window > 0) ||           /* Window only suffix    */
06309         (trace >= 0 && window > 0),            /* Trace & window suffix */
06310         CPL_ERROR_ILLEGAL_INPUT, "Illegal trace and window numbers: (%d, %d)", 
06311         trace, window);
06312 
06313     /* Chip */
06314     chip_string = uves_chip_tostring_lower(chip);
06315     
06316     /* Trace and window number (possibly empty string) */
06317     check(( t = int_to_string(trace),
06318         w = int_to_string(window)),
06319           "Error creating substrings");
06320 
06321 /* old code:
06322     result = cpl_calloc(strlen(prefix) + 1 + 
06323             strlen(chip_string) + strlen(t) + strlen(w) + strlen(suffix) + 1,
06324             sizeof(char));
06325     
06326     assure_mem( result );
06327     
06328     strcpy(result, prefix);
06329     strcat(result, "_");
06330     strcat(result, chip_string);
06331     strcat(result, t);
06332     strcat(result, w);
06333     strcat(result, suffix);
06334 */
06335     result = uves_sprintf("%s_%s%s%s%s", prefix, chip_string, t, w, suffix);
06336     assure_mem( result );
06337 
06338   cleanup:
06339     cpl_free(t);
06340     cpl_free(w);
06341     if (cpl_error_get_code() != CPL_ERROR_NONE)
06342     {
06343         cpl_free(result); result = NULL;
06344     }
06345     return result;
06346 }
06347 
06348 /*----------------------------------------------------------------------------*/
06359 /*----------------------------------------------------------------------------*/
06360 static char *
06361 int_to_string(int i)
06362 {
06363     char *result = NULL;
06364 
06365     assure( -1 <= i, CPL_ERROR_ILLEGAL_INPUT, "Illegal number (%d)", i);
06366 
06367     if (i == -1)
06368     {
06369         /* Empty string */
06370         result = cpl_calloc(1, sizeof(char));
06371         assure_mem( result );
06372     }
06373     else
06374     {
06375         result = uves_sprintf("_%d", i);
06376     }
06377     
06378   cleanup:
06379     if (cpl_error_get_code() != CPL_ERROR_NONE){
06380     cpl_free(result); result = NULL;
06381     }
06382     return result;
06383 }
06384 
06385 
06386 /*----------------------------------------------------------------------------*/
06396 /*----------------------------------------------------------------------------*/
06397 
06398 cpl_image*
06399 uves_vector_to_image(const cpl_vector* vector,cpl_type type)
06400 {
06401   int i=0;
06402   cpl_image* image=NULL;
06403   int size=0;
06404   const double* pv=NULL;
06405   int* pi=NULL;
06406   float* pf=NULL;
06407   double* pd=NULL;
06408 
06409 
06410       size=cpl_vector_get_size(vector);
06411       image=cpl_image_new(size,1,type);
06412       pv=cpl_vector_get_data_const(vector);
06413       if(type == CPL_TYPE_INT) {
06414         pi=cpl_image_get_data_int(image);
06415         for(i=0;i<size;i++) {
06416       pi[i]=pv[i];
06417     }
06418       } else if (type == CPL_TYPE_FLOAT) {
06419         pf=cpl_image_get_data_float(image);
06420         for(i=0;i<size;i++) {
06421       pf[i]=pv[i];
06422     }
06423       } else if (type == CPL_TYPE_DOUBLE) {
06424         pd=cpl_image_get_data_double(image);
06425         for(i=0;i<size;i++) {
06426       pd[i]=pv[i];
06427     }
06428       } else {
06429         assure( false, CPL_ERROR_INVALID_TYPE,
06430             "No CPL type to represent BITPIX = %d", type);
06431       }
06432 
06433  cleanup:
06434     if (cpl_error_get_code() != CPL_ERROR_NONE){
06435       uves_free_image(&image);
06436     }
06437 
06438     return image;
06439 
06440 }

Generated on Thu Nov 15 14:32:28 2007 for UVES Pipeline Reference Manual by  doxygen 1.5.1