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: amodigli $
00022  * $Date: 2012/01/12 16:43:41 $
00023  * $Revision: 1.269 $
00024  * $Name: uves-4_9_15 $
00025  * $Log: uves_dfs.c,v $
00026  * Revision 1.269  2012/01/12 16:43:41  amodigli
00027  * fixed compiler warnings with CPL6
00028  *
00029  * Revision 1.268  2011/12/08 14:07:24  amodigli
00030  * Fix warnings with CPL6
00031  *
00032  * Revision 1.267  2011/04/08 08:11:33  amodigli
00033  * removed paf generation
00034  *
00035  * Revision 1.266  2010/12/09 17:33:55  amodigli
00036  * corredted wavemap filename
00037  *
00038  * Revision 1.265  2010/11/26 07:41:49  amodigli
00039  * added uves_scired_wmap_filename()
00040  *
00041  * Revision 1.264  2010/09/24 09:32:02  amodigli
00042  * put back QFITS dependency to fix problem spot by NRI on FIBER mode (with MIDAS calibs) data
00043  *
00044  * Revision 1.262  2010/06/07 17:41:49  amodigli
00045  * added uves_scired_fluxcal_science_noappend_filename(),uves_scired_fluxcal_error_noappend_filename()
00046  *
00047  * Revision 1.261  2010/06/07 13:24:20  amodigli
00048  * Fixed typo in PRO.CATG and PIPEFILE of products in case of merging option is noappend: NOAPPEND-->NONMERGED
00049  *
00050  * Revision 1.260  2010/06/07 11:12:02  amodigli
00051  * added uves_scired_red_noappend_error_filename()
00052  *
00053  * Revision 1.259  2010/06/04 09:50:10  amodigli
00054  * added UVES_RED_NOAPPEND_STD, uves_response_red_noappend_standard_filename() uves_scired_red_noappend_science_filename()
00055  *
00056  * Revision 1.258  2010/05/19 13:28:51  amodigli
00057  * rename uves_extraction_quality_standard_filename->uves_order_extract_qc_standard_filename, UVES_EXTRACTION_QUALITY->UVES_ORDER_EXTRACT_QC
00058  *
00059  * Revision 1.257  2010/05/18 17:09:24  amodigli
00060  * added UVES_EXTRACTION_QUALITY and uves_extraction_quality_standard_filename
00061  *
00062  * Revision 1.256  2010/02/10 17:20:10  amodigli
00063  * added classification of UVES_ORD_TAB: 'FIB_ORD_TAB_CHIP' as CALIB
00064  *
00065  * Revision 1.255  2009/11/09 15:15:16  amodigli
00066  * added check on input file existance
00067  *
00068  * Revision 1.254  2009/03/04 12:58:58  amodigli
00069  * added uves_scired_resampled_2d_filename()
00070  *
00071  * Revision 1.253  2009/02/20 18:21:22  amodigli
00072  * added RAW_IMA
00073  *
00074  * Revision 1.252  2009/01/02 08:30:03  amodigli
00075  * added uves_contains_frames_kind
00076  *
00077  * Revision 1.251  2008/09/29 06:55:19  amodigli
00078  * add #include <string.h>
00079  *
00080  * Revision 1.250  2008/09/15 07:03:45  amodigli
00081  * remove qfits dependance
00082  *
00083  * Revision 1.249  2008/08/29 09:52:20  amodigli
00084  * fixed compiler warning
00085  *
00086  * Revision 1.248  2008/06/26 08:26:36  amodigli
00087  * removed static from uves_local_filename and fixed bug on FLAMES_CORVEL_MASK read
00088  *
00089  * Revision 1.247  2008/02/27 15:01:26  amodigli
00090  * cleaned output
00091  *
00092  * Revision 1.246  2008/02/15 11:46:03  amodigli
00093  * fixed bug to load pipe generated INSTR_RESPONSE curve
00094  *
00095  * Revision 1.245  2008/02/05 14:09:53  amodigli
00096  * collate 2 image estension for BLUE arm 626KHz
00097  *
00098  * Revision 1.244  2008/02/05 13:51:36  amodigli
00099  * fixed compilation warnings
00100  *
00101  * Revision 1.243  2008/02/01 12:48:16  amodigli
00102  * modified load_raw_image in order to support new BLUE arm FITS FORMAT with multi estention active since 2008-01-18
00103  *
00104  * Revision 1.242  2007/12/03 16:29:55  amodigli
00105  * commented out uves_propertylist_copy_property_regexp command to copy HIERARCH ESO keywords as was screwing up the header of the rotated-cropped frame
00106  *
00107  * Revision 1.241  2007/12/03 07:59:15  amodigli
00108  * use uves_propertylist_copy_property_regexp to copy some HIERARCH keys to 'debug' product
00109  *
00110  * Revision 1.240  2007/10/30 17:45:03  jmlarsen
00111  * Added WEIGHTS_<chip> images to support object weighted arclamp extraction
00112  *
00113  * Revision 1.239  2007/10/17 14:58:59  amodigli
00114  * added uves_check_if_format_is_midas and fixed compilation warnings
00115  *
00116  * Revision 1.238  2007/10/15 06:39:13  amodigli
00117  * keep 'Fibre' column in linetable to make work flames-uves data reduction chain
00118  *
00119  * Revision 1.237  2007/10/01 17:07:49  amodigli
00120  * cleaned output
00121  *
00122  * Revision 1.236  2007/09/19 11:09:49  amodigli
00123  * Now FLAMES_FIB_FF_DT is a macro
00124  *
00125  * Revision 1.235  2007/09/12 13:11:56  amodigli
00126  * fixed bug with UVES-ech data reduction
00127  *
00128  * Revision 1.234  2007/09/11 17:08:07  amodigli
00129  * added uves_polynomial_convert_from_plist_midas from uves_utils_polynomial.h
00130  *
00131  * Revision 1.233  2007/09/06 15:48:42  amodigli
00132  * added info on old/new format
00133  *
00134  * Revision 1.232  2007/09/06 14:15:16  amodigli
00135  * changed filenames science products
00136  *
00137  * Revision 1.231  2007/08/24 06:43:37  amodigli
00138  * fixed compilation warnings
00139  *
00140  * Revision 1.230  2007/08/21 13:08:26  jmlarsen
00141  * Removed irplib_access module, largely deprecated by CPL-4
00142  *
00143  * Revision 1.229  2007/08/20 07:59:15  amodigli
00144  * update to CPL4
00145  *
00146  * Revision 1.228  2007/08/16 13:21:15  amodigli
00147  * added uves_scired_red_2d_error_filename
00148  *
00149  * Revision 1.227  2007/08/16 06:49:47  amodigli
00150  * added uves_vector_to_image
00151  *
00152  * Revision 1.226  2007/08/10 12:10:35  amodigli
00153  * changed 2d extraction product file names as by DFS04196
00154  *
00155  * Revision 1.225  2007/07/27 14:17:07  amodigli
00156  * 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
00157  *
00158  * Revision 1.224  2007/07/25 10:56:23  amodigli
00159  * fixed small leak
00160  *
00161  * Revision 1.223  2007/07/25 10:52:17  amodigli
00162  * fixed problem with images with NAXIS=1 and CPL4
00163  *
00164  * Revision 1.222  2007/07/23 06:30:50  amodigli
00165  * added FLAMES_FIB_FF_DT
00166  *
00167  * Revision 1.221  2007/07/03 12:40:03  amodigli
00168  * added FLAMES_CORVEL_MASK FLAMES_SCI_SIM_RED and support for cubes FIB_FF and SLIT_FF
00169  *
00170  * Revision 1.220  2007/06/29 10:47:50  jmlarsen
00171  * load_linetable: Assume MIDAS like format if FLAMES
00172  *
00173  * Revision 1.219  2007/06/28 09:17:16  jmlarsen
00174  * Make work order table column renaming for FLAMES
00175  *
00176  * Revision 1.218  2007/06/26 14:48:11  jmlarsen
00177  * Removed unused variable
00178  *
00179  * Revision 1.217  2007/06/26 14:46:01  jmlarsen
00180  * Do not try to read dispersion polynomial when not requested
00181  *
00182  * Revision 1.216  2007/06/26 14:04:35  jmlarsen
00183  * Save with BITPIX16 for FLAMES orderpos
00184  *
00185  * Revision 1.215  2007/06/26 13:34:52  jmlarsen
00186  * Exported function for FLAMES
00187  *
00188  * Revision 1.214  2007/06/25 15:43:45  jmlarsen
00189  * uves_frameset_insert(): propagate custom keywords before, not after, calling cpl_dfs_setup_product_header
00190  *
00191  * Revision 1.213  2007/06/25 05:55:11  amodigli
00192  * added FLAMES_SCI_RED FLAMES_SCI_COM_RED to raw frames list
00193  *
00194  * Revision 1.212  2007/06/22 14:50:46  jmlarsen
00195  * Optionally save height=1 images as NAXIS=1
00196  *
00197  * Revision 1.211  2007/06/22 11:15:05  jmlarsen
00198  * uves_save_image(): Also save float images with NAXIS=1 when height is 1
00199  *
00200  * Revision 1.210  2007/06/22 09:30:08  jmlarsen
00201  * Allow saving CPL_TYPE_INT images as 16 or 32 bit FITS
00202  *
00203  * Revision 1.209  2007/06/20 15:49:05  jmlarsen
00204  * Enabled check for NULL polynoimal
00205  *
00206  * Revision 1.208  2007/06/20 13:05:17  amodigli
00207  * commented assure not to make fail a test case
00208  *
00209  * Revision 1.207  2007/06/20 08:32:52  amodigli
00210  * updated uves_load_linetable to support FIBER mode
00211  *
00212  * Revision 1.206  2007/06/06 08:17:33  amodigli
00213  * replace tab with 4 spaces
00214  *
00215  * Revision 1.205  2007/05/23 12:50:53  jmlarsen
00216  * Replace isnan/isinf -> irplib_isnan/irplib_isinf
00217  *
00218  * Revision 1.204  2007/05/16 14:56:27  jmlarsen
00219  * Fixed error message
00220  *
00221  * Revision 1.203  2007/05/16 11:47:18  amodigli
00222  * added FLAMES_SCI_COM_RED
00223  *
00224  * Revision 1.202  2007/05/04 08:55:15  amodigli
00225  * moved up declaration of img to suppress compilation warning
00226  *
00227  * Revision 1.201  2007/05/03 15:19:10  jmlarsen
00228  * Added const version of uves_load_linetable()
00229  *
00230  * Revision 1.200  2007/05/02 13:36:14  jmlarsen
00231  * Decreased verbosity of debug message
00232  *
00233  * Revision 1.199  2007/05/02 13:16:30  jmlarsen
00234  * Fixed error message typo
00235  *
00236  * Revision 1.198  2007/04/26 13:19:11  jmlarsen
00237  * Exported function copy_if_possible
00238  *
00239  * Revision 1.197  2007/04/24 16:44:26  amodigli
00240  * changed interface uves_load_ordertable to return also extention table
00241  *
00242  * Revision 1.196  2007/04/24 12:50:29  jmlarsen
00243  * Replaced cpl_propertylist -> uves_propertylist which is much faster
00244  *
00245  * Revision 1.195  2007/04/23 06:59:29  amodigli
00246  * added uves_save_imagelist
00247  *
00248  * Revision 1.194  2007/04/12 12:15:12  jmlarsen
00249  * Propagate keyword OS-EXPOI
00250  *
00251  * Revision 1.193  2007/04/12 11:58:46  jmlarsen
00252  * Rename order table column if necessary
00253  *
00254  * Revision 1.192  2007/04/10 07:06:59  jmlarsen
00255  * Take into account 64 pixel gap in REDU CRVAL2 computation
00256  *
00257  * Revision 1.191  2007/04/04 06:27:06  jmlarsen
00258  * Fixed malloc -> cpl_malloc
00259  *
00260  * Revision 1.190  2007/04/03 11:02:25  jmlarsen
00261  * Support reading float MIDAS arrays
00262  *
00263  * Revision 1.189  2007/04/03 08:03:59  jmlarsen
00264  * uves_read_midas_array: support arrays of any length
00265  *
00266  * Revision 1.188  2007/04/03 06:28:45  amodigli
00267  * uves_load_ordertable provides now fibre_mask and fibre_pos if appropriate
00268  *
00269  * Revision 1.187  2007/03/30 07:06:59  jmlarsen
00270  * Initialize variables to suppress warnings
00271  *
00272  * Revision 1.186  2007/03/23 07:59:30  jmlarsen
00273  * Fixed minor memory leak
00274  *
00275  * Revision 1.185  2007/03/20 15:39:46  amodigli
00276  * added FLAMES tags
00277  *
00278  * Revision 1.184  2007/03/20 07:26:57  jmlarsen
00279  * Don't remove std star from flux table which has NULL type
00280  *
00281  * Revision 1.183  2007/03/15 15:04:34  jmlarsen
00282  * Allow spaces in HISTORY keyword string values
00283  *
00284  * Revision 1.182  2007/03/05 10:16:12  jmlarsen
00285  * Define 'dWave' as constant
00286  *
00287  * Revision 1.181  2007/02/27 14:04:35  jmlarsen
00288  * Added comment
00289  *
00290  * Revision 1.180  2007/02/26 13:27:53  jmlarsen
00291  * Partial workaround for slow uves_propertylist_copy_property_regexp()
00292  *
00293  * Revision 1.179  2007/02/22 15:33:24  jmlarsen
00294  * Redefine catalogue wavelength uncertainties to better match new catalogue
00295  *
00296  * Revision 1.178  2007/02/14 14:06:34  jmlarsen
00297  * Use REF_TFLAT, not MASTER_TFLAT as master
00298  *
00299  * Revision 1.177  2007/02/12 10:09:33  jmlarsen
00300  * Fixed recently introduced bug that REDL image was loaded twice, instead of REDL + REDU
00301  *
00302  * Revision 1.176  2007/02/09 13:36:04  jmlarsen
00303  * Added function to load ref_flat
00304  *
00305  * Revision 1.175  2007/02/09 08:51:06  jmlarsen
00306  * Use define's rather than hard-coded recipe names
00307  *
00308  * Revision 1.174  2007/02/09 08:03:08  jmlarsen
00309  * Changed definition of CRVAL in products
00310  *
00311  * Revision 1.173  2007/02/08 07:33:01  jmlarsen
00312  * Added uves_load_cd_align(), changed CRVAL computation
00313  *
00314  * Revision 1.172  2007/02/01 07:23:44  jmlarsen
00315  * Removed debugging code
00316  *
00317  * Revision 1.171  2007/01/31 15:18:52  jmlarsen
00318  * Write +- FLT_MAX to FITS file if double value out of range
00319  *
00320  * Revision 1.170  2007/01/31 15:10:34  jmlarsen
00321  * Avoid inf+nan when saving FITS files
00322  *
00323  * Revision 1.169  2007/01/17 13:25:39  jmlarsen
00324  * Added uves_load_image()
00325  *
00326  * Revision 1.168  2007/01/16 10:27:30  jmlarsen
00327  * Implemented self-consistent propagation of FITS geometry keywords
00328  *
00329  * Revision 1.167  2007/01/15 08:45:27  jmlarsen
00330  * Added comment
00331  *
00332  * Revision 1.166  2007/01/10 12:37:16  jmlarsen
00333  * Exported function to warn about mismatching calibration frames
00334  *
00335  * Revision 1.165  2007/01/09 17:45:42  amodigli
00336  * added uves_check_rec_status
00337  *
00338  * Revision 1.164  2006/12/12 12:09:14  jmlarsen
00339  * Added function to load corvel table
00340  *
00341  * Revision 1.163  2006/12/11 12:34:01  jmlarsen
00342  * Use date to determine new/old format
00343  *
00344  * Revision 1.162  2006/12/07 08:22:59  jmlarsen
00345  * uves_load_raw_imagelist: support FLAMES
00346  *
00347  * Revision 1.161  2006/12/01 08:26:56  jmlarsen
00348  * Load FLAMES order table oshift/yshift
00349  *
00350  * Revision 1.160  2006/11/24 16:21:07  jmlarsen
00351  * Added FIB_LINE_TABLE_x
00352  *
00353  * Revision 1.159  2006/11/24 11:10:14  jmlarsen
00354  * Support for loading FLAMES guess line table
00355  *
00356  * Revision 1.158  2006/11/24 09:35:40  jmlarsen
00357  * Workaround for slow uves_propertylist_get_size
00358  *
00359  * Revision 1.157  2006/11/23 10:04:11  jmlarsen
00360  * Minor message change
00361  *
00362  * Revision 1.156  2006/11/22 08:39:55  jmlarsen
00363  * Exported and fixed bug in uves_read_midas_array
00364  *
00365  * Revision 1.154  2006/11/22 08:22:29  jmlarsen
00366  * Set message level according to preprocessor symbol
00367  *
00368  * Revision 1.153  2006/11/16 14:08:33  jmlarsen
00369  * Implemented loading FLAMES ordertable
00370  *
00371  * Revision 1.152  2006/11/16 09:51:13  jmlarsen
00372  * Use compile time branching to support both released and development CPL versions
00373  *
00374  * Revision 1.151  2006/11/16 08:32:03  jmlarsen
00375  * Save CPL_TYPE_INT images as 16 bit unsigned, to support flames_cal_orderpos
00376  *
00377  * Revision 1.150  2006/11/15 15:02:14  jmlarsen
00378  * Implemented const safe workarounds for CPL functions
00379  *
00380  * Revision 1.148  2006/11/15 14:04:08  jmlarsen
00381  * Removed non-const version of parameterlist_get_first/last/next which is already 
00382  * in CPL, added const-safe wrapper, unwrapper and deallocator functions
00383  *
00384  * Revision 1.147  2006/11/13 14:23:55  jmlarsen
00385  * Removed workarounds for CPL const bugs
00386  *
00387  * Revision 1.146  2006/11/13 12:44:31  jmlarsen
00388  * Support FLAMES FIB_ARC_LAMP_RED frames
00389  *
00390  * Revision 1.145  2006/11/08 14:03:31  jmlarsen
00391  * Fixed doc bug when warning about deprecated background table
00392  *
00393  * Revision 1.144  2006/11/08 08:03:26  jmlarsen
00394  * Avoid initializers not computable at compile time, for portability
00395  *
00396  * Revision 1.143  2006/11/07 14:01:10  jmlarsen
00397  * Moved flames_load_ functions to separate source file
00398  *
00399  * Revision 1.142  2006/11/06 15:19:41  jmlarsen
00400  * Removed unused include directives
00401  *
00402  * Revision 1.141  2006/11/03 15:01:21  jmlarsen
00403  * Killed UVES 3d table module and use CPL 3d tables
00404  *
00405  * Revision 1.140  2006/10/26 14:02:41  jmlarsen
00406  * Removed redundant goto
00407  *
00408  * Revision 1.139  2006/10/24 14:05:23  jmlarsen
00409  * Generalized load functions to support FLAMES
00410  *
00411  * Revision 1.138  2006/10/19 13:53:25  jmlarsen
00412  * Changed guess line table tag to LINE_GUESS_TAB
00413  *
00414  * Revision 1.137  2006/10/12 11:37:28  jmlarsen
00415  * Temporarily disabled FLAMES code generation
00416  *
00417  * Revision 1.136  2006/10/10 11:29:24  jmlarsen
00418  * Added code to propagate TM-START
00419  *
00420  * Revision 1.135  2006/10/10 11:20:47  jmlarsen
00421  * Renamed line table columns to match MIDAS
00422  *
00423  * Revision 1.134  2006/10/05 11:14:59  jmlarsen
00424  * Removed debugging code
00425  *
00426  * Revision 1.133  2006/10/02 08:34:04  jmlarsen
00427  * Added REF_TFLAT
00428  *
00429  * Revision 1.132  2006/09/27 13:13:26  jmlarsen
00430  * Use dynamic memory allocation to store bad pixels
00431  *
00432  * Revision 1.131  2006/09/20 15:42:17  jmlarsen
00433  * Implemented MASTER_RESPONSE support
00434  *
00435  * Revision 1.130  2006/09/20 10:56:50  jmlarsen
00436  * Propagate DATAMEAN/DATAMED/DATARMS if present
00437  *
00438  * Revision 1.129  2006/09/19 14:25:30  jmlarsen
00439  * Propagate FITS keywords from master flat, not science, to WCALIB_FLAT_OBJ
00440  *
00441  * Revision 1.128  2006/09/19 06:55:06  jmlarsen
00442  * Changed interface of uves_frameset to optionally write image statistics kewwords
00443  *
00444  * Revision 1.127  2006/09/14 08:46:51  jmlarsen
00445  * Added support for TFLAT, SCREEN_FLAT frames
00446  *
00447  * Revision 1.126  2006/09/08 14:04:41  jmlarsen
00448  * Documentation update
00449  *
00450  * Revision 1.125  2006/08/31 07:24:57  jmlarsen
00451  * Fixed buffer overruns happening when raw frames are not available
00452  *
00453  * Revision 1.124  2006/08/24 11:36:56  jmlarsen
00454  * Write recipe start/stop time to header
00455  *
00456  * Revision 1.123  2006/08/23 09:33:03  jmlarsen
00457  * Renamed local variables shadowing POSIX reserved names
00458  *
00459  * Revision 1.122  2006/08/21 07:53:17  jmlarsen
00460  * Added debug message
00461  *
00462  * Revision 1.121  2006/08/18 13:32:13  jmlarsen
00463  * Use legal FITS keywords for TRACEID/WINDOW/FABSORD/LABSORD
00464  *
00465  * Revision 1.120  2006/08/18 07:07:43  jmlarsen
00466  * Switched order of cpl_calloc arguments
00467  *
00468  * Revision 1.119  2006/08/17 14:11:25  jmlarsen
00469  * Use assure_mem macro to check for memory allocation failure
00470  *
00471  * Revision 1.118  2006/08/17 13:56:52  jmlarsen
00472  * Reduced max line length
00473  *
00474  * Revision 1.117  2006/08/17 13:04:10  jmlarsen
00475  * Reduced max line length
00476  *
00477  * Revision 1.116  2006/08/17 09:17:15  jmlarsen
00478  * Removed CPL2 code
00479  *
00480  * Revision 1.115  2006/08/11 14:56:05  amodigli
00481  * removed Doxygen warnings
00482  *
00483  * Revision 1.114  2006/08/11 11:26:59  jmlarsen
00484  * Change text message
00485  *
00486  * Revision 1.113  2006/08/11 08:59:07  jmlarsen
00487  * Take into account the different meanings of line table 'Y' column
00488  *
00489  * Revision 1.112  2006/08/08 12:55:00  jmlarsen
00490  * Support uppercase column names when loading linetable
00491  *
00492  * Revision 1.111  2006/08/08 11:27:18  amodigli
00493  * upgrade to CPL3
00494  *
00495  * Revision 1.110  2006/08/07 14:42:02  jmlarsen
00496  * Implemented on-the-fly correction of a line table when its 
00497  * order numbering is inconsistent with the order table (DFS02694)
00498  *
00499  * Revision 1.109  2006/08/07 12:14:13  jmlarsen
00500  * Removed unused code
00501  *
00502  * Revision 1.108  2006/08/01 14:43:36  amodigli
00503  * fixed bug loading fitsheader in uves_load_masterformatcheck
00504  *
00505  * Revision 1.107  2006/07/31 06:29:05  amodigli
00506  * added flames_load_frame_index
00507  *
00508  * Revision 1.106  2006/07/14 12:19:28  jmlarsen
00509  * Support multiple QC tests per product
00510  *
00511  * Revision 1.105  2006/07/03 12:59:14  jmlarsen
00512  * Changed message to debug level
00513  *
00514  * Revision 1.104  2006/06/29 07:57:21  amodigli
00515  * fixed warning messages from make html
00516  *
00517  * Revision 1.103  2006/06/29 07:32:05  amodigli
00518  * removed warning from make html
00519  *
00520  * Revision 1.102  2006/06/28 13:27:50  amodigli
00521  * Fixed problem dumping ARCFILE key changing uves_save_paf interface
00522  *
00523  * Revision 1.101  2006/06/26 07:54:14  amodigli
00524  * flames_load_image flames_load_table
00525  *
00526  * Revision 1.100  2006/06/23 15:31:32  amodigli
00527  * added useful stuff for flames
00528  *
00529  * Revision 1.99  2006/06/22 15:25:35  amodigli
00530  * changes for flames_cal_prep_sff_ofpos
00531  *
00532  * Revision 1.98  2006/06/22 12:03:56  amodigli
00533  * clean msg warning
00534  *
00535  * Revision 1.97  2006/06/22 09:42:56  jmlarsen
00536  * Removed syntax error
00537  *
00538  * Revision 1.96  2006/06/22 08:57:38  jmlarsen
00539  * Changed a few messages
00540  *
00541  * Revision 1.95  2006/06/22 06:42:38  amodigli
00542  * fixed some compilation warnings
00543  *
00544  * Revision 1.94  2006/06/20 08:25:56  amodigli
00545  * fixed doxigen warnings
00546  *
00547  * Revision 1.93  2006/06/19 06:51:14  amodigli
00548  * added support flames-old format
00549  *
00550  * Revision 1.92  2006/06/16 08:22:01  jmlarsen
00551  * Manually propagate ESO.DET. keywords from 1st/2nd input header
00552  *
00553  * Revision 1.91  2006/06/13 11:55:06  jmlarsen
00554  * Shortened max line length
00555  *
00556  * Revision 1.90  2006/06/05 08:51:55  amodigli
00557  * cleaned some warnings from static checks
00558  *
00559  * Revision 1.89  2006/06/01 14:43:17  jmlarsen
00560  * Added missing documentation
00561  *
00562  * Revision 1.88  2006/06/01 14:21:02  amodigli
00563  * frm --> frm_tmp, dup --> frm_dup
00564  *
00565  * Revision 1.87  2006/05/31 09:51:01  amodigli
00566  * removed compilation warning
00567  *
00568  * Revision 1.86  2006/05/22 06:47:15  amodigli
00569  * fixed some bugs on msflat
00570  *
00571  * Revision 1.85  2006/05/19 13:07:52  amodigli
00572  * modified to support SFLATs
00573  *
00574  * Revision 1.84  2006/05/17 09:54:55  amodigli
00575  * added supposr SFLATs
00576  *
00577  * Revision 1.82  2006/05/15 06:09:52  amodigli
00578  * added support for some FLAMES input frames
00579  *
00580  * Revision 1.81  2006/05/12 15:01:30  jmlarsen
00581  * Changed msg level warning -> debug when there's no QC log
00582  *
00583  * Revision 1.80  2006/04/25 14:58:48  amodigli
00584  * added paf creation functionalities
00585  *
00586  * Revision 1.79  2006/04/24 09:18:06  jmlarsen
00587  * Minor message change
00588  *
00589  * Revision 1.78  2006/04/20 10:48:20  amodigli
00590  * inform that no QC log is provided
00591  *
00592  * Revision 1.77  2006/04/10 12:35:42  jmlarsen
00593  * Simplified the save-product function
00594  *
00595  * Revision 1.76  2006/04/06 13:12:54  jmlarsen
00596  * Fixed doc. bug
00597  *
00598  * Revision 1.75  2006/04/06 12:56:50  jmlarsen
00599  * Added support for PDARK, IFLAT, DLFAT frames
00600  *
00601  * Revision 1.74  2006/04/06 11:48:17  jmlarsen
00602  * Support for SCI_POINT_-, SCI_EXTND_- and SCI_SLICER-frames
00603  *
00604  * Revision 1.73  2006/04/06 09:48:15  amodigli
00605  * changed uves_frameset_insert interface to have QC log
00606  *
00607  * Revision 1.72  2006/04/06 08:31:15  jmlarsen
00608  * Added support for reading MASTER_DFLAT, MASTER_IFLAT, MASTER_PDARK
00609  *
00610  * Revision 1.71  2006/03/24 14:24:29  jmlarsen
00611  * Don't blindly stack flat-fields of different wavelenghts
00612  *
00613  * Revision 1.70  2006/03/09 10:51:58  jmlarsen
00614  * Added timing info
00615  *
00616  * Revision 1.69  2006/03/06 09:22:43  jmlarsen
00617  * Added support for reading MIDAS line tables with MIDAS tags
00618  *
00619  * Revision 1.68  2006/03/03 13:54:11  jmlarsen
00620  * Changed syntax of check macro
00621  *
00622  * Revision 1.67  2006/02/15 13:19:15  jmlarsen
00623  * Reduced source code max. line length
00624  *
00625  * Revision 1.66  2006/01/17 10:14:20  jmlarsen
00626  * Changed order of functions
00627  *
00628  * Revision 1.65  2006/01/16 07:10:53  amodigli
00629  *
00630  * Clean
00631  *
00632  * Revision 1.64  2006/01/09 15:22:53  jmlarsen
00633  * Removed some warnings
00634  *
00635  * Revision 1.63  2006/01/09 14:05:21  amodigli
00636  * Fixed doxigen warnings
00637  *
00638  * Revision 1.62  2006/01/03 16:56:53  amodigli
00639  * Added MASTER_ARC_FORM
00640  *
00641  * Revision 1.61  2005/12/19 16:17:56  jmlarsen
00642  * Replaced bool -> int
00643  *
00644  */
00645 
00646 #ifdef HAVE_CONFIG_H
00647 #include <config.h>
00648 #endif
00649 
00650 /*----------------------------------------------------------------------------*/
00657 /*----------------------------------------------------------------------------*/
00658 
00659 /*-----------------------------------------------------------------------------
00660                                    Includes
00661  -----------------------------------------------------------------------------*/
00662 
00663 #include <uves_dfs.h>
00664 
00665 #include <uves_utils.h>
00666 #include <uves_wavecal_utils.h>
00667 #include <uves_pfits.h>
00668 #include <uves_dump.h>
00669 #include <uves_qclog.h>
00670 #include <uves.h>
00671 #include <uves_utils_wrappers.h>
00672 #include <uves_error.h>
00673 #include <uves_msg.h>
00674 
00675 #include <irplib_utils.h>
00676 
00677 #include <cpl.h>
00678 
00679 #include <uves_time.h> /* iso time */
00680 
00681 #include <float.h>
00682 #include <string.h>
00683 /*-----------------------------------------------------------------------------
00684                                    Defines
00685  -----------------------------------------------------------------------------*/
00686 #define FITS_MAGIC_SZ      6
00687 
00688 /*-----------------------------------------------------------------------------
00689                                    Prototypes
00690  -----------------------------------------------------------------------------*/
00691 
00692 static polynomial *load_polynomial(const char* filename, int extension);
00693 static char *int_to_string(int i);
00694 
00695 static cpl_error_code
00696 load_raw_image(const char *filename, 
00697            cpl_type type, bool flames, bool blue,
00698            cpl_image *raw_image[2],
00699            uves_propertylist *raw_header[2], 
00700            uves_propertylist *rotated_header[2]);
00701 
00702 static int uves_is_fits_file(const char *filename);
00710 int uves_check_rec_status(const int val) {
00711    if(cpl_error_get_code() != CPL_ERROR_NONE) {
00712       uves_msg_error("error before %d",val);
00713       uves_msg_error((char* ) cpl_error_get_message());
00714       uves_msg_error((char* ) cpl_error_get_where());
00715       return -1;
00716     }
00717     return 0;
00718 }
00719 
00720 /*-------------------------------------------------------------------------*/
00731 /*--------------------------------------------------------------------------*/
00732 
00733 static int uves_is_fits_file(const char *filename)
00734 {
00735    FILE    *fp ;
00736    char    *magic ;
00737    int        isfits ;
00738 
00739    if ((fp = fopen(filename, "r"))==NULL) {
00740       uves_msg_error("cannot open file [%s]", filename) ;
00741       return -1 ;
00742    }
00743 
00744    magic = cpl_calloc(FITS_MAGIC_SZ+1, sizeof(char)) ;
00745    (void)fread(magic, 1, FITS_MAGIC_SZ, fp) ;
00746    (void)fclose(fp) ;
00747    magic[FITS_MAGIC_SZ] = (char)0 ;
00748    if (strstr(magic, "SIMPLE")!=NULL)
00749       isfits = 1 ;
00750    else
00751       isfits = 0 ;
00752    cpl_free(magic) ;
00753    return isfits ;
00754 }
00755 
00756 /*----------------------------------------------------------------------------*/
00766 /*----------------------------------------------------------------------------*/
00767 static int 
00768 uves_dfs_files_dont_exist(cpl_frameset *frameset)
00769 {
00770     const char *func = "dfs_files_dont_exist";
00771     cpl_frame  *frame;
00772 
00773 
00774     if (frameset == NULL) {
00775         cpl_error_set(func, CPL_ERROR_NULL_INPUT);
00776         return 1;
00777     }
00778 
00779     if (cpl_frameset_is_empty(frameset)) {
00780         return 0;
00781     }
00782 
00783     frame = cpl_frameset_get_first(frameset);
00784 
00785     while (frame) {
00786         if (access(cpl_frame_get_filename(frame), F_OK)) {
00787             cpl_msg_error(func, "File %s (%s) was not found", 
00788                           cpl_frame_get_filename(frame), 
00789                           cpl_frame_get_tag(frame));
00790             cpl_error_set(func, CPL_ERROR_FILE_NOT_FOUND);
00791         }
00792 
00793         frame = cpl_frameset_get_next(frameset);
00794     }
00795 
00796     if (cpl_error_get_code())
00797         return 1;
00798 
00799     return 0;
00800 }
00801 
00802 
00803 
00804 /*----------------------------------------------------------------------------*/
00813 /*----------------------------------------------------------------------------*/
00814 
00815 int 
00816 uves_contains_frames_kind(cpl_frameset * sof, 
00817                                cpl_frameset* raw,
00818                                const char*         type)
00819 {
00820    char* tag=NULL;
00821    char* name=NULL;
00822    cpl_frame* frame   = NULL;
00823    cpl_frame* frame_dup   = NULL;
00824 
00825    int nsof=0;
00826    int i=0;
00827    nsof = cpl_frameset_get_size(sof);
00828    for (i=0 ; i<nsof ; i++) {
00829       frame = cpl_frameset_get_frame(sof,i);
00830       name= (char*) cpl_frame_get_filename(frame);
00831       if(uves_is_fits_file(name) == 1) {
00832          /* to go on the file must exist */
00833          if(cpl_frame_get_tag(frame) != NULL) {
00834             /* If the frame has a tag we process it. Else it is an object */ 
00835             tag= (char*) cpl_frame_get_tag(frame);
00836             /* uves_msg("name=%s tag=%s type=%s\n",name,tag,type); */
00837             if(strstr(tag,type) != NULL) {
00838                /* uves_msg("Match name=%s tag=%s type=%s\n",name,tag,type); */
00839                frame_dup = cpl_frame_duplicate(frame);
00840                cpl_frameset_insert(raw,frame_dup);
00841                /* uves_msg("inserted\n"); */ 
00842             }
00843          }
00844       }
00845    }
00846    return 0;
00847 }
00848 
00849 /*----------------------------------------------------------------------------*/
00866 /*----------------------------------------------------------------------------*/
00867 polynomial *
00868 uves_polynomial_convert_from_plist_midas(const uves_propertylist *plist, 
00869                      const char *regression_name,
00870                                          const int index)
00871 {
00872     polynomial *result = NULL;
00873     cpl_polynomial *pol = NULL;
00874     int N = strlen(regression_name);
00875     const char *coeffi_name = NULL;
00876     cpl_type type;
00877     int length;
00878     int *coeffi = NULL;
00879     int degree1 = -1;
00880     int degree2 = -1; 
00881     bool found = false;
00882     const long int plist_size = uves_propertylist_get_size(plist);
00883     int i;
00884      
00885     char cind=' ';
00886 
00887     if (index == -1) {
00888       coeffi_name = cpl_sprintf("%sI", regression_name);
00889     }
00890     else {
00891 
00892      switch(index) {
00893 
00894      case 1: cind='1'; break;
00895      case 2: cind='2'; break;
00896      case 3: cind='3'; break;
00897      case 4: cind='4'; break;
00898      case 5: cind='5'; break;
00899      case 6: cind='6'; break;
00900      case 7: cind='7'; break;
00901      case 8: cind='8'; break;
00902      case 9: cind='9'; break;
00903      default: 
00904        assure( false, CPL_ERROR_ILLEGAL_INPUT, 
00905              "Illegal index %d, 1-9 expected", index);
00906        break;
00907      }
00908 
00909 
00910       coeffi_name = cpl_sprintf("%sI%d", regression_name, index);
00911     }
00912 
00913     check_nomsg( coeffi = uves_read_midas_array(plist, coeffi_name, &length, &type, NULL));
00914 
00915 
00916     assure( type == CPL_TYPE_INT, CPL_ERROR_TYPE_MISMATCH,
00917         "Type of array %s is %s, integer expected",
00918         coeffi_name, uves_tostring_cpl_type(type));
00919     /*
00920     assure( length == 7, CPL_ERROR_ILLEGAL_INPUT,
00921         "Wrong array length = %d, 7 expected",
00922         length);
00923     */
00924     /* ignore OUTPUTI(1)- N,no.of data, */
00925     
00926     /* OUTPUTI(2)- M,no.of ind.var. */
00927     
00928     assure( coeffi[1] == 2, CPL_ERROR_UNSUPPORTED_MODE,
00929         "Regressions is %d-dimensional (2D expected)", 
00930         coeffi[1]);
00931 
00932     /* ignore OUTPUTI(3-5) (column number of variables)
00933        (3)- col.no. of dep.var.
00934        (4)- col.no. of indep.var.
00935        (5)-
00936     */
00937     
00938     /* Read degree of first and second variable 
00939        (6)- degree (ND) */
00940 
00941     degree1 = coeffi[5];
00942     degree2 = coeffi[6];
00943     
00944     uves_msg_debug("Degree of 2D regression %s is (%d, %d)",
00945                    regression_name, degree1, degree2);
00946 
00947     /* The degree of the regression is now known. Next, read the coefficients */
00948 
00949     pol = cpl_polynomial_new(2);
00950 
00951     /* Search for <regression_name>D */
00952     found = false;
00953     for (i = 0; !found && i < plist_size; i++){
00954     const cpl_property *p = uves_propertylist_get_const(plist, i);
00955     const char *name = cpl_property_get_name(p);
00956     
00957     if (strcmp(name, "HISTORY") == 0) {
00958         const char *value;
00959         check( value = cpl_property_get_string(p),
00960            "Error reading property value");
00961         
00962         /* match the string  "'<regression_name>D'"  */
00963 
00964         if (
00965          
00966         (((index < 0) &&
00967         (int)strlen(value) >= 1+N+2 &&
00968              value[0]     == '\'' &&
00969              value[1+N]   == 'D' && 
00970          value[1+N+1] == '\'') 
00971 
00972                 || 
00973 
00974         ((index > 0) &&
00975         (int)strlen(value) >= 1+N+3 &&
00976              value[0]     == '\'' &&
00977              value[1+N]   == 'D' && 
00978              value[1+N+1] == cind && 
00979          value[1+N+2] == '\'') ) 
00980 
00981                  &&
00982  
00983         strncmp(value+1, regression_name, N) == 0
00984         ) {
00985         double coeff;
00986         char *next;
00987         cpl_size power[2];
00988         int j = i; /* points to the property currently being read */
00989 
00990         power[0] = 0;  /* Current degree */
00991         power[1] = 0;
00992 
00993         found = true;
00994         value = "dummy"; /* This will make strtod fail the first time */
00995         
00996         while (power[1] <= degree2){
00997             /* Read coefficient */
00998             coeff = strtod(value, &next);
00999             
01000             if (next != value) {
01001             /* A prefix of the string was successfully converted to double */
01002             cpl_polynomial_set_coeff(pol, power, coeff);
01003             uves_msg_debug("Polynomial coefficient of order (%" CPL_SIZE_FORMAT ", %" CPL_SIZE_FORMAT ") is %e",
01004                        power[0], power[1], coeff);
01005             
01006             power[0]++;
01007             if (power[0] > degree1){
01008                 power[0] = 0;
01009                 power[1]++;
01010             }
01011             value = next;
01012             }
01013             else {
01014             /* No more doubles could be read from the string,
01015                so move to the next property in the plist */
01016             j = j + 1;
01017             
01018             assure(j < plist_size, CPL_ERROR_ILLEGAL_INPUT,
01019                    "Missing header data");
01020             
01021             p = uves_propertylist_get_const(plist, j);
01022             assure(       cpl_property_get_type(p)             == CPL_TYPE_STRING &&
01023                    strcmp(cpl_property_get_name(p), "HISTORY") == 0, 
01024                       CPL_ERROR_ILLEGAL_INPUT, "Error parsing polynomial");
01025             
01026             value = cpl_property_get_string(p);
01027 
01028             
01029             uves_msg_debug("Parsing string '%s'", value);
01030             }
01031         } /* Read coefficients */
01032         } /* string was "'...D'" */
01033     } /* Keyword was HISTORY */
01034     }/* for i... */
01035     
01036     assure( found, CPL_ERROR_ILLEGAL_INPUT, "Could not find '%sD' in property list", 
01037         regression_name);
01038 
01039     /* Create a new polynomial from the cpl_polynomial */
01040     result = uves_polynomial_new(pol);
01041     
01042   cleanup:
01043     uves_free_int(&coeffi);
01044     uves_free_string_const(&coeffi_name);
01045     uves_free_polynomial(&pol);
01046     if (cpl_error_get_code() != CPL_ERROR_NONE) 
01047     {
01048         uves_polynomial_delete(&result);
01049     }
01050 
01051     return result;
01052 }
01053 
01054 
01055 /*----------------------------------------------------------------------------*/
01062 /*----------------------------------------------------------------------------*/
01063 cpl_error_code
01064 uves_frameset_merge(cpl_frameset * set1, const cpl_frameset* set2)
01065 {
01066 
01067     const cpl_frame* frm_tmp=NULL;
01068     cpl_frame* frm_dup=NULL;
01069 
01070   passure(set1 != NULL, "Wrong input set");
01071   passure(set2 != NULL, "Wrong input set");
01072   
01073   for (frm_tmp = cpl_frameset_get_first_const(set2);
01074        frm_tmp != NULL;
01075        frm_tmp = cpl_frameset_get_next_const(set2))
01076       {
01077       frm_dup = cpl_frame_duplicate(frm_tmp);
01078       cpl_frameset_insert(set1, frm_dup);
01079       }
01080   
01081   cleanup:
01082   return cpl_error_get_code();
01083 }
01084 
01085 /*----------------------------------------------------------------------------*/
01093 /*----------------------------------------------------------------------------*/
01094 
01095 cpl_error_code
01096 uves_extract_frames_group_type(const cpl_frameset * set, cpl_frameset** ext, cpl_frame_group type)
01097 {
01098     const cpl_frame* frm_tmp=NULL;
01099   cpl_frame* frm_dup=NULL;
01100   cpl_frame_group g;
01101 
01102   check_nomsg(*ext = cpl_frameset_new());
01103   check_nomsg(frm_tmp = cpl_frameset_get_first_const(set));
01104   while (frm_tmp != NULL)
01105     {
01106       g=cpl_frame_get_group(frm_tmp);
01107       if(g == type) {
01108     frm_dup=cpl_frame_duplicate(frm_tmp);
01109         cpl_frameset_insert(*ext,frm_dup);
01110         uves_msg_debug("group %d insert file %s ",type,cpl_frame_get_filename(frm_dup));
01111       }
01112       frm_tmp = cpl_frameset_get_next_const(set);
01113     }
01114 
01115   cleanup:
01116     return cpl_error_get_code();
01117 }
01118 
01119 /*----------------------------------------------------------------------------*/
01127 /*----------------------------------------------------------------------------*/
01128 cpl_error_code
01129 uves_sflats_get_encoder_steps(const cpl_frameset * set, cpl_table** enc, int* nset)
01130 {
01131   /* Input */
01132     const cpl_frame* frm=NULL;
01133   int x1enc=0;
01134   int x2enc=0;
01135   int ref_x1enc=0;
01136   int ref_x2enc=0;
01137   int i=0;
01138   int ndata=0;
01139   const int threshold=5;
01140   int status=0;
01141   uves_propertylist* plist=NULL;
01142   cpl_table* encoder_tbl=NULL;
01143   ndata = cpl_frameset_get_size(set);
01144   encoder_tbl=cpl_table_new(ndata);
01145   cpl_table_new_column(encoder_tbl,"x1enc",CPL_TYPE_INT);
01146   cpl_table_new_column(encoder_tbl,"x2enc",CPL_TYPE_INT);
01147   cpl_table_new_column(encoder_tbl,"flag",CPL_TYPE_INT);
01148  
01149   for(i=0;i<cpl_frameset_get_size(set);i++)
01150     {
01151     check_nomsg(frm=cpl_frameset_get_frame_const(set,i));
01152     check_nomsg(plist=uves_propertylist_load(cpl_frame_get_filename(frm),0));
01153     check_nomsg(x1enc=uves_pfits_get_slit3_x1encoder(plist));
01154     check_nomsg(x2enc=uves_pfits_get_slit3_x2encoder(plist));
01155     check_nomsg(cpl_table_set_int(encoder_tbl,"x1enc",i,x1enc));
01156     check_nomsg(cpl_table_set_int(encoder_tbl,"x2enc",i,x2enc));
01157     uves_free_propertylist(&plist);
01158     }
01159  
01160   check_nomsg(uves_sort_table_2(encoder_tbl,"x1enc","x2enc",false,true));
01161 
01162   check_nomsg(ref_x1enc=cpl_table_get_int(encoder_tbl,"x1enc",0,&status));
01163   check_nomsg(ref_x2enc=cpl_table_get_int(encoder_tbl,"x2enc",0,&status));
01164   *nset=1;
01165   *enc=cpl_table_new(1);
01166   cpl_table_new_column(*enc,"x1enc",CPL_TYPE_INT);
01167   cpl_table_new_column(*enc,"x2enc",CPL_TYPE_INT);
01168   check_nomsg(cpl_table_set_int(*enc,"x1enc",0,ref_x1enc));
01169   check_nomsg(cpl_table_set_int(*enc,"x2enc",0,ref_x2enc));
01170 
01171   for(i=1;i<cpl_table_get_nrow(encoder_tbl);i++) {
01172      check_nomsg(x1enc=cpl_table_get_int(encoder_tbl,"x1enc",i,&status));
01173      check_nomsg(x2enc=cpl_table_get_int(encoder_tbl,"x2enc",i,&status));
01174      if( (fabs(ref_x1enc -x1enc) > threshold) || 
01175          (fabs(ref_x2enc -x2enc) > threshold) ) {
01176   
01177        ref_x1enc = x1enc;
01178        ref_x2enc = x2enc;
01179        cpl_table_set_size(*enc,(*nset+1));
01180        check_nomsg(cpl_table_set_int(*enc,"x1enc",*nset,ref_x1enc));
01181        check_nomsg(cpl_table_set_int(*enc,"x2enc",*nset,ref_x2enc));
01182        *nset=*nset+1;
01183 
01184      }
01185   }
01186   uves_msg("Number of sets = %d",*nset);
01187 
01188   cleanup:
01189    uves_free_table(&encoder_tbl);
01190     uves_free_propertylist(&plist);
01191     return cpl_error_get_code();
01192 }
01193 
01194 
01195 /*----------------------------------------------------------------------------*/
01201 /*----------------------------------------------------------------------------*/
01202 cpl_error_code
01203 uves_dfs_set_groups(cpl_frameset * set)
01204 {
01205     cpl_frame   *   cur_frame ;
01206     int             nframes ;
01207     
01208     /* Check entries */
01209     assure(set != NULL, CPL_ERROR_NULL_INPUT, "Null input"); 
01210     
01211     /* Initialize */
01212     check( nframes = cpl_frameset_get_size(set), "Could not read frameset size");
01213     
01214     /* Loop on frames */
01215     for (cur_frame = cpl_frameset_get_first(set);
01216      cur_frame != NULL;
01217      cur_frame = cpl_frameset_get_next(set))
01218     {
01219         bool is_raw   = false;
01220         bool is_calib = false;
01221         bool is_recognized = false;
01222         bool blue;
01223         enum uves_chip chip;
01224         const char  *   tag = cpl_frame_get_tag(cur_frame);
01225         
01226         assure( tag != NULL && strcmp(tag, "") != 0, CPL_ERROR_ILLEGAL_INPUT,
01227             "Frame has no tag!");
01228         
01229         blue = false;
01230         do {
01231         bool flames = false;
01232         do {
01233             /* RAW frames */
01234             is_raw   = is_raw   || 
01235             (strcmp(tag, UVES_ORDER_FLAT  (flames,blue)) == 0 ||
01236              strcmp(tag, UVES_BIAS        (blue)) == 0 ||
01237              strcmp(tag, UVES_DARK        (blue)) == 0 ||
01238              strcmp(tag, UVES_PDARK       (blue)) == 0 ||
01239              strcmp(tag, UVES_FLAT        (blue)) == 0 ||
01240              strcmp(tag, UVES_IFLAT       (blue)) == 0 ||
01241              strcmp(tag, UVES_DFLAT       (blue)) == 0 ||
01242              strcmp(tag, UVES_SFLAT       (blue)) == 0 ||
01243              strcmp(tag, UVES_TFLAT       (blue)) == 0 ||
01244              strcmp(tag, UVES_SCREEN_FLAT (blue)) == 0 ||
01245              strcmp(tag, UVES_CD_ALIGN    (blue)) == 0 ||
01246              strcmp(tag, UVES_FORMATCHECK (flames,blue)) == 0 ||
01247              strcmp(tag, UVES_STD_STAR    (blue)) == 0 ||
01248              strcmp(tag, UVES_SCIENCE     (blue)) == 0 ||
01249              strcmp(tag, UVES_SCI_EXTND   (blue)) == 0 ||
01250              strcmp(tag, UVES_SCI_POINT   (blue)) == 0 ||
01251              strcmp(tag, UVES_SCI_SLICER  (blue)) == 0 ||
01252              strcmp(tag, UVES_ARC_LAMP    (flames,blue)) == 0 ||
01253              strcmp(tag, UVES_ECH_ARC_LAMP(blue)) == 0 ||
01254              strcmp(tag, RAW_IMA) == 0 ||
01255              strcmp(tag, FLAMES_SCI_RED) == 0 ||
01256              strcmp(tag, FLAMES_SCI_SIM_RED) == 0 ||
01257              strcmp(tag, FLAMES_SCI_COM_RED) == 0 ||
01258              strcmp(tag, FLAMES_FIB_FF_ODD) == 0 ||
01259              strcmp(tag, FLAMES_FIB_FF_EVEN) == 0 ||
01260              strcmp(tag, FLAMES_FIB_FF_ALL) == 0);
01261             
01262             /* CALIB frames */
01263             
01264             /* Loop through all (1 or 2) blue or red chips */
01265             for (chip = uves_chip_get_first(blue);
01266              chip != UVES_CHIP_INVALID; 
01267              chip = uves_chip_get_next(chip))
01268             {
01269                 int window;
01270                 
01271                 is_calib = is_calib || 
01272                 (strcmp(tag, UVES_DRS_SETUP(flames, chip)) == 0 ||
01273                  strcmp(tag, UVES_ORDER_TABLE(flames, chip)) == 0 ||
01274                  strcmp(tag, UVES_GUESS_ORDER_TABLE(flames,chip)) == 0 ||
01275                  strcmp(tag, UVES_MASTER_BIAS   (chip)) == 0 ||
01276                  strcmp(tag, UVES_MASTER_DARK   (chip)) == 0 ||
01277                  strcmp(tag, UVES_MASTER_PDARK  (chip)) == 0 ||
01278                  strcmp(tag, UVES_MASTER_FLAT   (chip)) == 0 ||
01279                  strcmp(tag, UVES_MASTER_DFLAT  (chip)) == 0 ||
01280                  strcmp(tag, UVES_MASTER_SFLAT  (chip)) == 0 ||
01281                  strcmp(tag, UVES_MASTER_IFLAT  (chip)) == 0 ||
01282                  strcmp(tag, UVES_MASTER_TFLAT  (chip)) == 0 ||
01283                  strcmp(tag, UVES_REF_TFLAT     (chip)) == 0 ||
01284                  strcmp(tag, UVES_ORD_TAB(flames,chip)) == 0 ||
01285                  strcmp(tag, UVES_MASTER_SCREEN_FLAT(chip)) == 0 ||
01286                  strcmp(tag, UVES_MASTER_ARC_FORM(chip)) == 0 ||
01287                  strcmp(tag, UVES_WEIGHTS(chip))        == 0 ||
01288                  strcmp(tag, UVES_LINE_TABLE(flames,chip)) == 0 ||
01289                  strcmp(tag, UVES_GUESS_LINE_TABLE(flames,chip)) == 0 ||
01290                  strcmp(tag, UVES_INSTR_RESPONSE(chip)) == 0 ||
01291                  strcmp(tag, UVES_MASTER_RESPONSE(chip)) == 0 ||
01292                  strcmp(tag, UVES_LINE_REFER_TABLE    ) == 0 ||
01293                  strcmp(tag, UVES_LINE_INTMON_TABLE   ) == 0 ||
01294                  strcmp(tag, UVES_FLUX_STD_TABLE      ) == 0 ||
01295                  strcmp(tag, UVES_EXTCOEFF_TABLE      ) == 0 ||
01296                  strcmp(tag, FLAMES_LINE_TABLE(chip)) == 0 ||
01297                  strcmp(tag, FLAMES_SLIT_FF_DT1(chip)) == 0 ||
01298                  strcmp(tag, FLAMES_SLIT_FF_DT2(chip)) == 0 ||
01299                  strcmp(tag, FLAMES_SLIT_FF_DT3(chip)) == 0 ||
01300                  strcmp(tag, FLAMES_SLIT_FF_DTC(chip)) == 0 ||
01301                  strcmp(tag, FLAMES_SLIT_FF_BP1(chip)) == 0 ||
01302                  strcmp(tag, FLAMES_SLIT_FF_BP2(chip)) == 0 ||
01303                  strcmp(tag, FLAMES_SLIT_FF_BP3(chip)) == 0 ||
01304                  strcmp(tag, FLAMES_SLIT_FF_BPC(chip)) == 0 ||
01305                  strcmp(tag, FLAMES_SLIT_FF_BN1(chip)) == 0 ||
01306                  strcmp(tag, FLAMES_SLIT_FF_BN2(chip)) == 0 ||
01307                  strcmp(tag, FLAMES_SLIT_FF_BN3(chip)) == 0 ||
01308                  strcmp(tag, FLAMES_SLIT_FF_BNC(chip)) == 0 ||
01309                  strcmp(tag, FLAMES_SLIT_FF_SG1(chip)) == 0 ||
01310                  strcmp(tag, FLAMES_SLIT_FF_SG2(chip)) == 0 ||
01311                  strcmp(tag, FLAMES_SLIT_FF_SG3(chip)) == 0 ||
01312                  strcmp(tag, FLAMES_SLIT_FF_SGC(chip)) == 0 ||
01313                  strcmp(tag, FLAMES_SLIT_FF_COM(chip)) == 0 ||
01314                  strcmp(tag, FLAMES_SLIT_FF_NOR(chip)) == 0 ||
01315                  strcmp(tag, FLAMES_SLIT_FF_NSG(chip)) == 0 ||
01316                  strcmp(tag, FLAMES_FIB_FF_DT1(chip)) == 0 ||
01317                  strcmp(tag, FLAMES_FIB_FF_DT2(chip)) == 0 ||
01318                  strcmp(tag, FLAMES_FIB_FF_DT3(chip)) == 0 ||
01319                  strcmp(tag, FLAMES_FIB_FF_DTC(chip)) == 0 ||
01320                  strcmp(tag, FLAMES_FIB_FF_BP1(chip)) == 0 ||
01321                  strcmp(tag, FLAMES_FIB_FF_BP2(chip)) == 0 ||
01322                  strcmp(tag, FLAMES_FIB_FF_BP3(chip)) == 0 ||
01323                  strcmp(tag, FLAMES_FIB_FF_BPC(chip)) == 0 ||
01324                  strcmp(tag, FLAMES_FIB_FF_BN1(chip)) == 0 ||
01325                  strcmp(tag, FLAMES_FIB_FF_BN2(chip)) == 0 ||
01326                  strcmp(tag, FLAMES_FIB_FF_BN3(chip)) == 0 ||
01327                  strcmp(tag, FLAMES_FIB_FF_BNC(chip)) == 0 ||
01328                  strcmp(tag, FLAMES_FIB_FF_SG1(chip)) == 0 ||
01329                  strcmp(tag, FLAMES_FIB_FF_SG2(chip)) == 0 ||
01330                  strcmp(tag, FLAMES_FIB_FF_SG3(chip)) == 0 ||
01331                  strcmp(tag, FLAMES_FIB_FF_SGC(chip)) == 0 ||
01332                  strcmp(tag, FLAMES_FIB_FF_COM(chip)) == 0 ||
01333                  strcmp(tag, FLAMES_FIB_FF_NOR(chip)) == 0 ||
01334                  strcmp(tag, FLAMES_FIB_FF_NSG(chip)) == 0 ||
01335                  strcmp(tag, FLAMES_ORDEF(flames,chip)) == 0 ||
01336                  strcmp(tag, FLAMES_CORVEL_MASK) == 0);
01337                 
01338                 for (window = 1; window <= 3; window++)
01339                 {
01340                     is_calib = is_calib || 
01341                     strcmp(tag, UVES_LINE_TABLE_MIDAS(chip, window)) == 0;
01342                 }
01343                 
01344                 if (!flames && strcmp(tag, UVES_BACKGR_TABLE(chip)) == 0)
01345                 {
01346                     uves_msg_warning("Background table %s has been deprecated. "
01347                              "Inter-order positions will be inferred "
01348                              "from the order table %s. "
01349                              "Use recipe parameters to define "
01350                              "measuring method ",
01351                              UVES_BACKGR_TABLE(chip), 
01352                              UVES_ORDER_TABLE(flames, chip));
01353                     
01354                     is_recognized = true;
01355                 }
01356                 
01357                 if (strcmp(tag, UVES_DRS_SETUP(flames, chip)) == 0)
01358                 {
01359                     uves_msg_warning("DRS setup table %s has been deprecated. "
01360                              "Use recipe parameters "
01361                              "to define data reduction parameters ",
01362                              UVES_DRS_SETUP(flames, chip));
01363                     
01364                     is_recognized = true;
01365                 }
01366             }
01367             flames = !flames;
01368         } while (flames);
01369         blue = !blue;
01370         }
01371         while (blue);
01372         
01373         is_recognized = is_recognized || is_raw || is_calib;
01374 
01375         if (is_raw)
01376         {
01377             cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW) ;
01378         }
01379         else if (is_calib)
01380         {
01381             cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_CALIB) ;
01382         }
01383         else if (!is_recognized)
01384         {
01385             uves_msg_warning("Unrecognized tag %s", tag);
01386         }
01387     }
01388 
01389     uves_dfs_files_dont_exist(set);
01390 
01391 
01392   cleanup:
01393     return cpl_error_get_code();
01394 }
01395 
01396 
01397 /*----------------------------------------------------------------------------*/
01406 /*----------------------------------------------------------------------------*/
01407 static void
01408 remove_pre_over_scan(uves_propertylist *pl)
01409 {
01410     bool blue, new_format;
01411     enum uves_chip chip;
01412     
01413     new_format = false;
01414     do {
01415     blue = false;
01416     do {
01417         for (chip = uves_chip_get_first(blue); 
01418          chip != UVES_CHIP_INVALID;
01419          chip = uves_chip_get_next(chip))
01420         {
01421             int n_erase_px = 0;   /* Number of erased properties */
01422             int n_erase_py = 0;
01423             int n_erase_ox = 0;
01424             int n_erase_oy = 0;
01425             
01426             do {
01427             /* This function erases only one property at a time,
01428              *  therefore call it until it returns 0
01429              */
01430             check( n_erase_px = 
01431                    uves_propertylist_erase(pl, UVES_PRESCANX(new_format, chip)),
01432                    "Error erasing keyword '%s'", UVES_PRESCANX(new_format, chip));
01433             
01434             check( n_erase_py = 
01435                    uves_propertylist_erase(pl, UVES_PRESCANY(new_format, chip)),
01436                    "Error erasing keyword '%s'", UVES_PRESCANY(new_format, chip));
01437             
01438             check( n_erase_ox =
01439                    uves_propertylist_erase(pl, UVES_OVRSCANX(new_format, chip)),
01440                    "Error erasing keyword '%s'", UVES_OVRSCANX(new_format, chip));
01441             
01442             check( n_erase_oy =
01443                    uves_propertylist_erase(pl, UVES_OVRSCANY(new_format, chip)),
01444                    "Error erasing keyword '%s'", UVES_OVRSCANY(new_format, chip));
01445             }
01446             while (n_erase_px > 0 ||
01447                n_erase_py > 0 ||
01448                n_erase_ox > 0 ||
01449                n_erase_oy > 0);
01450         }
01451         blue = !blue;
01452     }
01453     while (blue);
01454     
01455     new_format = !new_format;
01456     }
01457     while (new_format);
01458 
01459   cleanup:
01460     return;
01461 }
01462 
01463 
01464 /*----------------------------------------------------------------------------*/
01474 /*----------------------------------------------------------------------------*/
01475 
01476 void
01477 uves_copy_if_possible(uves_propertylist *to, const uves_propertylist *from,
01478          const char *name)
01479 {
01480     if (!uves_propertylist_contains(to, name) &&
01481     uves_propertylist_contains(from, name))
01482     {
01483         uves_msg_debug("Propagating keyword %s", name);
01484 
01485         check_nomsg( uves_propertylist_copy_property(to, from, name) );
01486     }
01487     else
01488     {
01489         uves_msg_debug("Keyword %s not propagated", name);
01490     }
01491     
01492   cleanup:
01493     return;
01494 }
01495 
01496 /*----------------------------------------------------------------------------*/
01540 /*----------------------------------------------------------------------------*/
01541 cpl_error_code
01542 uves_frameset_insert(cpl_frameset *frames, 
01543                      void *object, 
01544                      cpl_frame_group group, 
01545                      cpl_frame_type type, 
01546                      cpl_frame_level level,
01547                      const char *filename, 
01548                      const char *tag, 
01549                      const uves_propertylist *raw_header,
01550                      const uves_propertylist *primary_header, 
01551                      const uves_propertylist *table_header, 
01552                      const cpl_parameterlist *parameters, 
01553                      const char *recipe, 
01554                      const char *pipeline,
01555                      cpl_table **qc,
01556                      const char *start_time,
01557                      bool dump_paf,
01558                      unsigned stats_mask)
01559 {
01560     cpl_frame *f = NULL;
01561     uves_propertylist *pl = NULL;
01562     const char *origin = "";
01563 
01564     passure( !(type == CPL_FRAME_TYPE_IMAGE && table_header != NULL), " ");
01565     passure( raw_header != NULL, " ");
01566     passure( primary_header != NULL, " ");
01567 
01568     assure( type == CPL_FRAME_TYPE_IMAGE || stats_mask == 0,
01569         CPL_ERROR_INCOMPATIBLE_INPUT,
01570         "Cannot compute image statistics on table product" );
01571 
01572     /* Insert the object (image or table) into frameset */
01573     check(( f = cpl_frame_new(),
01574             cpl_frame_set_filename(f, filename),    /* local filename */
01575             cpl_frame_set_tag     (f, tag),         /* e.g. ORDER_TABLE_BLUE */
01576             cpl_frame_set_type    (f, type),        /* e.g. table */
01577             cpl_frame_set_group   (f, group),       /* e.g. raw/product */
01578             cpl_frame_set_level   (f, level),       /* e.g. temporary/final */
01579             cpl_frameset_insert(frames, f)), "Could not insert frame into frameset");
01580     
01581     /* Pipeline id format is <PACKAGE "/" PACKAGE_VERSION>; */
01582     if (strchr(pipeline, '/') == NULL)
01583     {
01584         uves_msg_warning("Pipeline ID '%s' is not of format: "
01585                  "Pipeline-name/version", pipeline);
01586     }
01587 
01588     /* Copy provided keywords in 'primary_header' to 'pl' */
01589     pl = uves_propertylist_new();
01590     if (!uves_propertylist_is_empty(primary_header))
01591     {
01592         if (0)
01593                 /* This takes (n*m) time */
01594                 {
01595                     /* The regexp "" matches any string (because any string has
01596                        the empty string as a sub-string),
01597                        except on Mac, where it is an illegal regexp (for whatever reason).
01598                        Therefore, use ".*" to match any string */
01599                     
01600                     check( uves_propertylist_copy_property_regexp(pl, primary_header, ".*", 0),
01601                            "Could not copy keywords");
01602                 }
01603             else
01604                 check( uves_propertylist_append(pl, primary_header),
01605                        "Could not copy keywords");
01606     }
01607     
01608     /* Propagate/create DFS keywords */
01609     UVES_TIME_START("cpl_dfs_setup_product_header");
01610     check( uves_dfs_setup_product_header(pl,
01611                     f,
01612                     frames,
01613                     parameters,
01614                     recipe,
01615                     pipeline,
01616                     DICTIONARY),
01617        "Error setting up product header");
01618     UVES_TIME_END;
01619     
01620     /* Change origin to 'ESO' if it says 'ESO-MIDAS'
01621      * NOST-Definition: "The value field shall contain a character string
01622      *                   identifying the organization or institution responsible 
01623      *                   for creating the FITS file."
01624      */
01625     
01626     check( uves_get_property_value(pl, "ORIGIN", CPL_TYPE_STRING, &origin),
01627        "Error reading ORIGIN from product header");
01628 
01629     if (strcmp(origin, "ESO-MIDAS") == 0) 
01630     {
01631         uves_propertylist_set_string(pl, "ORIGIN", "ESO");
01632     }
01633     
01634     /* Set OBJECT = DO category */
01635     check( uves_pfits_set_object(pl, tag), "Error writing object keyword");
01636         
01637     /* Add statistics keywords */
01638     if (type == CPL_FRAME_TYPE_IMAGE && stats_mask != 0)
01639     {
01640         check( uves_dfs_write_statistics((cpl_image *) object, pl, stats_mask),
01641            "Error adding image statistics keywords");
01642     }
01643     
01644     /* Propagate ESO.DET keywords from 'raw_header',
01645      * This is necessary because cpl_dfs_setup_product_header() copies
01646      * only from the primary extension of the first input frames
01647      */
01648     check( uves_propertylist_copy_property_regexp(pl, raw_header, "^ESO DET ", 0),
01649        "Could not propagate 'ESO DET*' keywords");
01650 
01651     /* But remove prescan, overscan keywords. 
01652        (Since these areas are not present in any products.) */
01653     check( remove_pre_over_scan(pl), 
01654        "Error removing pre-, overscan keywords from product header");
01655 
01656     /* Propagate certain keywords from 'raw_header' 
01657        (only if available and if not already present in product header) */
01658     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_AIRMASS) );
01659     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_IMAGETYP) );
01660     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_UT) );
01661     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_ST) );
01662     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_EXPTIME) );
01663     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_EXTNAME) );
01664     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_DATE) );
01665     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_DATAMEAN) );
01666     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_DATAMED) );
01667     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_DATARMS) );
01668     check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_OS_EXPOI) );
01669 
01670     /* MIDAS internal(?): check_nomsg( uves_copy_if_possible(pl, raw_header, UVES_TMSTART) ); */
01671 
01672     if (0)
01673         /* uves_propertylist_copy_property_regexp() is slow */
01674         {
01675             check( uves_propertylist_copy_property_regexp(pl, raw_header, "^GRAT[0-9]*$", 0),
01676                    "Could not propagate 'GRATi' keywords");
01677             check( uves_propertylist_copy_property_regexp(pl, raw_header, "^FILTER[0-9]*$", 0),
01678                    "Could not propagate 'FILTERi' keywords");
01679             check( uves_propertylist_copy_property_regexp(pl, raw_header, "^WLEN[0-9]*$", 0),
01680                    "Could not propagate 'WLENi' keywords");
01681         }
01682     else
01683         {
01684             check( uves_propertylist_copy_property_regexp(
01685                        pl, raw_header, "^((GRAT|FILTER|WLEN)[0-9]*)$", 0),
01686                    "Could not propagate GRATi, FILTERi and WLENi keywords");
01687         }
01688 
01689     /* If RA,DEC do not exist, invent them and set to zero, like MIDAS */
01690     if ( !uves_propertylist_contains(pl, UVES_RA) )
01691     {
01692         uves_pfits_set_ra(pl, 0);
01693     }
01694     if ( !uves_propertylist_contains(pl, UVES_DEC) )
01695     {
01696         uves_pfits_set_dec(pl, 0);
01697     }
01698 
01699     /* 
01700      * REDLEVEL and STATUS have been deprecated, so delete them
01701      * along with inherited MIDAS specific keywords
01702      */
01703     {
01704         bool invert = false;
01705         uves_propertylist_erase_regexp(pl, "^("
01706                                        "ESO PRO (REDLEVEL|REC[0-9]+ STATUS)|"
01707                                        "TM-START|MIDASFTP|FILENAME)$", invert);
01708     }
01709 
01710     check( uves_pfits_set_starttime(pl, start_time),
01711        "Could not write recipe start time");
01712 
01713     check( uves_pfits_set_stoptime(pl, uves_get_datetime_iso8601()),
01714        "Could not write recipe stop time");
01715 
01716     /* Create paf file from each QC table, and transfer
01717        all QC parameters to product header
01718     */
01719     if (qc != NULL)
01720     {
01721         int i;
01722         for (i = 0; qc[i] != NULL; i++)
01723         {
01724             uves_pfits_put_qc(pl, qc[i]);
01725                         
01726             if (dump_paf)
01727             {
01728                 /* Exception! This is a hack */
01729                 if (strcmp(recipe, make_str(UVES_TFLAT_ID)) == 0 && i == 1)
01730                 {
01731                     /* Don't dump the science QC again */
01732                 }
01733                 else
01734                 {
01735           /*
01736                     uves_save_paf(filename, i, recipe, qc[i], 
01737                           pl, raw_header, tag);
01738           */
01739                 }
01740             }
01741         } 
01742     }
01743 
01744     UVES_TIME_START("save product");
01745 
01746     /* Now save with the correct header */
01747     if (type == CPL_FRAME_TYPE_IMAGE)
01748     {
01749         bool use_bitpix16_for_int = (strcmp(recipe, make_str(FLAMES_CAL_ORDERPOS)) == 0);
01750         
01751         check( uves_save_image((cpl_image *) object, filename, pl, 
01752                                use_bitpix16_for_int, true), 
01753            "Error saving image to file %s", filename);
01754     }
01755     else if (type == CPL_FRAME_TYPE_TABLE)                           /* Table */
01756     {
01757         check( uves_table_save((cpl_table *) object,
01758                   pl,                                /* Primary header */
01759                   table_header,                      /* Table header */
01760                   filename,
01761                   CPL_IO_DEFAULT),                   /* Create new file */
01762            "Error saving table to file '%s'", filename);
01763     }
01764     else
01765     {
01766         assure(false, CPL_ERROR_UNSUPPORTED_MODE, "Unsupported frame type");
01767     }
01768 
01769     UVES_TIME_END;
01770     
01771   cleanup:
01772     uves_free_propertylist(&pl);
01773     
01774     return cpl_error_get_code();
01775 }
01776 
01777 
01778 /*----------------------------------------------------------------------------*/
01787 /*----------------------------------------------------------------------------*/
01788 void
01789 uves_dfs_write_statistics(const cpl_image *image, uves_propertylist *header,
01790          unsigned stats_mask)
01791 {
01792     cpl_stats *stats = NULL;
01793 
01794     /* Only these bits are supported, all others must be zero */
01795     assure( (stats_mask & (CPL_STATS_MEAN | CPL_STATS_STDEV | CPL_STATS_MEDIAN |
01796               CPL_STATS_MIN  | CPL_STATS_MAX)) == stats_mask,
01797         CPL_ERROR_UNSUPPORTED_MODE, "Cannot compute mask %d",
01798         stats_mask );
01799 
01800     UVES_TIME_START("calculate stats");
01801 
01802     check( stats = cpl_stats_new_from_image(
01803            image, stats_mask),
01804        "Error reading image statistics");
01805     
01806     UVES_TIME_END;
01807     
01808     if (stats_mask & CPL_STATS_MEDIAN)
01809     {
01810         check( uves_pfits_set_data_median (header, cpl_stats_get_median(stats) ), 
01811            "Could not write median flux");
01812     }
01813     if (stats_mask & CPL_STATS_MEAN)
01814     {
01815         check( uves_pfits_set_data_average(header, cpl_stats_get_mean  (stats) ), 
01816            "Could not write average flux");
01817     }
01818     if (stats_mask & CPL_STATS_STDEV)
01819     {
01820         check( uves_pfits_set_data_stddev (header, cpl_stats_get_stdev (stats) ), 
01821            "Could not write flux stdev");
01822     }
01823     if (stats_mask & CPL_STATS_MIN)
01824     {
01825         check( uves_pfits_set_data_min    (header, cpl_stats_get_min   (stats) ), 
01826            "Could not write min flux");
01827     }
01828     if (stats_mask & CPL_STATS_MIN)
01829     {
01830         check( uves_pfits_set_data_max    (header, cpl_stats_get_max   (stats) ), 
01831            "Could not write max flux");
01832     }
01833 
01834   cleanup:
01835     uves_free_stats(&stats);
01836     return;
01837 }
01838 
01839 
01840 /*----------------------------------------------------------------------------*/
01875 /*----------------------------------------------------------------------------*/
01876 void *
01877 uves_read_midas_array(const uves_propertylist *plist, const char *name, 
01878                       int *length, cpl_type *type, int *ncards)
01879 {
01880     void *result = NULL;
01881     unsigned result_size;
01882     int N = strlen(name);
01883     bool found = false;
01884     const char *value;
01885     int size;
01886     int i;
01887     const long int plist_size = uves_propertylist_get_size(plist);
01888    
01889     assure_nomsg( length != NULL, CPL_ERROR_NULL_INPUT );
01890     assure_nomsg(   type != NULL, CPL_ERROR_NULL_INPUT );
01891     for (i = 0; !found && i < plist_size; i++)
01892     {
01893       const cpl_property *p = uves_propertylist_get_const(plist, i);
01894       value = cpl_property_get_name(p);
01895       
01896       if (strcmp(value, "HISTORY") == 0)
01897         {
01898           
01899           check( value = cpl_property_get_string(p),
01900          "Error reading property value");
01901           
01902           /* match the string  "'<name>','t"  */
01903           
01904           if ((int)strlen(value) >= 1+N+4 &&
01905           value[0]     == '\'' &&
01906           value[N+1]   == '\'' && 
01907           value[N+2]   == ','  && 
01908           value[N+3]   == '\'' && 
01909           strncmp(value+1, name, N) == 0
01910           )
01911         { 
01912           switch(value[N+4]) {
01913           case 'R':
01914         /* Distinguish between 
01915            "'<name>','R*4'" and
01916            "'<name>','R*8'"
01917         */
01918         *type = CPL_TYPE_DOUBLE;
01919 
01920         if ((int)strlen(value) >= 1+N+4+2 && value[N+4+1] == '*')
01921           {
01922             switch(value[N+4+2]) {
01923             case '4': *type = CPL_TYPE_FLOAT; break;
01924             case '8': *type = CPL_TYPE_DOUBLE; break; 
01925             default:
01926               assure( false, CPL_ERROR_ILLEGAL_INPUT,
01927                   "Unrecognized MIDAS type: 'R*%c'",
01928                   value[N+4+2]);
01929               break;
01930             }
01931           }
01932         break;
01933           case 'I': *type = CPL_TYPE_INT   ; size = sizeof(int);    break;
01934           case 'C': *type = CPL_TYPE_STRING; size = sizeof(char);   break;
01935           default:
01936         assure( false, CPL_ERROR_UNSUPPORTED_MODE,
01937             "Unrecognized type '%c'", value[N+4]);
01938         break;
01939           }
01940           found = true;
01941         }
01942         }
01943     }
01944     
01945     assure( found, CPL_ERROR_ILLEGAL_INPUT, "Could not find '%s' in property list", name);
01946     
01947     /* 'i' is now the row immediately after first occurence of 'HISTORY   '<name>...  */
01948     result_size = sizeof(double) * 100;  /* realloc when/if out of memory */
01949     result = cpl_malloc(result_size);
01950 
01951     *length = 0;
01952     if (ncards != NULL) *ncards = 2; /* First HISTORY entry + termination HISTORY entry */
01953     do {
01954       const cpl_property *p;
01955 
01956       if (ncards != NULL) *ncards += 1;
01957 
01958       assure(i < plist_size, 
01959          CPL_ERROR_ILLEGAL_INPUT, "Missing header data");
01960       p = uves_propertylist_get_const(plist, i);
01961       assure(       cpl_property_get_type(p)             == CPL_TYPE_STRING &&
01962             strcmp(cpl_property_get_name(p), "HISTORY") == 0, 
01963             CPL_ERROR_ILLEGAL_INPUT, "Error parsing array");
01964       value = cpl_property_get_string(uves_propertylist_get_const(plist, i));
01965     
01966       uves_msg_debug("Parsing '%s'", value);
01967 
01968       if (*type == CPL_TYPE_STRING)
01969     {
01970       assure( strlen(value) < 100, CPL_ERROR_UNSUPPORTED_MODE, 
01971           "String too long. Max size is 100");
01972 
01973       /* Remove any blanks from the string
01974          (e.g. convert "0 1 2" to "012")
01975       */
01976       {
01977         int len = strlen(value);
01978         int j = 0;
01979         int k;
01980         for (k = 0; k <= len; k++)  /* including final '\0' */
01981           {
01982         //if (value[k] != ' '){
01983         ((char*)result)[j] = value[k];
01984         j++;
01985         //      }
01986           }
01987         *length = j-1;
01988       }
01989 
01990       uves_msg_debug("Converted '%s' to '%s'",
01991              value, (char*)result);
01992                 
01993       /* done parsing */
01994       value = "";
01995     }
01996         
01997       else { /* numerical types */
01998     if (strcmp(value, "") != 0) {
01999       double numberd = -1; /* suppres warning */
02000       int numberi = -1;
02001       float numberf = -1;
02002       const int base = 10;
02003       char *next = (char *) value;
02004 
02005       do {
02006             /* ignore OUTPUTI(1)- N,no.of data, */
02007         switch(*type) {
02008         case CPL_TYPE_DOUBLE:
02009           numberd = strtod(value, &next);
02010           uves_msg_debug("Got %g, remaining: '%s'", numberd, next);
02011           break;
02012         case CPL_TYPE_FLOAT:
02013           numberf = strtod(value, &next); // C99: strtof(value, &next);
02014           uves_msg_debug("Got %g, remaining: '%s'", numberf, next);
02015           break;
02016         case CPL_TYPE_INT:
02017           numberi = strtol(value, &next, base);
02018           uves_msg_debug("Got %d, remaining: '%s'", numberi, next);
02019           break;
02020         default:
02021           passure(false, " ");
02022         }
02023                     
02024             if (next != value)
02025           {
02026                 /* A prefix of the string could be converted */
02027                 (*length)++;
02028         if (*length * sizeof(double) > result_size)
02029           {
02030             result_size *= 2;
02031             result = cpl_realloc(result, result_size);
02032           }
02033 
02034         switch(*type) {
02035         case CPL_TYPE_DOUBLE:
02036           ((double *)result)[*length-1] = numberd;
02037           break;
02038         case CPL_TYPE_FLOAT:
02039           ((float *)result)[*length-1] = numberf;
02040           break;
02041         case CPL_TYPE_INT:
02042           ((int    *)result)[*length-1] = numberi;
02043           break;
02044         default:
02045           passure(false, " ");
02046         }
02047 
02048                 value = next;
02049                             
02050         switch(*type) {
02051         case CPL_TYPE_DOUBLE:
02052           numberd = strtod(value, &next);
02053           uves_msg_debug("Got %g, remaining: '%s'", numberd, next);
02054           break;
02055         case CPL_TYPE_FLOAT:
02056           numberf = strtod(value, &next); // C99: strtof(value, &next);
02057           uves_msg_debug("Got %g, remaining: '%s'", numberf, next);
02058           break;
02059         case CPL_TYPE_INT:
02060           numberi = strtol(value, &next, base);
02061           uves_msg_debug("Got %d, remaining: '%s'", numberi, next);
02062           break;
02063         default:
02064           passure(false, " ");
02065         }
02066           }
02067       } while (next != value);
02068         }
02069       }/* if numerical type */
02070         
02071       i++;
02072 
02073       assure( strcmp(value, "") == 0, CPL_ERROR_ILLEGAL_INPUT,
02074           "Cannot parse %s descriptor %s, remaining string: '%s'", 
02075           uves_tostring_cpl_type(*type), name, value);
02076     
02077       /* Find out if we can continue parsing the next HISTORY keyword */
02078       if (i < plist_size)
02079         {
02080       p = uves_propertylist_get_const(plist, i);
02081       if (cpl_property_get_type(p) == CPL_TYPE_STRING &&
02082           strcmp(cpl_property_get_name(p), "HISTORY") == 0)
02083             {
02084           value = cpl_property_get_string(
02085                           uves_propertylist_get_const(plist, i));
02086 
02087           if (*type == CPL_TYPE_STRING)
02088         {
02089           if (strcmp(value, "") != 0) {
02090             uves_msg_debug("String array %s with length > 1 found. Ignoring remaining values", name);
02091             while (strcmp(value, "") != 0 && i+1 < plist_size) {
02092               i++;
02093               p = uves_propertylist_get_const(plist, i);
02094               value = cpl_property_get_string(
02095                               uves_propertylist_get_const(plist, i));
02096               if (ncards != NULL) *ncards += 1;
02097             }
02098           }
02099         }
02100         }
02101     }
02102       
02103     } while (strcmp(value, "") != 0);
02104     
02105  cleanup:
02106     if (cpl_error_get_code() != CPL_ERROR_NONE)
02107       {
02108     cpl_free(result); result = NULL;
02109       }
02110     return result;
02111 }
02112 
02113 
02114 /*----------------------------------------------------------------------------*/
02132 /*----------------------------------------------------------------------------*/
02133 cpl_error_code
02134 uves_save_table_local(const char *description, const char *filename_prefix,
02135               const cpl_table *table, 
02136               enum uves_chip chip, int trace, int window,
02137               const uves_propertylist *pheader, const uves_propertylist *eheader)
02138 {
02139     char *filename = NULL;
02140 
02141     check( filename = uves_local_filename(filename_prefix, chip, trace, window),
02142        "Error getting filename");
02143 
02144     check( uves_table_save(table, pheader, eheader, filename, CPL_IO_DEFAULT), 
02145        "Error saving table to file '%s'", filename);
02146     
02147     if (description != NULL) uves_msg("%s saved to '%s'", description, filename);
02148     
02149   cleanup:
02150     cpl_free(filename);
02151     return cpl_error_get_code();
02152 }
02153 
02154 /*----------------------------------------------------------------------------*/
02175 /*----------------------------------------------------------------------------*/
02176 cpl_error_code
02177 uves_save_image_local(const char *description, const char *filename_prefix, 
02178                       const cpl_image *image, 
02179                       enum uves_chip chip, int trace, int window,
02180                       const uves_propertylist *plist,
02181                       bool use_bitpix16_for_int)
02182 {
02183     char *filename = NULL;
02184     
02185     check( filename = uves_local_filename(filename_prefix, chip, trace, window),
02186        "Error getting filename");
02187     
02188     check( uves_save_image(image, filename, plist, use_bitpix16_for_int, true),
02189            "Error saving image to file '%s'", filename);
02190     if (description != NULL) uves_msg("%s saved to '%s'", description, filename);
02191     
02192   cleanup:
02193     cpl_free(filename);
02194     return cpl_error_get_code();
02195 }
02196 
02197 
02198 /*----------------------------------------------------------------------------*/
02208 /*----------------------------------------------------------------------------*/
02209 cpl_image *uves_load_image(const cpl_frame *f,
02210                int plane,
02211                int extension,
02212                uves_propertylist **header)
02213 {
02214     cpl_image *image = NULL;
02215     uves_propertylist *plist = NULL;
02216     const char *filename;
02217     int bitpix;
02218     cpl_type type;
02219     int naxis=0;
02220     cpl_vector * vector=NULL;
02221 
02222     
02223     assure_nomsg( f != NULL, CPL_ERROR_NULL_INPUT );
02224  
02225     assure( cpl_frame_get_type(f) == CPL_FRAME_TYPE_IMAGE,
02226         CPL_ERROR_TYPE_MISMATCH, "Wrong type: %s",
02227         uves_tostring_cpl_frame_type(cpl_frame_get_type(f)));
02228 
02229     filename = cpl_frame_get_filename(f);
02230 
02231     check( plist = uves_propertylist_load(filename, extension),
02232        "Could not load header from %s extension %d", 
02233        filename, extension);
02234     
02235     check( bitpix = uves_pfits_get_bitpix(plist),
02236        "Could not read BITPIX from %s extension %d",
02237        filename, extension);
02238     
02239     if      (bitpix == -32) type = CPL_TYPE_FLOAT;
02240     else if (bitpix == -64) type = CPL_TYPE_DOUBLE;
02241     else if (bitpix ==  32) type = CPL_TYPE_INT;
02242     else if (bitpix ==  16) type = CPL_TYPE_INT;
02243     else
02244     {
02245         assure( false, CPL_ERROR_UNSUPPORTED_MODE,
02246             "No CPL type to represent BITPIX = %d", bitpix);
02247     }
02248 
02249     check( naxis = uves_pfits_get_naxis(plist),
02250            "could not get NAXIS" );
02251 
02252     if( naxis == 1) {
02253 
02254       check( vector = cpl_vector_load(filename,extension),
02255              "Could not load vector from extension %d of file '%s' ",
02256              extension, filename);
02257       cknull(image=uves_vector_to_image(vector,type),
02258          "could not convert vector to image");
02259     } else {
02260 
02261 
02262       check( image = cpl_image_load(filename,
02263                     type,
02264                     plane,
02265                     extension),
02266          "Could not load image from extension %d of file '%s' ", 
02267          extension, filename);
02268 
02269     }
02270 
02271     if (header != NULL)
02272     {
02273         *header = uves_propertylist_duplicate(plist);
02274     }
02275 
02276   cleanup:
02277     uves_free_vector(&vector);
02278     uves_free_propertylist(&plist);
02279     return image;
02280 }
02281 /*----------------------------------------------------------------------------*/
02285 /*----------------------------------------------------------------------------*/
02286 
02287 cpl_image *uves_load_image_file(const char *filename,
02288                                 int plane,
02289                                 int extension,
02290                                 uves_propertylist **header)
02291 {
02292     cpl_image *i;
02293     cpl_frame *f = cpl_frame_new();
02294     cpl_frame_set_filename(f, filename);
02295     cpl_frame_set_type(f, CPL_FRAME_TYPE_IMAGE);
02296 
02297     i = uves_load_image(f, plane, extension, header);
02298     
02299     uves_free_frame(&f);
02300 
02301     return i;
02302 }
02303 
02304 /*----------------------------------------------------------------------------*/
02329 /*----------------------------------------------------------------------------*/
02330 void
02331 uves_save_image(const cpl_image *image, const char *filename, const uves_propertylist *plist,
02332                 bool use_bitpix16_for_int, bool save1d)
02333 {
02334     cpl_type_bpp bpp;
02335     cpl_type t;
02336     const cpl_vector *image_1d = NULL;
02337     uves_propertylist *header = NULL;
02338     cpl_image *thresholded = NULL;
02339     cpl_image *thresholded_double = NULL;
02340     
02341     if (image == NULL) {
02342         check( uves_image_save(image, filename, CPL_BPP_IEEE_FLOAT, plist, CPL_IO_DEFAULT), 
02343                "Error saving NULL image to file '%s'", filename);
02344     }
02345     else {
02346         check( t = cpl_image_get_type(image), "Error reading image type");
02347         if      (t == CPL_TYPE_FLOAT ) bpp = CPL_BPP_IEEE_FLOAT;
02348         else if (t == CPL_TYPE_DOUBLE) bpp = CPL_BPP_IEEE_FLOAT;
02349         /* Internal computations in double precision,
02350            save as single precision */
02351 #if CPL_VERSION_CODE >= CPL_VERSION(3, 0, 1)
02352         /* Some FLAMES images are BITPIX=16 (ORDEF), 
02353            some are 32 SLIT_FF_COM_REDL
02354         */
02355         else if (t == CPL_TYPE_INT   ) {
02356             if (use_bitpix16_for_int) bpp = CPL_BPP_16_UNSIGNED;
02357             else bpp = CPL_BPP_32_SIGNED;
02358         }
02359 #else
02360         else if (t == CPL_TYPE_INT   ) bpp = CPL_BPP_16_SIGNED;
02361 #endif
02362         else assure(false, CPL_ERROR_UNSUPPORTED_MODE,
02363                     "Unsupported image type '%s'", uves_tostring_cpl_type(t));
02364 
02365 
02366         thresholded = cpl_image_duplicate(image);
02367         assure_mem( thresholded );
02368 
02369         if (t == CPL_TYPE_DOUBLE)
02370             {
02371                 passure( bpp == CPL_BPP_IEEE_FLOAT, "%d", bpp);
02372 
02373                 /* Avoid infinities that would happen when casting
02374                    double -> float
02375                    by thresholding the image to +-FLT_MAX (or, better
02376                    a little less than FLT_MAX just to be sure).
02377         
02378                    (This is not a really nice solution because it solves the
02379                    problem (too large/small values) after it is introduced
02380                    (rather than avoiding it), but a general solution of the
02381                    problem would probably mean guarding every arithmetic
02382                    operation with range checks.)
02383                 */
02384         
02385                 check_nomsg( cpl_image_threshold(thresholded,
02386                                                  -FLT_MAX, FLT_MAX,
02387                                                  -FLT_MAX, FLT_MAX) );
02388 
02389                 /* Also get rid of NaN, set to zero (what else?) */
02390                 {
02391                     double *data = cpl_image_get_data_double(thresholded);
02392                     int nx = cpl_image_get_size_x(thresholded);
02393                     int ny = cpl_image_get_size_y(thresholded);
02394                     int x, y;
02395         
02396                     for (y = 0; y < ny; y++)
02397                         for (x = 0; x < nx; x++)
02398                             {
02399                                 if (irplib_isnan(data[x + y*nx]))
02400                                     {
02401                                         data[x + y*nx] = 0;
02402                                     }
02403                             }
02404                 }
02405             }
02406 
02407         if (save1d && 
02408             cpl_image_get_size_y(thresholded) == 1 &&
02409             (t == CPL_TYPE_DOUBLE ||
02410              t == CPL_TYPE_FLOAT)) {
02411             
02412             bool invert = false;
02413             if (plist != NULL)
02414                 {
02415                     header = uves_propertylist_duplicate(plist);
02416             
02417                     uves_propertylist_erase_regexp(header, "^CDELT2$", invert);
02418                     uves_propertylist_erase_regexp(header, "^CRPIX2$", invert);
02419                     uves_propertylist_erase_regexp(header, "^CRVAL2$", invert);
02420                     uves_propertylist_erase_regexp(header, "^CTYPE2$", invert);
02421                 }
02422             else
02423                 {
02424                     header = NULL;
02425                 }
02426         
02427             /* Image type must be double, before wrapping it
02428                in a vector */
02429             if (t == CPL_TYPE_FLOAT) {
02430                 thresholded_double = cpl_image_cast(thresholded, CPL_TYPE_DOUBLE);
02431             }
02432             else {
02433                 thresholded_double = cpl_image_duplicate(thresholded);
02434             }
02435         
02436             passure( cpl_image_get_type(thresholded_double) == CPL_TYPE_DOUBLE, "%d",
02437                      cpl_image_get_type(thresholded_double));
02438         
02439             image_1d = cpl_vector_wrap(
02440                 cpl_image_get_size_x(thresholded_double),
02441                 cpl_image_get_data_double(thresholded_double));
02442         
02443             check( uves_vector_save(image_1d, filename, bpp, header, CPL_IO_DEFAULT),
02444                    "Error saving vector to file '%s'", filename );
02445         }
02446         else
02447             {
02448                 check( uves_image_save(thresholded, filename, bpp, plist, CPL_IO_DEFAULT), 
02449                        "Error saving image to file '%s'", filename);
02450             }
02451     }
02452     
02453   cleanup:
02454     uves_unwrap_vector_const(&image_1d);
02455     uves_free_propertylist(&header);
02456     uves_free_image(&thresholded);
02457     uves_free_image(&thresholded_double);
02458     
02459     return;
02460 }
02461 
02462 
02463 /*----------------------------------------------------------------------------*/
02483 /*----------------------------------------------------------------------------*/
02484 void
02485 uves_save_imagelist(const cpl_imagelist *iml, const char *filename, const uves_propertylist *plist)
02486 {
02487     const cpl_image* img=NULL;
02488     cpl_type_bpp bpp;
02489     cpl_type t;
02490     const cpl_vector *image_1d = NULL;
02491     uves_propertylist *header = NULL;
02492     cpl_imagelist *thresholded = NULL;
02493 
02494     int nx = 0;
02495     int ny = 0;
02496     int nz = 0;
02497 
02498     
02499     cknull(iml,"Null input image");
02500     check(img=cpl_imagelist_get_const(iml,0),"error reading image");
02501 
02502     check_nomsg( nx = cpl_image_get_size_x(img));
02503     check_nomsg( ny = cpl_image_get_size_y(img));
02504     check_nomsg( nz = cpl_imagelist_get_size(iml));
02505 
02506     check( t = cpl_image_get_type(img), "Error reading image type");
02507     if      (t == CPL_TYPE_FLOAT ) bpp = CPL_BPP_IEEE_FLOAT;
02508     else if (t == CPL_TYPE_DOUBLE) bpp = CPL_BPP_IEEE_FLOAT;
02509     /* Internal computations in double precision,
02510        save as single precision */
02511 #if CPL_VERSION_CODE >= CPL_VERSION(3, 0, 1)
02512     else if (t == CPL_TYPE_INT   ) bpp = CPL_BPP_16_UNSIGNED;
02513 #else
02514     else if (t == CPL_TYPE_INT   ) bpp = CPL_BPP_16_SIGNED;
02515 #endif
02516     else assure(false, CPL_ERROR_UNSUPPORTED_MODE,
02517         "Unsupported image type '%s'", uves_tostring_cpl_type(t));
02518 
02519 
02520     thresholded = cpl_imagelist_duplicate(iml);
02521     assure_mem( thresholded );
02522 
02523     if (t == CPL_TYPE_DOUBLE)
02524     {
02525         passure( bpp == CPL_BPP_IEEE_FLOAT, "%d", bpp);
02526 
02527         /* Avoid infinities that would happen when casting
02528                double -> float
02529            by thresholding the image to +-FLT_MAX (or, better
02530            a little less than FLT_MAX just to be sure).
02531         
02532            (This is not a really nice solution because it solves the
02533            problem (too large/small values) after it is introduced
02534            (rather than avoiding it), but a general solution of the
02535            problem would probably mean guarding every arithmetic
02536            operation with range checks.)
02537         */
02538         
02539         check_nomsg( cpl_imagelist_threshold(thresholded,
02540                          -FLT_MAX, FLT_MAX,
02541                          -FLT_MAX, FLT_MAX) );
02542 
02543 
02544 
02545         /* Also get rid of NaN, set to zero (what else?) */
02546         {
02547         int x, y, z;
02548         double* data=NULL;
02549         cpl_image* ima=NULL;
02550         for (z = 0; z < nz; z++) {
02551           ima=cpl_imagelist_get(thresholded,z);
02552           data = cpl_image_get_data_double(ima);
02553 
02554           for (y = 0; y < ny; y++) {
02555             for (x = 0; x < nx; x++) {
02556               if (irplib_isnan(data[x + y*nx])) {
02557             data[x + y*nx] = 0;    
02558               }
02559             }
02560           }
02561         }
02562         }
02563     }
02564     if (nz == 1 && t == CPL_TYPE_DOUBLE)
02565     /* To support other types (float, int) we would
02566        need to convert to double first */
02567     {
02568         bool invert = false;
02569         if (plist != NULL)
02570         {
02571             header = uves_propertylist_duplicate(plist);
02572             
02573             uves_propertylist_erase_regexp(header, "^CDELT3$", invert);
02574             uves_propertylist_erase_regexp(header, "^CRPIX3$", invert);
02575             uves_propertylist_erase_regexp(header, "^CRVAL3$", invert);
02576             uves_propertylist_erase_regexp(header, "^CTYPE3$", invert);
02577         }
02578         else
02579         {
02580             header = NULL;
02581         }
02582         /*
02583         image_1d = cpl_vector_wrap(nx,
02584                         cpl_image_get_data_double_const(thresholded));
02585         
02586         check( uves_vector_save(image_1d, filename, bpp, header, CPL_IO_DEFAULT),
02587            "Error saving vector to file '%s'", filename );
02588         */
02589         
02590     }
02591     else
02592     {
02593         check( uves_imagelist_save(thresholded, filename, bpp, plist, CPL_IO_DEFAULT), 
02594            "Error saving image to file '%s'", filename);
02595     }
02596     
02597   cleanup:
02598     uves_unwrap_vector_const(&image_1d);
02599     uves_free_propertylist(&header);
02600     uves_free_imagelist(&thresholded);
02601 
02602     return;
02603 }
02604 
02605 /*----------------------------------------------------------------------------*/
02619 /*----------------------------------------------------------------------------*/
02620 cpl_error_code
02621 uves_save_polynomial(polynomial *p, const char *filename, const uves_propertylist *header)
02622 {
02623     cpl_table *t = NULL;
02624 
02625     check( t = uves_polynomial_convert_to_table(p), "Error converting polynomial to table");
02626     
02627     check( uves_table_save(t, 
02628               NULL,                       /* Primary header, ignored when 
02629                              mode = CPL_IO_EXTEND */
02630               header,                     /* Table header */
02631               filename,
02632               CPL_IO_EXTEND),             /* Append to existing file */
02633        "Error saving table to file '%s'", filename);
02634     
02635   cleanup:
02636     uves_free_table(&t);
02637     return cpl_error_get_code();
02638 }
02639 
02640 
02641 /*----------------------------------------------------------------------------*/
02649 /*----------------------------------------------------------------------------*/
02650 static polynomial *
02651 load_polynomial(const char* filename, int extension)
02652 {
02653     polynomial *p = NULL;  /* Result */
02654     cpl_table  *t = NULL;
02655     
02656     check(t = cpl_table_load(filename,
02657                  extension,
02658                  1),                   /* Mark identified 
02659                               invalid null values (1=yes) */
02660       "Error loading polynomial from extension %d of file '%s'", extension, filename);
02661 
02662     assure( uves_erase_invalid_table_rows(t, NULL) == 0, 
02663         CPL_ERROR_ILLEGAL_INPUT, "Table contains invalid rows");
02664     
02665     check(p = uves_polynomial_convert_from_table(t), "Error converting table to polynomial");
02666 
02667   cleanup:
02668     uves_free_table(&t);
02669     if (cpl_error_get_code() != CPL_ERROR_NONE)
02670     uves_polynomial_delete(&p);
02671     return p;
02672 }
02673 /*----------------------------------------------------------------------------*/
02688 /*----------------------------------------------------------------------------*/
02689 static const char *
02690 identify_arm(const cpl_frameset *frames, const char *blue_tag, const char *red_tag,
02691          bool *blue)
02692 {
02693     const char *tag = NULL; /* Result */
02694     
02695     const cpl_frame *frame = NULL;
02696     
02697     passure( frames != NULL, "");
02698     assure (!cpl_frameset_is_empty(frames), CPL_ERROR_ILLEGAL_INPUT, "No input frames");
02699     
02700     /* Identify blue/red arm */
02701     frame = cpl_frameset_find_const(frames, blue_tag);
02702     *blue = (frame != NULL);
02703     
02704     if (frame == NULL)
02705     {
02706         frame = cpl_frameset_find_const(frames, red_tag);
02707     }
02708     
02709     assure( frame != NULL, CPL_ERROR_ILLEGAL_INPUT, 
02710         "No valid input frames "
02711         "('%s' or '%s') in frame set",
02712         blue_tag, red_tag);
02713     
02714     assure( cpl_frameset_find_const(frames, blue_tag) == NULL ||
02715         cpl_frameset_find_const(frames, red_tag)  == NULL,
02716         CPL_ERROR_INCOMPATIBLE_INPUT,
02717         "Multiple types of input frames ('%s' and '%s') in frame set",
02718         blue_tag, red_tag);
02719     
02720     tag = cpl_frame_get_tag(frame);
02721     
02722     uves_msg("Input frames are '%s'", tag);
02723     
02724 
02725   cleanup:
02726     return tag;
02727 }
02728 
02729 /*----------------------------------------------------------------------------*/
02747 /*----------------------------------------------------------------------------*/
02748 cpl_image *
02749 uves_crop_and_rotate(const cpl_image *image, const uves_propertylist *header,
02750              enum uves_chip chip,
02751              const uves_propertylist *redl_header, 
02752              bool new_format, uves_propertylist **out_header)
02753 {
02754     cpl_image *result = NULL;
02755     int prescanx, ovrscanx;
02756     int nx, ny;
02757     int x_0, y_0, x_1, y_1; /* Extracted area (inclusive) in 
02758                    FITS convention (i.e. counting from 1) */
02759 
02760     const char *ctype1, *ctype2; /* Geometry */
02761     const char *bunit;
02762     double crval1, crval2;
02763     double crpix1, crpix2;
02764     double cdelt1, cdelt2;
02765 
02766 
02767     passure( image != NULL, " ");
02768     passure( header != NULL, " ");
02769     passure( out_header != NULL, " ");
02770     
02771     nx = cpl_image_get_size_x(image);
02772     ny = cpl_image_get_size_y(image);
02773 
02774 
02775     /* Determine pre- and overscan areas */
02776     check( prescanx = uves_pfits_get_prescanx(header, chip), "Could not read x-prescan info" );
02777     check( ovrscanx = uves_pfits_get_ovrscanx(header, chip), "Could not read x-overscan info");
02778   
02779     /* Don't try to read the y pre- and overscan regions, which should be zero for UVES.
02780        The keywords are not present in older UVES data. */
02781 
02782     /* Read geometry */
02783     check( ctype1 = uves_pfits_get_ctype1(header), "Error reading keyword");
02784     check( ctype2 = uves_pfits_get_ctype2(header), "Error reading keyword");
02785     check( crval1 = uves_pfits_get_crval1(header), "Error reading keyword");
02786     check( crval2 = uves_pfits_get_crval2(header), "Error reading keyword");
02787     check( crpix1 = uves_pfits_get_crpix1(header), "Error reading keyword");
02788     check( crpix2 = uves_pfits_get_crpix2(header), "Error reading keyword");
02789     check( cdelt1 = uves_pfits_get_cdelt1(header), "Error reading keyword");
02790     check( cdelt2 = uves_pfits_get_cdelt2(header), "Error reading keyword");
02791     if (uves_propertylist_contains(header, UVES_BUNIT))
02792     {
02793         bunit = uves_pfits_get_bunit(header);
02794     }
02795     else
02796     {
02797         bunit = " ";
02798     }
02799     
02800 
02801     /* Crop the image */
02802     {
02803     y_0 = 1;
02804     y_1 = ny;
02805     if (new_format || chip == UVES_CHIP_BLUE)
02806         {
02807         x_0 = prescanx + 1;
02808         x_1 = nx - ovrscanx;
02809         }
02810     else /* red, old format */
02811         {
02812         if (chip == UVES_CHIP_REDU)
02813             {
02814             x_0 = prescanx + 1;
02815             x_1 = nx/2 - ovrscanx;
02816             }
02817         else
02818             { /* lower */
02819             x_0 = nx/2 + prescanx + 1;
02820             x_1 = nx - ovrscanx;
02821             }
02822         }
02823     check( result = cpl_image_extract(image, x_0, y_0, x_1, y_1), "Could not crop image");
02824     crpix1 = crpix1 - (x_0 - 1);
02825     crpix2 = crpix2 - (y_0 - 1);
02826     nx = (x_1 - x_0) + 1;
02827     ny = (y_1 - y_0) + 1;
02828     }
02829 
02830     UVES_TIME_START("Rotation");
02831     /* ... is a bit slow, and there's probably nothing to
02832        do about as it involves moving data between remote
02833        places in memory.
02834     */
02835 
02836     /* Rotate the image into standard orientation */
02837     {
02838     int crpix1_old = crpix1;
02839     int crpix2_old = crpix2;
02840     int crval1_old = crval1;
02841     int crval2_old = crval2;
02842     int cdelt1_old = cdelt1;
02843     int cdelt2_old = cdelt2;
02844     const char *ctype1_old = ctype1;
02845     const char *ctype2_old = ctype2;
02846 
02847     if (chip == UVES_CHIP_BLUE)
02848         {
02849         /* 90 deg counterclockwise rotation */
02850         check( cpl_image_turn(result, -1), "Could not turn image");
02851         
02852         crpix1 = ny - (crpix2_old - 1); /* Note: old value of ny */
02853         crpix2 = crpix1_old;
02854         crval1 = crval2_old;
02855         crval2 = crval1_old;
02856         }
02857     else 
02858         {
02859         /* Red */
02860         /* Flip image around y=-x */
02861         check( cpl_image_flip(result, 3), "Could not flip image");
02862 
02863         crpix1 = ny - (crpix2_old - 1); /* Note: old value of nx, ny */
02864         crpix2 = nx - (crpix1_old - 1);
02865         crval1 = crval2_old;
02866         crval2 = crval1_old;
02867         }
02868 
02869 
02870     /* Always swap these ones */
02871     ctype1 = ctype2_old;
02872     ctype2 = ctype1_old;
02873     cdelt1 = cdelt2_old;
02874     cdelt2 = cdelt1_old;
02875     }
02876 
02877     UVES_TIME_END;
02878 
02879     /* Here we should use the CROTAi keywords to 
02880        properly describe the new rotation */
02881     
02882     /* Instead, redefine CRVAL as in the following, on request from DFO */
02883 
02884     crpix1 = 1;
02885     crpix2 = 1;
02886     if (chip == UVES_CHIP_BLUE || chip == UVES_CHIP_REDL)
02887     {
02888         crval1 = 1;
02889         crval2 = 1;
02890     }
02891     else 
02892     {
02893             int physical_gap_between_chips = 64; /* Pixels. Unbinned. Hardcoded. */
02894 
02895 
02896         passure( chip == UVES_CHIP_REDU , "%d", chip );
02897         
02898         crval1 = 1;
02899         
02900         /* Set CRVAL2 = REDL_height - REDL_overscan - REDL_prescan + gap. */
02901         if (new_format)
02902         {
02903 
02904             check( crval2 = 1 +
02905                (uves_pfits_get_naxis1(redl_header) -
02906                 uves_pfits_get_ovrscanx(redl_header, UVES_CHIP_REDL) -
02907                 uves_pfits_get_prescanx(redl_header, UVES_CHIP_REDL)) *
02908                uves_pfits_get_cdelt1(redl_header) +
02909                            physical_gap_between_chips,
02910                "Error reading REDL chip geometry");
02911 
02912             uves_msg_debug("Setting CRVAL2 = 1 + (%d - %d - %d) * %f + %d = %f",
02913                    uves_pfits_get_naxis1(redl_header),
02914                    uves_pfits_get_ovrscanx(redl_header, UVES_CHIP_REDL),
02915                    uves_pfits_get_prescanx(redl_header, UVES_CHIP_REDL),
02916                    uves_pfits_get_cdelt1(redl_header),
02917                                    physical_gap_between_chips, crval2);
02918         }
02919         else
02920         {
02921 
02922             /* old format */
02923             check( crval2 = 1 +
02924                (uves_pfits_get_naxis1(header)/2 -
02925                 uves_pfits_get_ovrscanx(redl_header, UVES_CHIP_REDL) -
02926                 uves_pfits_get_prescanx(redl_header, UVES_CHIP_REDL)) *
02927                uves_pfits_get_cdelt1(redl_header) +
02928                            physical_gap_between_chips,
02929                "Error reading REDL chip geometry");
02930 
02931             uves_msg_debug("Setting CRVAL2 = 1 + (%d - %d - %d) * %f + %d = %f",
02932                    uves_pfits_get_naxis1(header)/2, 
02933                    uves_pfits_get_ovrscanx(redl_header, UVES_CHIP_REDL),
02934                    uves_pfits_get_prescanx(redl_header, UVES_CHIP_REDL),
02935                    uves_pfits_get_cdelt1(redl_header),
02936                                    physical_gap_between_chips, crval2);
02937         }
02938 
02939     }
02940 
02941 
02942     /* Update header with new geometry */
02943     check( *out_header = uves_initialize_image_header(ctype1, ctype2, bunit,
02944                               crval1, crval2,
02945                               crpix1, crpix2,
02946                               cdelt1, cdelt2),
02947        "Error initializing header");
02948 
02949     //check(uves_propertylist_copy_property_regexp(*out_header, header,
02950     //                      "^ESO ", 0),
02951     //   "Error copying hieararch keys");
02952 
02953 
02954     uves_msg("Raw image cropped and rotated from %" CPL_SIZE_FORMAT "x%" CPL_SIZE_FORMAT " to %" CPL_SIZE_FORMAT "x%" CPL_SIZE_FORMAT "",
02955          nx, ny,
02956          cpl_image_get_size_x(result),
02957          cpl_image_get_size_y(result));     
02958 
02959   cleanup:
02960     if (cpl_error_get_code() != CPL_ERROR_NONE)
02961     {
02962         uves_free_image(&result);
02963         if (out_header != NULL)
02964         {
02965             uves_free_propertylist(out_header);
02966         }
02967     }
02968 
02969     return result;
02970 }
02971 
02972 /*----------------------------------------------------------------------------*/
02986 /*----------------------------------------------------------------------------*/
02987 void
02988 uves_warn_if_chip_names_dont_match(const uves_propertylist *calib_header, 
02989                   const char *raw_chip_name, enum uves_chip chip)
02990 {
02991     const char *calib_chip_name;
02992     bool mismatch = false;
02993 
02994     check( calib_chip_name = uves_pfits_get_chipid(calib_header, chip),
02995        "Could not read chip name of calibration data");
02996 
02997 
02998     /* Ignore leading/trailing blanks when comparing name strings.
02999      * (The following is O(n^2) where n is the string length, 
03000      * but that's ok because the strings stored in a FITS card are short).
03001      */
03002     {
03003     unsigned int calib_first, calib_last;  /* inclusive */
03004     unsigned int raw_first, raw_last;
03005     
03006     calib_first = 0;
03007     raw_first = 0;
03008     while (calib_chip_name[calib_first] == ' ' && calib_first < strlen(calib_chip_name) - 1)
03009         {
03010         calib_first++;
03011         }
03012     while (raw_chip_name[raw_first] == ' ' && raw_first < strlen(raw_chip_name) - 1)
03013         {
03014         raw_first++;
03015         }
03016 
03017     calib_last = strlen(calib_chip_name) - 1;
03018     raw_last = strlen(raw_chip_name) - 1;
03019     while (calib_chip_name[calib_last] == ' ' && calib_last > 0)
03020         {
03021         calib_last--;
03022         }
03023     while (raw_chip_name[raw_last] == ' ' && raw_last > 0)
03024         {
03025         raw_last--;
03026         }
03027 
03028     /* Compare substrings */
03029     if (calib_last - calib_first != raw_last - raw_first)
03030         {
03031         mismatch = true;
03032         }
03033     else
03034         {
03035         unsigned int i;
03036         
03037         for (i = 0; i <= (calib_last - calib_first); i++)
03038             {
03039             if (raw_chip_name[raw_first + i] != 
03040                 calib_chip_name[calib_first + i])
03041                 {
03042                 mismatch = true;
03043                 }
03044             }
03045         }
03046     }
03047 
03048 
03049     if (mismatch)
03050     {
03051         uves_msg_warning("Calibration frame chip ID '%s' does "
03052                  "not match raw frame chip ID '%s'",
03053                  calib_chip_name, raw_chip_name);
03054     }
03055 
03056   cleanup:
03057     return;
03058 }
03059 
03060 
03061 /*----------------------------------------------------------------------------*/
03083 /*----------------------------------------------------------------------------*/
03084 
03085 static cpl_error_code
03086 load_raw_image(const char *filename, 
03087                cpl_type type,
03088                bool flames,
03089                bool blue,
03090                cpl_image *raw_image[2],
03091                uves_propertylist *raw_header[2], 
03092                uves_propertylist *rotated_header[2])
03093 {
03094 
03095  
03096     cpl_image *image = NULL;
03097     uves_propertylist *primary_header = NULL;
03098     uves_propertylist *ext_header = NULL;
03099     int extension, nextensions;
03100     bool new_format;
03101     int plane = 0;   /* Only one plane in FLAMES/UVES raw files */
03102 
03103     cpl_image* image1=NULL;
03104     cpl_image* image2=NULL;
03105     int sx=0;
03106     int sy=0;
03107 
03108 
03109     /* Initialize parameters */
03110     raw_image[0] = NULL;
03111     raw_image[1] = NULL;
03112     raw_header[0] = NULL;
03113     raw_header[1] = NULL;
03114     rotated_header[0] = NULL;
03115     rotated_header[1] = NULL;
03116 
03117     check( nextensions = uves_get_nextensions(filename),
03118        "Error reading number of extensions of file '%s'", filename);
03119 
03120     /* Find out if new/old format */
03121     extension = 0;
03122     check( primary_header = uves_propertylist_load(filename,
03123                           extension),
03124        "Could not load header from extension %d of file '%s'", 
03125        extension, filename);
03126 
03127     check( new_format = uves_format_is_new(primary_header),
03128        "Error determining new/old format of file %s", filename);
03129  
03130     uves_msg_low("Raw frame is %s, %s format, file '%s' has %d extensions", 
03131          (blue) ? "blue" : "red", (new_format) ? "new" : "old", 
03132          filename, nextensions);
03133 
03134     /* If the raw frame is blue, or if it's an old format red frame */
03135     if (blue || !new_format)
03136     {
03137         enum uves_chip chip;
03138         
03139         uves_msg_debug("Frame is blue or old format");
03140 
03141         assure( nextensions == 0 || 
03142                 (blue   && nextensions == 2) ||
03143                 (flames && nextensions == 2),
03144                 CPL_ERROR_ILLEGAL_INPUT,
03145                 "Unrecognized format of file '%s'. %d extensions expected. %d found.",
03146                 filename,
03147                 ((flames||blue) && (nextensions ==2)) ? 2 : 0, nextensions);
03148 
03149         /* FLAMES: the 2 extensions contain OzPoz table and FLAMES FIBRE table */
03150 
03151        /* Load the header */
03152         check( raw_header[0] = uves_propertylist_load(filename,
03153                              extension),
03154            "Could not load header from extension %d of file '%s'", 
03155            extension, filename);
03156 
03157 
03158         extension = 0;
03159         if(blue && nextensions == 2) {
03160            extension = 1;
03161            check( raw_header[1] = uves_propertylist_load(filename,
03162                                                          extension),
03163                   "Could not load header from extension %d of file '%s'",
03164                   extension, filename);
03165            check( uves_propertylist_append(raw_header[0],raw_header[1]),
03166                   "Could not collate header from extension 1 to 0 of file '%s'",filename);
03167            uves_free_propertylist(&raw_header[1]);
03168  
03169            check( image1 = cpl_image_load(filename,
03170                                           type,
03171                                           plane,   
03172                                           extension
03173                      ), "Could not load image from extension %d of file '%s' ", 
03174                   extension, filename);
03175            cpl_image_save(image1, "ima1.fits", CPL_BPP_IEEE_FLOAT,
03176                           NULL,CPL_IO_DEFAULT);
03177 
03178            extension = 2;
03179            check( image2 = cpl_image_load(filename,
03180                                           type,
03181                                           plane,   
03182                                           extension
03183                      ), "Could not load image from extension %d of file '%s' ", 
03184                   extension, filename);
03185            check_nomsg(sx=cpl_image_get_size_x(image1));
03186            check_nomsg(sy=cpl_image_get_size_y(image1));
03187 
03188            check_nomsg(image=cpl_image_new(2*sx,sy,type));
03189            check_nomsg(cpl_image_copy(image,image1,1,1));
03190            check_nomsg(cpl_image_copy(image,image2,1+sx,1));
03191 
03192            
03193            uves_free_image(&image1);
03194            uves_free_image(&image2);
03195 
03196            extension = 1;
03197 
03198 
03199 
03200         } else {
03201 
03202 
03203         check( image = cpl_image_load(filename,
03204                       type,
03205                       plane,   
03206                       extension
03207                ), "Could not load image from extension %d of file '%s' ", 
03208            extension, filename);
03209         }
03210  
03211         /* Get blue (or lower red) chip */
03212         chip = (blue) ? UVES_CHIP_BLUE : UVES_CHIP_REDL;
03213         check( raw_image[0] = uves_crop_and_rotate(image, raw_header[0], 
03214                                chip, raw_header[0],
03215                                new_format, 
03216                                &rotated_header[0]),
03217            "Error splitting image");
03218         
03219         if (!blue)
03220         {
03221             const uves_propertylist *redl_header;
03222 
03223             /* Upper red chip, use again the primary header */
03224             check( raw_header[1] = uves_propertylist_duplicate(raw_header[0]),
03225                "Error duplicating FITS header");
03226             
03227             /* Get upper red chip */
03228             chip = UVES_CHIP_REDU;
03229             redl_header = raw_header[0];
03230             check( raw_image[1] = uves_crop_and_rotate(image, raw_header[1],
03231                                    chip, redl_header,
03232                                    new_format,
03233                                    &rotated_header[1]),
03234                "Error splitting red image");
03235         }
03236         else
03237         {
03238             raw_image[1] = NULL;
03239             raw_header[1] = NULL;
03240             rotated_header[1] = NULL;
03241         }
03242     }
03243     else
03244     /* New red format. UVES must have 2 extensions,
03245      * FLAMES must have 2 or more extensions
03246      */
03247     {
03248         uves_msg_debug("Frame is red, new format");
03249         
03250         assure( nextensions >= 2, CPL_ERROR_UNSUPPORTED_MODE,
03251             "File '%s' (red frame) has %d extensions. 2+ extensions expected "
03252                     "for new format",
03253             filename, nextensions);
03254         
03255         uves_msg_debug("New red format, %s frame",
03256                (nextensions > 2) ? "FLAMES" : "FLAMES/UVES");
03257         
03258 
03259         /* Images always in extension 1 and 2. First load just the headers */
03260         for (extension = 1; extension <= 2; extension++)
03261         {
03262             /* In the FITS file, REDU is stored
03263                in extension 1, and REDL is stored in
03264                extension 2 */
03265             enum uves_chip chip = (extension == 1) ? UVES_CHIP_REDU : UVES_CHIP_REDL;
03266             int indx = uves_chip_get_index(chip);
03267 
03268             /* Load the extension header */
03269             uves_free_propertylist(&ext_header);
03270             check( ext_header = uves_propertylist_load(filename,
03271                                   extension),
03272                "Could not load header from extension %d of file '%s'", 
03273                extension, filename);
03274             
03275             /* Merge with primary header */
03276             check( raw_header[indx] = uves_propertylist_duplicate(primary_header),
03277                "Error cloning primary header");
03278             
03279             if (!uves_propertylist_is_empty(ext_header))
03280             {
03281                 check( uves_propertylist_copy_property_regexp(raw_header[indx],
03282                                      ext_header, ".*", 0),
03283                    "Error merging primary header with extension %d header", 
03284                    extension);
03285             }
03286         }
03287 
03288 
03289         /* Remove pre-, overscan areas (we needed to load both image headers for this) */
03290         for (extension = 1; extension <= 2; extension++)
03291         {
03292             enum uves_chip chip = (extension == 1) ? UVES_CHIP_REDU : UVES_CHIP_REDL;
03293             int indx      = uves_chip_get_index(chip);
03294             int indx_redl = uves_chip_get_index(UVES_CHIP_REDL);
03295             
03296             const uves_propertylist *redl_header = raw_header[indx_redl];
03297             
03298             uves_free_image(&image);
03299             check( image = cpl_image_load(filename,
03300                           type,
03301                           plane,               
03302                           extension),
03303                "Could not load image from extension %d of file '%s' ", 
03304                extension, filename);
03305             
03306             check( raw_image[indx] = uves_crop_and_rotate(image, 
03307                                   raw_header[indx],
03308                                   chip, redl_header,
03309                                   new_format,
03310                                   &rotated_header[indx]),
03311                "Error splitting red image");
03312         }
03313 
03314         
03315     }/* if new format */
03316  
03317 
03318   cleanup:
03319     uves_free_image(&image);
03320     uves_free_image(&image1);
03321     uves_free_image(&image2);
03322 
03323     uves_free_propertylist(&primary_header);
03324     uves_free_propertylist(&ext_header);
03325 
03326     if (cpl_error_get_code() != CPL_ERROR_NONE)
03327     {
03328         uves_free_image       (&raw_image[0]);
03329         uves_free_image       (&raw_image[1]);
03330         uves_free_propertylist(&raw_header[0]);
03331         uves_free_propertylist(&raw_header[1]);
03332         uves_free_propertylist(&rotated_header[0]);
03333         uves_free_propertylist(&rotated_header[1]);
03334     }
03335     
03336     return cpl_error_get_code();
03337 }
03338 
03339 
03340 /*----------------------------------------------------------------------------*/
03368 /*----------------------------------------------------------------------------*/
03369 cpl_error_code
03370 uves_load_raw_imagelist(const cpl_frameset *frames,
03371             bool flames,
03372             const char *blue_tag, const char *red_tag, cpl_type type, 
03373             cpl_imagelist *images[2],
03374             uves_propertylist **raw_headers[2], uves_propertylist *rotated_header[2],
03375             bool *blue)
03376 {
03377     const char *tag           = NULL;
03378     const cpl_frame *frame    = NULL;
03379     cpl_image *temp_image[2]  = {NULL, NULL};
03380     uves_propertylist *temp_header[2] = {NULL, NULL};
03381     int number_of_frames = 0;
03382     int frameset_size = 0;   /* Keeps track of number of raw_header pointers allocated */
03383     int nchips;
03384     int chip;
03385     
03386     raw_headers[0] = NULL;
03387     raw_headers[1] = NULL;
03388 
03389     check( frameset_size = cpl_frameset_get_size(frames),
03390        "Error reading frameset size");
03391 
03392     check( tag = identify_arm(frames, blue_tag, red_tag, blue),
03393        "Could not identify chip type");
03394     
03395     nchips = (*blue) ? 1 : 2;
03396     for(chip = 0; chip < nchips; chip++)
03397     {
03398         images[chip] = NULL;
03399         rotated_header[chip] = NULL;
03400         
03401         images[chip] = cpl_imagelist_new();
03402         raw_headers[chip] = cpl_calloc(frameset_size, sizeof(uves_propertylist *));
03403     }
03404 
03405     /* Load all input images with correct tag,
03406        split,
03407        insert into image list(s) */  
03408 
03409     number_of_frames = 0;
03410     for(frame = cpl_frameset_get_first_const(frames);
03411     frame != NULL;
03412     frame = cpl_frameset_get_next_const(frames))
03413     {
03414         /* If match */
03415         if ( strcmp(cpl_frame_get_tag(frame), tag) == 0)
03416         {
03417             const char *filename = cpl_frame_get_filename(frame);
03418             
03419             /* Load image + header */
03420             uves_free_propertylist(&rotated_header[0]);
03421             uves_free_propertylist(&rotated_header[1]);
03422             
03423             check( load_raw_image(filename,
03424                       type,
03425                       flames,
03426                       *blue,
03427                       temp_image,
03428                       temp_header,
03429                       rotated_header),
03430                "Could not load image from file '%s'", filename);
03431             
03432             /* Append to image lists */
03433             for(chip = 0; chip < nchips; chip++)
03434             {
03435                 raw_headers[chip][number_of_frames] = temp_header[chip];
03436                 temp_header[chip] = NULL;
03437                 
03438                 check( cpl_imagelist_set(images[chip],
03439                              temp_image[chip],
03440                              /* Position */
03441                              cpl_imagelist_get_size(images[chip])
03442                        ),
03443                    "Could not insert image into image list");
03444                 
03445                 /* Don't deallocate image or header */
03446                 temp_image[chip] = NULL;
03447             }
03448             
03449             number_of_frames += 1;
03450         }
03451     }
03452 
03453     /* Check that image sizes are identical */
03454     
03455     for(chip = 0; chip < nchips; chip++)
03456     {
03457         /* This function returns zero iff the list is uniform */
03458         assure (cpl_imagelist_is_uniform(images[chip]) == 0,
03459             CPL_ERROR_INCOMPATIBLE_INPUT, 
03460             "Input images are not of same size and type");
03461         
03462         passure( cpl_imagelist_get_size(images[chip]) == number_of_frames, 
03463              "%" CPL_SIZE_FORMAT " %" CPL_SIZE_FORMAT"", cpl_imagelist_get_size(images[0]), number_of_frames);
03464 
03465     }
03466 
03467     
03468     /* Check central wavelengths (not bias/dark) */
03469     if ( strcmp(UVES_BIAS (*blue), tag) != 0 &&
03470      strcmp(UVES_DARK (*blue), tag) != 0 &&
03471      strcmp(UVES_PDARK(*blue), tag) != 0) {
03472     enum uves_chip chip_id;
03473     int i;
03474     double wlen = 0;
03475     
03476     for (chip_id = uves_chip_get_first(*blue); 
03477          chip_id != UVES_CHIP_INVALID;
03478          chip_id = uves_chip_get_next(chip_id)) {
03479         for (i = 0; i < number_of_frames; i++) {
03480         if (i == 0) {
03481             check( wlen = uves_pfits_get_gratwlen(
03482                    raw_headers[uves_chip_get_index(chip_id)][i], chip_id),
03483                "Error reading central wavelength of input frame number %d", i+1);
03484         }
03485         else {
03486             double w;
03487             
03488             check( w = uves_pfits_get_gratwlen(
03489                    raw_headers[uves_chip_get_index(chip_id)][i], chip_id),
03490                "Error reading central wavelength of input frame number %d", i+1);
03491             
03492             assure( fabs((w-wlen)/wlen) < 0.01, CPL_ERROR_INCOMPATIBLE_INPUT,
03493                 "Mis-matching input frame central wavelengths: "
03494                 "%e (frame 1) != %e (frame %d)", wlen, w, i+1);
03495         }
03496         }
03497     }
03498     }
03499     
03500   cleanup:
03501     uves_free_image(&temp_image[0]);
03502     uves_free_image(&temp_image[1]);
03503     uves_free_propertylist(&temp_header[0]);
03504     uves_free_propertylist(&temp_header[1]);
03505     
03506     if (cpl_error_get_code() != CPL_ERROR_NONE) {
03507     if (raw_headers[0] != NULL) {
03508         int i;
03509         for (i = 0; i < frameset_size; i++)    {
03510         if (raw_headers[0] != NULL) uves_free_propertylist(&raw_headers[0][i]);
03511         if (raw_headers[1] != NULL) uves_free_propertylist(&raw_headers[1][i]);
03512         }
03513     }
03514     cpl_free(raw_headers[0]); raw_headers[0] = NULL;
03515     cpl_free(raw_headers[1]); raw_headers[1] = NULL;
03516     
03517     uves_free_imagelist(&images[0]);
03518     uves_free_imagelist(&images[1]);
03519     
03520     uves_free_propertylist(&rotated_header[0]);
03521     uves_free_propertylist(&rotated_header[1]);
03522     }
03523 
03524     return cpl_error_get_code();
03525 }
03526 
03527 
03528 /*----------------------------------------------------------------------------*/
03545 /*----------------------------------------------------------------------------*/
03546 cpl_error_code
03547 uves_load_orderpos(const cpl_frameset *frames,
03548            bool flames,
03549            const char **raw_filename,
03550            cpl_image *raw_image[2],
03551            uves_propertylist *raw_header[2], 
03552            uves_propertylist *rotated_header[2], bool *blue)
03553 {
03554     const char *tags[4];
03555 
03556     int number_of_tags = sizeof(tags) / sizeof(char *);
03557     int indx;
03558 
03559     /* Warning: Duplicate logic. The number of tags must match the size of the
03560        tags array defined above */
03561     tags[0] = UVES_ORDER_FLAT(flames, false); /* red */
03562     tags[1] = UVES_ORDER_FLAT(flames, true);  /* blue */
03563     tags[2] = UVES_STD_STAR(false);
03564     tags[3] = UVES_STD_STAR(true);
03565 
03566     if (flames)
03567     {
03568         *blue = false;
03569         number_of_tags = 1;
03570 
03571         check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx,
03572                            NULL),
03573            "Could not find raw frame (%s) in SOF", 
03574            tags[0]);
03575         
03576     }
03577     else
03578     {    
03579         check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx,
03580                            NULL),
03581            "Could not find raw frame (%s, %s, %s, or %s) in SOF", 
03582            tags[0], tags[1], tags[2], tags[3]);
03583         
03584         *blue = (indx == 1) || (indx == 3);
03585     }
03586 
03587     /* Load the image */
03588     check( load_raw_image(*raw_filename,
03589               CPL_TYPE_DOUBLE,
03590               flames,
03591               *blue,
03592               raw_image,
03593               raw_header,
03594               rotated_header),
03595        "Error loading image from file '%s'", *raw_filename);
03596     
03597     passure( !flames || !(*blue), "%d %d",
03598          flames, *blue );
03599 
03600   cleanup:
03601     if (cpl_error_get_code() != CPL_ERROR_NONE)
03602     {
03603         *raw_filename = NULL;
03604     }
03605     
03606     return cpl_error_get_code();
03607 }
03608 
03609 /*----------------------------------------------------------------------------*/
03625 /*----------------------------------------------------------------------------*/
03626 cpl_error_code
03627 uves_load_formatcheck(const cpl_frameset *frames,
03628               bool flames,
03629               const char **raw_filename,
03630               cpl_image *raw_image[2],
03631               uves_propertylist *raw_header[2], 
03632               uves_propertylist *rotated_header[2], bool *blue)
03633 {
03634     const char *tags[2];
03635     int number_of_tags = sizeof(tags) / sizeof(char *);
03636     int indx;
03637 
03638     tags[0] = UVES_FORMATCHECK(flames, false);   /* red */
03639     tags[1] = UVES_FORMATCHECK(flames, true);    /* blue */
03640     if (flames)
03641     {
03642         *blue = false;
03643         number_of_tags = 1;
03644 
03645         check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
03646            "Could not find raw frame (%s) in SOF",
03647            tags[0]);
03648     }
03649     else
03650     {
03651         check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
03652            "Could not find raw frame (%s or %s) in SOF", 
03653            tags[0], tags[1]);
03654         
03655         *blue = (indx == 1);
03656     }
03657 
03658     /* Load the image */
03659     check( load_raw_image(*raw_filename,
03660               CPL_TYPE_DOUBLE,
03661               flames,
03662               *blue,
03663               raw_image,
03664               raw_header,
03665               rotated_header),
03666        "Error loading image from file '%s'", *raw_filename);
03667    
03668   cleanup:
03669     if (cpl_error_get_code() != CPL_ERROR_NONE) 
03670     {
03671         *raw_filename = NULL;
03672     }
03673     return cpl_error_get_code();
03674 }
03675 
03676 /*----------------------------------------------------------------------------*/
03695 /*----------------------------------------------------------------------------*/
03696 void uves_load_cd_align(const cpl_frameset *frames,
03697             const char **raw_filename1,
03698             const char **raw_filename2,
03699             cpl_image *raw_image1[2],
03700             cpl_image *raw_image2[2],
03701             uves_propertylist *raw_header1[2], 
03702             uves_propertylist *raw_header2[2], 
03703             uves_propertylist *rotated_header1[2], 
03704             uves_propertylist *rotated_header2[2], 
03705             bool *blue)
03706 {
03707     const char *tags[2];
03708     int number_of_tags = sizeof(tags) / sizeof(char *);
03709     int indx;
03710     bool flames = false;
03711     const cpl_frame *frame;
03712 
03713     tags[0] = UVES_CD_ALIGN(false);   /* red */
03714     tags[1] = UVES_CD_ALIGN(true);    /* blue */
03715 
03716     check( *raw_filename1 = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
03717        "Could not find raw frame (%s or %s) in SOF", 
03718        tags[0], tags[1]);
03719     
03720     *blue = (indx == 1);
03721 
03722     assure( cpl_frameset_count_tags(frames, tags[indx]) == 2,
03723         CPL_ERROR_ILLEGAL_INPUT,
03724         "%d %s frames found. Exactly 2 required",
03725         cpl_frameset_count_tags(frames, tags[indx]), tags[indx] );
03726 
03727     /* Load the two frames */
03728     {
03729     int n = 1;
03730     for (frame = cpl_frameset_get_first_const(frames);
03731          frame != NULL;
03732          frame = cpl_frameset_get_next_const(frames))
03733         {
03734         if (strcmp(cpl_frame_get_tag(frame), tags[indx]) == 0)
03735             {
03736             if (n == 1)
03737                 {
03738                 *raw_filename1 = cpl_frame_get_filename(frame);
03739                 }
03740             else
03741                 {
03742                 *raw_filename2 = cpl_frame_get_filename(frame);
03743                 }
03744             
03745             check( load_raw_image(n == 1 ? 
03746                           *raw_filename1 :
03747                           *raw_filename2,
03748                           CPL_TYPE_DOUBLE,
03749                           flames,
03750                           *blue,
03751                           n == 1 ?
03752                           raw_image1 :
03753                           raw_image2,
03754                           n == 1 ?
03755                           raw_header1 :
03756                           raw_header2,
03757                           n == 1 ?
03758                           rotated_header1 :
03759                           rotated_header2),
03760                    "Error loading image from file '%s'",
03761                    n == 1 ? *raw_filename1 : *raw_filename2);
03762 
03763             n++;
03764             }
03765         }
03766     }
03767     
03768   cleanup:
03769     if (cpl_error_get_code() != CPL_ERROR_NONE) 
03770     {
03771         *raw_filename1 = NULL;
03772         *raw_filename2 = NULL;
03773     }
03774     
03775     return;
03776 }
03777 
03778 
03779 /*----------------------------------------------------------------------------*/
03800 /*----------------------------------------------------------------------------*/
03801 void
03802 uves_load_arclamp(const cpl_frameset *frames,
03803           bool flames,
03804           const char **raw_filename, 
03805           cpl_image *raw_image[2], uves_propertylist *raw_header[2],
03806           uves_propertylist *rotated_header[2], bool *blue,
03807           bool *sim_cal)
03808 {
03809     const char *tags[4];
03810 
03811     int number_of_tags = sizeof(tags) / sizeof(char *);
03812     int indx;
03813 
03814     /* Warning: duplicate logic. Array size above must match */
03815     if (flames)
03816     {
03817         assure_nomsg( sim_cal != NULL, CPL_ERROR_NULL_INPUT );
03818 
03819         tags[0] = UVES_ARC_LAMP(flames, true);  /* blue flag not used */
03820         tags[1] = FLAMES_FIB_SCI_SIM;
03821 
03822         number_of_tags = 2;
03823         *blue = false;
03824 
03825         check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
03826            "Could not find raw frame (%s or %s) in SOF", 
03827            tags[0], tags[1]);
03828         
03829         *sim_cal = (indx == 1);
03830     }
03831     else
03832     {
03833         tags[0] = UVES_ARC_LAMP(flames, true);
03834         tags[1] = UVES_ARC_LAMP(flames, false);
03835         tags[2] = UVES_ECH_ARC_LAMP(true);
03836         tags[3] = UVES_ECH_ARC_LAMP(false);
03837 
03838         check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
03839            "Could not find raw frame (%s, %s, %s or %s) in SOF", 
03840            tags[0], tags[1], tags[2], tags[3]);
03841         
03842         *blue = (indx == 0 || indx == 2);
03843     }
03844     
03845     /* Load the image */
03846     check( load_raw_image(*raw_filename,
03847               CPL_TYPE_DOUBLE,
03848               flames,
03849               *blue,
03850               raw_image,
03851               raw_header,
03852               rotated_header),
03853        "Error loading image from file '%s'", *raw_filename);
03854 
03855   cleanup:
03856     if (cpl_error_get_code() != CPL_ERROR_NONE) {
03857     *raw_filename = NULL;
03858     uves_free_image       (raw_image);
03859     uves_free_propertylist(raw_header);
03860     }
03861     return;
03862 }
03863 
03864 /*----------------------------------------------------------------------------*/
03879 /*----------------------------------------------------------------------------*/
03880 cpl_error_code
03881 uves_load_science(const cpl_frameset *frames, const char **raw_filename, 
03882           cpl_image *raw_image[2], 
03883           uves_propertylist *raw_header[2], 
03884           uves_propertylist *rotated_header[2], 
03885           bool *blue,
03886           const char **sci_type)
03887 {
03888     /* Note: the two following arrays must match */
03889     const char *tags[] = 
03890     { 
03891         UVES_SCIENCE(true), UVES_SCIENCE(false),
03892         UVES_SCI_EXTND(true), UVES_SCI_EXTND(false),
03893         UVES_SCI_POINT(true), UVES_SCI_POINT(false),
03894         UVES_SCI_SLICER(true), UVES_SCI_SLICER(false),
03895         UVES_TFLAT(true), UVES_TFLAT(false) 
03896     };
03897 
03898     const char *type[] = 
03899     {
03900         "SCIENCE", "SCIENCE",
03901         "SCI_EXTND", "SCI_EXTND",
03902         "SCI_POINT", "SCI_POINT",
03903         "SCI_SLICER", "SCI_SLICER",
03904         "TFLAT", "TFLAT",
03905     };
03906 
03907     int number_of_tags = sizeof(tags) / sizeof(char *);
03908     int indx;
03909     bool flames = false;
03910 
03911     check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
03912        "No science frame (%s, %s, %s, %s, %s, %s, %s, %s, %s or %s) in SOF", 
03913        tags[0], tags[1], tags[2], tags[3], 
03914        tags[4], tags[5], tags[6], tags[7], tags[7], tags[8]);
03915 
03916     *blue = (indx % 2 == 0);
03917     *sci_type = type[indx];
03918     
03919     /* Load the image */
03920     check( load_raw_image(*raw_filename,
03921               CPL_TYPE_DOUBLE,
03922               flames,
03923               *blue,
03924               raw_image,
03925               raw_header,
03926               rotated_header),
03927        "Error loading image from file '%s'", *raw_filename);
03928   cleanup:
03929     if (cpl_error_get_code() != CPL_ERROR_NONE)
03930     {
03931         *raw_filename = NULL;
03932         uves_free_image       (raw_image);
03933         uves_free_propertylist(raw_header);
03934     }
03935     return cpl_error_get_code();
03936 }
03937 
03938 /*----------------------------------------------------------------------------*/
03955 /*----------------------------------------------------------------------------*/
03956 cpl_error_code
03957 uves_load_standard(const cpl_frameset *frames, const char **raw_filename, 
03958            cpl_image *raw_image[2],
03959            uves_propertylist *raw_header[2], 
03960            uves_propertylist *rotated_header[2], bool *blue)
03961 {
03962     const char *tags[] = { UVES_STD_STAR(true), UVES_STD_STAR(false) };
03963     int number_of_tags = sizeof(tags) / sizeof(char *);
03964     int indx;
03965     bool flames = false;
03966     
03967     check( *raw_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
03968        "Could not identify raw frame (%s or %s) in SOF", tags[0], tags[1]);
03969 
03970     *blue = (indx == 0);
03971     
03972     /* Load the image */
03973     check( load_raw_image(*raw_filename,
03974               CPL_TYPE_DOUBLE,
03975               flames,
03976               *blue,
03977               raw_image,
03978               raw_header,
03979               rotated_header),
03980        "Error loading image from file '%s'", *raw_filename);
03981 
03982   cleanup:
03983     if (cpl_error_get_code() != CPL_ERROR_NONE)
03984     {
03985         *raw_filename = NULL;
03986         uves_free_image       (raw_image);
03987         uves_free_propertylist(raw_header);
03988     }
03989     return cpl_error_get_code();
03990 }
03991 
03992 /*----------------------------------------------------------------------------*/
04008 /*----------------------------------------------------------------------------*/
04009 
04010 cpl_error_code
04011 uves_load_drs(const cpl_frameset *frames, 
04012           bool flames,
04013           const char *chip_name,
04014           const char **drs_filename, 
04015           uves_propertylist **drs_header,
04016           enum uves_chip chip)
04017 {
04018     const char *tags[1];
04019     int number_of_tags = sizeof(tags) / sizeof(char *);
04020     int extension;
04021     int indx;
04022     
04023     *drs_header = NULL;
04024     tags[0]   = UVES_DRS_SETUP(flames, chip);
04025     extension = UVES_DRS_SETUP_EXTENSION(chip);
04026 
04027     check( *drs_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
04028        "Could not find DRS table (%s) in SOF", tags[0]);
04029     
04030     /* Load the header */
04031     check( *drs_header = uves_propertylist_load(*drs_filename,
04032                            extension),
04033        "Could not load header from extension %d of file '%s'", extension, *drs_filename);
04034 
04035     check_nomsg( uves_warn_if_chip_names_dont_match(*drs_header, chip_name, chip) );
04036 
04037   cleanup:
04038     if (cpl_error_get_code() != CPL_ERROR_NONE) {
04039     *drs_filename = NULL;
04040     uves_free_propertylist(drs_header);
04041     }
04042     return cpl_error_get_code();
04043 }
04044 
04045 /*----------------------------------------------------------------------------*/
04053 /*----------------------------------------------------------------------------*/
04054 cpl_image *
04055 uves_load_weights(const cpl_frameset *frames, const char **weights_filename,
04056                   enum uves_chip chip)
04057 {
04058     cpl_image *weights = NULL;
04059     const char *tags[1];
04060     int number_of_tags = sizeof(tags) / sizeof(char *);
04061     int extension = 0;
04062     int indx;
04063 
04064     assure( weights_filename != NULL, CPL_ERROR_NULL_INPUT, "Null filename");
04065     
04066     tags[0]   = UVES_WEIGHTS(chip);
04067 
04068     check( *weights_filename = uves_find_frame(frames, 
04069                                                tags, number_of_tags, &indx, NULL), 
04070            "Could not find '%s' in frame set", tags[0]);
04071     
04072     check( weights = cpl_image_load(*weights_filename,
04073                                     CPL_TYPE_DOUBLE,           /* Convert to this type */
04074                                     0,                         /* plane number */
04075                                     extension                  /* Extension number */
04076                ),
04077            "Could not load master bias from extension %d of file '%s'", 
04078            extension, *weights_filename);
04079 
04080   cleanup:
04081     return weights;
04082 }
04083 
04084 
04085 /*----------------------------------------------------------------------------*/
04101 /*----------------------------------------------------------------------------*/
04102 
04103 cpl_error_code
04104 uves_load_mbias(const cpl_frameset *frames, const char *chip_name,
04105         const char **mbias_filename, 
04106         cpl_image **mbias, uves_propertylist **mbias_header, enum uves_chip chip)
04107 {
04108     const char *tags[1];
04109     int number_of_tags = sizeof(tags) / sizeof(char *);
04110     int extension;
04111     int indx;
04112     
04113     *mbias        = NULL;
04114     *mbias_header = NULL;
04115 
04116     tags[0]   = UVES_MASTER_BIAS          (chip);
04117     extension = UVES_MASTER_BIAS_EXTENSION(chip);
04118     
04119     check( *mbias_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
04120        "Could not find '%s' in frame set", tags[0]);
04121     
04122     /* Load the mbias image */
04123     check( *mbias = cpl_image_load(*mbias_filename,
04124                    CPL_TYPE_DOUBLE,           /* Convert to this type */
04125                    0,                         /* plane number */
04126                    extension                  /* Extension number */
04127            ),
04128        "Could not load master bias from extension %d of file '%s'", 
04129        extension, *mbias_filename);
04130 
04131     /* Load the header */
04132     check( *mbias_header = uves_propertylist_load(*mbias_filename,
04133                          extension),
04134        "Could not load header from extension %d of file '%s'", 
04135        extension, *mbias_filename);
04136 
04137     check_nomsg( uves_warn_if_chip_names_dont_match(*mbias_header, chip_name, chip) );
04138 
04139   cleanup:
04140     if (cpl_error_get_code() != CPL_ERROR_NONE) 
04141     {
04142         *mbias_filename = NULL;
04143         uves_free_image(mbias);
04144         uves_free_propertylist(mbias_header);
04145     }
04146     return cpl_error_get_code();
04147 }
04148 
04149 
04150 /*----------------------------------------------------------------------------*/
04166 /*----------------------------------------------------------------------------*/
04167 
04168 cpl_error_code
04169 uves_load_master_formatcheck(const cpl_frameset *frames, const char *chip_name,
04170         const char **mform_filename, 
04171         cpl_image **mform, uves_propertylist **mform_header, enum uves_chip chip)
04172 {
04173     const char *tags[1];
04174     int number_of_tags = sizeof(tags) / sizeof(char *);
04175     int extension;
04176     int indx;
04177     
04178     *mform        = NULL;
04179     *mform_header = NULL;
04180 
04181     tags[0]   = UVES_MASTER_ARC_FORM          (chip);
04182     extension = UVES_MASTER_ARC_FORM_EXTENSION(chip);
04183     
04184     check( *mform_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
04185        "Could not find '%s' in frame set", tags[0]);
04186     
04187     /* Load the mbias image */
04188     check( *mform = cpl_image_load(*mform_filename,
04189                    CPL_TYPE_DOUBLE,           /* Convert to this type */
04190                    0,                         /* plane number */
04191                    extension                  /* Extension number */
04192            ),
04193        "Could not load master formatcheck from extension %d of file '%s'", 
04194        extension, *mform_filename);
04195 
04196     /* Load the header */
04197     
04198     check( *mform_header = uves_propertylist_load(*mform_filename,
04199                          extension),
04200        "Could not load header from extension %d of file '%s'", 
04201        extension, *mform_filename);
04202 
04203     check_nomsg( uves_warn_if_chip_names_dont_match(*mform_header, chip_name, chip) );
04204 
04205   cleanup:
04206     if (cpl_error_get_code() != CPL_ERROR_NONE) 
04207     {
04208         *mform_filename = NULL;
04209         uves_free_image(mform);
04210         uves_free_propertylist(mform_header);
04211     }
04212     return cpl_error_get_code();
04213 }
04214 
04215 /*----------------------------------------------------------------------------*/
04231 /*----------------------------------------------------------------------------*/
04232 
04233 cpl_error_code
04234 uves_load_mdark(const cpl_frameset *frames, const char *chip_name,
04235         const char **mdark_filename, cpl_image **mdark,
04236         uves_propertylist **mdark_header, enum uves_chip chip)
04237 {
04238     const char *tags[2];
04239     int number_of_tags = sizeof(tags) / sizeof(char *);
04240     int extension;
04241     int indx;
04242     
04243     *mdark        = NULL;
04244     *mdark_header = NULL;
04245 
04246     tags[0]   = UVES_MASTER_DARK          (chip);
04247     tags[1]   = UVES_MASTER_PDARK         (chip);
04248     extension = UVES_MASTER_DARK_EXTENSION(chip);
04249     
04250     check( *mdark_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
04251        "Could not find %s or %s in frame set", tags[0], tags[1]);
04252     
04253     /* Load the mdark image */
04254     check( *mdark = cpl_image_load(*mdark_filename,
04255                    CPL_TYPE_DOUBLE,           /* Convert to this type */
04256                    0,                         /* plane number */
04257                    extension                  /* Extension number */
04258            ),
04259        "Could not load master dark from extension %d of file '%s'", 
04260        extension, *mdark_filename);
04261 
04262     /* Load the header */
04263     check( *mdark_header = uves_propertylist_load(*mdark_filename,
04264                          extension),
04265        "Could not load header from extension %d of file '%s'", 
04266        extension, *mdark_filename);
04267 
04268     check_nomsg( uves_warn_if_chip_names_dont_match(*mdark_header, chip_name, chip) );
04269 
04270   cleanup:
04271     if (cpl_error_get_code() != CPL_ERROR_NONE) 
04272     {
04273         *mdark_filename = NULL;
04274         uves_free_image(mdark);
04275         uves_free_propertylist(mdark_header);
04276     }
04277     return cpl_error_get_code();
04278 }
04279 /*----------------------------------------------------------------------------*/
04295 /*----------------------------------------------------------------------------*/
04296 void
04297 uves_load_ref_flat(const cpl_frameset *frames, const char *chip_name,
04298            const char **filename, cpl_image **rflat,
04299            uves_propertylist **rflat_header, enum uves_chip chip)
04300 {
04301     const char *tags[1];
04302     int number_of_tags = sizeof(tags) / sizeof(char *);
04303     int extension;
04304     int indx;
04305     
04306     *rflat        = NULL;
04307     *rflat_header = NULL;
04308 
04309     tags[0]   = UVES_REF_TFLAT(chip);
04310     extension = UVES_MASTER_FLAT_EXTENSION(chip);
04311 
04312     check( *filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
04313        "Could not find %s in frame set", tags[0]);
04314     
04315     check( *rflat = cpl_image_load(*filename,
04316                    CPL_TYPE_DOUBLE,           /* Convert to this type */
04317                    0,                         /* plane number */
04318                    extension                  /* Extension number */
04319            ),
04320        "Could not load reference dark from extension %d of file '%s'", 
04321        extension, *filename);
04322 
04323     check( *rflat_header = uves_propertylist_load(*filename,
04324                          extension),
04325        "Could not load header from extension %d of file '%s'", 
04326        extension, *filename);
04327 
04328     check_nomsg( uves_warn_if_chip_names_dont_match(*rflat_header, chip_name, chip) );
04329 
04330   cleanup:
04331     if (cpl_error_get_code() != CPL_ERROR_NONE) 
04332     {
04333         *filename = NULL;
04334         uves_free_image(rflat);
04335         uves_free_propertylist(rflat_header);
04336     }
04337 
04338     return;
04339 }
04340 
04341 /*----------------------------------------------------------------------------*/
04357 /*----------------------------------------------------------------------------*/
04358 
04359 cpl_error_code
04360 uves_load_mflat_const(const cpl_frameset *frames, const char *chip_name,
04361               const char **mflat_filename, 
04362               cpl_image **mflat, uves_propertylist **mflat_header, 
04363               enum uves_chip chip,
04364               const cpl_frame **mflat_frame)
04365 {
04366     const char *tags[6];
04367     int number_of_tags = sizeof(tags) / sizeof(char *);
04368     int extension;
04369     int indx;
04370     
04371     *mflat        = NULL;
04372     *mflat_header = NULL;
04373 
04374     tags[0]   = UVES_REF_TFLAT            (chip);   /* Use REF TFLAT, rather than MASTER_TFLAT */
04375     tags[1]   = UVES_MASTER_FLAT          (chip);
04376     tags[2]   = UVES_MASTER_DFLAT         (chip);
04377     tags[3]   = UVES_MASTER_IFLAT         (chip);
04378     tags[4]   = UVES_MASTER_TFLAT         (chip);
04379     tags[5]   = UVES_MASTER_SCREEN_FLAT   (chip);
04380     extension = UVES_MASTER_FLAT_EXTENSION(chip);
04381     
04382     check( *mflat_filename = uves_find_frame(frames, tags, number_of_tags, &indx,
04383                          mflat_frame), 
04384        "Could not find '%s', '%s', '%s', '%s' or '%s' in frame set", 
04385        tags[0], tags[1], tags[2], tags[3], tags[4]);
04386     
04387     /* Load the mflat image */
04388     check( *mflat = cpl_image_load(*mflat_filename,
04389                    CPL_TYPE_DOUBLE,           /* Convert to this type */
04390                    0,                         /* plane number */
04391                    extension                  /* Extension number */
04392            ),
04393        "Could not load master flat from extension %d of file '%s'", 
04394        extension, *mflat_filename);
04395 
04396     /* Load the header */
04397     check( *mflat_header = uves_propertylist_load(*mflat_filename,
04398                          extension),
04399        "Could not load header from extension %d of file '%s'", 
04400        extension, *mflat_filename);
04401 
04402     check_nomsg( uves_warn_if_chip_names_dont_match(*mflat_header, chip_name, chip) );
04403 
04404   cleanup:
04405     if (cpl_error_get_code() != CPL_ERROR_NONE) 
04406     {
04407         *mflat_filename = NULL;
04408         uves_free_image(mflat);
04409         uves_free_propertylist(mflat_header);
04410     }
04411     return cpl_error_get_code();
04412 }
04413 
04414 /*----------------------------------------------------------------------------*/
04429 /*----------------------------------------------------------------------------*/
04430 cpl_error_code
04431 uves_load_mflat(cpl_frameset *frames, const char *chip_name,
04432         const char **mflat_filename, 
04433         cpl_image **mflat, uves_propertylist **mflat_header, enum uves_chip chip,
04434         cpl_frame **mflat_frame)
04435 {
04436     return uves_load_mflat_const((const cpl_frameset *)frames,
04437                  chip_name,
04438                  mflat_filename,
04439                  mflat, mflat_header, chip,
04440                  (const cpl_frame **) mflat_frame);
04441 }
04442 
04443 /*----------------------------------------------------------------------------*/
04475 /*----------------------------------------------------------------------------*/
04476 cpl_error_code
04477 uves_load_ordertable(const cpl_frameset *frames, 
04478                      bool flames,
04479                      const char *chip_name,
04480                      const char **ordertable_filename, 
04481                      cpl_table **ordertable, 
04482                      uves_propertylist **ordertable_header, 
04483                      uves_propertylist **ordertable_xheader, 
04484                      polynomial **order_locations, 
04485                      cpl_table **traces, 
04486                      int *tab_in_out_oshift,
04487                      double *tab_in_out_yshift,
04488                      int ** fib_msk,
04489                      double ** fib_pos,
04490                      enum uves_chip chip,
04491                      bool guess_table)
04492 {
04493     uves_propertylist *midas_header = NULL;      /* Table header if midas format */
04494     uves_propertylist *prime_header = NULL;      /* Prime header if flames  */
04495     const char *tags[1];
04496     int number_of_tags = sizeof(tags) / sizeof(char *);
04497     bool format_is_midas;
04498     int *tioo = NULL;
04499     double *tioy = NULL;
04500     int indx;
04501 
04502     double *fibre_pos = NULL;
04503     int *fibre_mask = NULL;
04504 
04505     if (guess_table)
04506     {
04507         tags[0] = UVES_GUESS_ORDER_TABLE(flames, chip);
04508     }
04509     else
04510     {
04511         tags[0] = UVES_ORDER_TABLE(flames, chip);
04512     }
04513 
04514     check( *ordertable_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL), 
04515        "No order table (%s) found in SOF", tags[0]);
04516     
04517     check( *ordertable = cpl_table_load(*ordertable_filename,
04518                     UVES_ORDER_TABLE_EXTENSION,
04519                     1),                /* Mark identified 
04520                                   invalid values? (1=yes) */
04521        "Error loading order table from extension %d of file '%s'", 
04522        UVES_ORDER_TABLE_EXTENSION, *ordertable_filename);
04523     
04524     assure(ordertable_header != NULL,CPL_ERROR_NULL_INPUT,
04525            "NULL primary header uves_propertylist variable header");
04526     check( *ordertable_header = uves_propertylist_load(*ordertable_filename, 0),
04527        "Could not load header from extension 0 of '%s'", *ordertable_filename);
04528 
04529     if(ordertable_xheader != NULL) {
04530 
04531     check( *ordertable_xheader = uves_propertylist_load(*ordertable_filename, 1),
04532        "Could not load header from extension 1 of '%s'", *ordertable_filename);
04533 
04534 
04535 
04536     }
04537     check_nomsg( uves_warn_if_chip_names_dont_match(*ordertable_header, chip_name, chip) );
04538     
04539     check(uves_check_if_format_is_midas(*ordertable_header,&format_is_midas),
04540       "Error getting FITS format");
04541 
04542 
04543     if (!format_is_midas && !flames)
04544     {
04545             /* The format check and order position recipes create order tables
04546                with different column names. Rename if necessary. 
04547 
04548                This is a workaround for the problem that different recipes
04549                create the same products (order tables and line tables).
04550                The true solution would be to remove the format check recipe from
04551                the recution cascade, and use the theoretical physical model to
04552                bootstrap the order definition and wavelength calibration.
04553             */
04554             if (cpl_table_has_column(*ordertable, "ORDER"))
04555                 {
04556                     cpl_table_name_column(*ordertable, "ORDER", "Order");
04557                 }
04558             if (cpl_table_has_column(*ordertable, "YFIT"))
04559                 {
04560                     cpl_table_name_column(*ordertable, "YFIT", "Yfit");
04561                 }
04562 
04563         if (order_locations != NULL)
04564         {
04565             check( *order_locations = 
04566                load_polynomial(*ordertable_filename, UVES_ORDER_TABLE_EXTENSION_POLY),
04567                "Could not read polynomial from extension %d of file '%s'",
04568                UVES_ORDER_TABLE_EXTENSION_POLY, *ordertable_filename);
04569         }
04570 
04571         if (traces != NULL)
04572         {
04573             check( *traces = cpl_table_load(*ordertable_filename,
04574                             UVES_ORDER_TABLE_EXTENSION_FIBRE,
04575                             1),    /* Mark identified 
04576                                   invalid values? (1=yes) */
04577                "Error loading fibre table from extension %d of file '%s'", 
04578                UVES_ORDER_TABLE_EXTENSION_FIBRE, *ordertable_filename);
04579         }
04580     }
04581     else
04582         /* MIDAS format, or FLAMES */
04583     {
04584         /* Rename */
04585         check(( cpl_table_cast_column (*ordertable, "ORDER", "Order", CPL_TYPE_INT),
04586                 cpl_table_erase_column(*ordertable, "ORDER")),
04587               "Error casting and renaming column 'ORDER'");
04588         
04589         check( cpl_table_name_column(*ordertable, "YFIT", "Yfit"),
04590                "Error renaming column 'YFIT'");
04591                 
04592         //check( midas_header = uves_propertylist_load(*ordertable_filename, 1),
04593     //      "Could not load header from extension 1 of '%s'", 
04594     //     *ordertable_filename);
04595       check(midas_header = uves_propertylist_load(*ordertable_filename, 1),
04596          "Could not load header from extension 1 of '%s'",
04597          *ordertable_filename);
04598 
04599     if(flames) {
04600           check(prime_header = uves_propertylist_load(*ordertable_filename, 0),
04601          "Could not load header from extension 0 of '%s'",
04602          *ordertable_filename);
04603       check_nomsg(uves_propertylist_append(midas_header,prime_header));
04604         }
04605 
04606         /* Load polynomial named 'COEFF' from descriptors in extension 1 */
04607         if (order_locations != NULL)
04608         {
04609             check( *order_locations = 
04610            uves_polynomial_convert_from_plist_midas(midas_header, "COEFF",-1),
04611                    "Error reading polynomial from %s", *ordertable_filename);
04612         }
04613 
04614 
04615         if (flames && tab_in_out_oshift != NULL )
04616         {
04617             /* Get tab_in_out_oshift */
04618             int tioo_length;
04619                     cpl_type tioo_type;
04620 
04621             check( tioo = uves_read_midas_array(
04622                    midas_header, "TAB_IN_OUT_OSHIFT", &tioo_length,
04623                                &tioo_type, NULL),
04624                "Error reading TAB_IN_OUT_OSHIFT from MIDAS header");
04625 
04626                     assure( tioo_type == CPL_TYPE_INT, CPL_ERROR_TYPE_MISMATCH,
04627                             "Type of TAB_IN_OUT_OSHIFT is %s, double expected",
04628                             uves_tostring_cpl_type(tioo_type));
04629 
04630             if (tioo_length != 1)
04631             {
04632                 uves_msg_warning("Length of TAB_IN_OUT_OSHIFT array is %d; "
04633                          "%d expected", tioo_length, 1);
04634             }
04635 
04636             *tab_in_out_oshift = tioo[0];
04637             
04638             uves_msg_debug("TAB_IN_OUT_OSHIFT = %d", *tab_in_out_oshift);
04639 
04640         }
04641         
04642         if (flames && tab_in_out_yshift != NULL)
04643         {
04644             /* Get tab_in_out_yshift */
04645             int tioy_length;
04646                     cpl_type tioy_type;
04647 
04648             check( tioy = uves_read_midas_array(
04649                    midas_header, "TAB_IN_OUT_YSHIFT", &tioy_length,
04650                                &tioy_type, NULL),
04651                "Error reading TAB_IN_OUT_YSHIFT from MIDAS header");
04652 
04653                     assure( tioy_type == CPL_TYPE_DOUBLE, CPL_ERROR_TYPE_MISMATCH,
04654                             "Type of TAB_IN_OUT_YSHIFT is %s, double expected",
04655                             uves_tostring_cpl_type(tioy_type));
04656 
04657             if (tioy_length != 1)
04658             {
04659                 uves_msg_warning("Length of TAB_IN_OUT_YSHIFT array is %d; "
04660                          "%d expected", tioy_length, 1);
04661             }
04662 
04663             *tab_in_out_yshift = tioy[0];
04664 
04665             uves_msg_debug("TAB_IN_OUT_YSHIFT = %f", *tab_in_out_yshift);
04666         }
04667         
04668         if (traces != NULL)
04669         {
04670             *traces = uves_ordertable_traces_new();
04671             
04672             if (!flames)
04673             /* UVES: one trace with zero offset */
04674             {
04675                 int fibre_ID = 0;
04676                 double fibre_offset = 0.0;
04677                 int fibre_msk = 1;
04678                 uves_ordertable_traces_add(*traces, 
04679                                fibre_ID,
04680                                fibre_offset,
04681                                fibre_msk);
04682             }
04683             else
04684             /* FLAMES */
04685             {
04686 
04687                 int fibre_pos_length;
04688                 int fibre_mask_length;
04689                             cpl_type fibre_pos_type;
04690                             cpl_type fibre_mask_type;
04691                 int fibre_ID;
04692 
04693                 check( fibre_pos = uves_read_midas_array(
04694                        midas_header, "FIBREPOS", &fibre_pos_length,
04695                                        &fibre_pos_type, NULL),
04696                    "Error reading FIBREPOS from MIDAS header");
04697 
04698                             assure( fibre_pos_type == CPL_TYPE_DOUBLE, CPL_ERROR_TYPE_MISMATCH,
04699                                     "Type of FIBREPOS is %s, double expected",
04700                                     uves_tostring_cpl_type(fibre_pos_type));
04701 
04702                 check( fibre_mask = uves_read_midas_array(
04703                        midas_header, "FIBREMASK", &fibre_mask_length,
04704                                        &fibre_mask_type, NULL),
04705                    "Error reading FIBREMASK from MIDAS header");
04706 
04707                             assure( fibre_mask_type == CPL_TYPE_INT, CPL_ERROR_TYPE_MISMATCH,
04708                                     "Type of FIBREMASK is %s, double expected",
04709                                     uves_tostring_cpl_type(fibre_mask_type));
04710                             
04711                 assure( fibre_pos_length == fibre_mask_length,
04712                     CPL_ERROR_INCOMPATIBLE_INPUT,
04713                     "FIBREMASK has length %d, but "
04714                     "FIBREPOS has length %d",
04715                     fibre_mask_length, fibre_pos_length );
04716             
04717                 *fib_pos= cpl_malloc(sizeof(double) * fibre_pos_length);
04718                 *fib_msk= cpl_malloc(sizeof(int) * fibre_mask_length);
04719 
04720                 for (fibre_ID = 0; fibre_ID < fibre_mask_length; fibre_ID++)
04721                 {
04722                     uves_msg_debug("Found trace %d, position %f (%s)",
04723                            fibre_ID, fibre_pos[fibre_ID],
04724                            fibre_mask[fibre_ID] ? 
04725                            "enabled" : "disabled");
04726                     uves_ordertable_traces_add(*traces, 
04727                                    fibre_ID,
04728                                    fibre_pos[fibre_ID],
04729                                    fibre_mask[fibre_ID]);
04730                     (*fib_pos)[fibre_ID]=fibre_pos[fibre_ID];
04731                     (*fib_msk)[fibre_ID]=fibre_mask[fibre_ID];
04732                 }
04733             }
04734         }
04735     }
04736 
04737   cleanup:
04738     uves_free_propertylist(&midas_header);
04739     uves_free_double(&fibre_pos);
04740     uves_free_int(&fibre_mask);
04741     uves_free_int(&tioo);
04742     uves_free_double(&tioy);
04743     uves_free_propertylist(&prime_header);
04744 
04745     if (cpl_error_get_code() != CPL_ERROR_NONE) 
04746     {
04747         *ordertable_filename = NULL;
04748         uves_free_table       (ordertable);
04749         uves_free_propertylist(ordertable_header);
04750         if (order_locations != NULL) uves_polynomial_delete(order_locations);
04751         if (traces != NULL)          uves_free_table       (traces);
04752     }
04753     return cpl_error_get_code();
04754 }
04755 
04756 
04757 
04758 /*--------------------------------------------------------------------------*/
04767 /*--------------------------------------------------------------------------*/
04768 
04769 
04770 cpl_error_code
04771 uves_check_if_format_is_midas(uves_propertylist* header, bool* format_is_midas)
04772 {
04773  
04774   /* Determine format of order table and read the polynomial */
04775   if (uves_propertylist_contains(header, UVES_DRS_ID)) {
04776 
04777 
04778     const char* drs_id=NULL;
04779 
04780     check( drs_id = uves_pfits_get_drs_id(header), "Error reading DRS ID");
04781     if (strstr(drs_id, "CPL") != NULL || 
04782     strstr(drs_id, "cpl") != NULL) {
04783       *format_is_midas = false;
04784       uves_msg_debug("Order table was written by CPL");
04785     } else if (strstr(drs_id, "MIDAS") != NULL || 
04786                strstr(drs_id, "midas") != NULL) {
04787       *format_is_midas = true;
04788       uves_msg_low("Order table was written by MIDAS");
04789     } else {
04790       assure ( false, CPL_ERROR_ILLEGAL_INPUT, 
04791            "Unrecognized order table format, DRS_ID = '%s'", drs_id);
04792     }
04793   } else {
04794 
04795     *format_is_midas = true;
04796     uves_msg_debug("No '%s' keyword found. Assuming MIDAS format", UVES_DRS_ID);
04797   }
04798  
04799  cleanup:
04800   return cpl_error_get_code();
04801 
04802 }
04803 
04804 /*--------------------------------------------------------------------------*/
04814 /*--------------------------------------------------------------------------*/
04815 
04816 static cpl_error_code
04817 create_column_pixelsize(cpl_table *linetable)
04818 {
04819     polynomial *p = NULL;
04820     cpl_table *t = NULL;
04821     double d1, d2;
04822     int i;
04823     int degree = 3;
04824     
04825     /* Remove rows with Ident = 0 (unidentified lines) */
04826     check( t = uves_extract_table_rows(linetable, "Ident", CPL_GREATER_THAN, 0.1),
04827        "Error deleting rows with Ident=0");
04828     
04829     /* Create column Aux := Ident * Order  */
04830     check(( cpl_table_duplicate_column(t, "Aux", t, "Ident"),
04831         cpl_table_multiply_columns(t, "Aux", "Order")),
04832       "Error creating 'Aux' column");
04833     
04834     check( p = uves_polynomial_regression_1d(t, 
04835                          "X", "Aux", NULL,
04836                          degree,
04837                          NULL, NULL,
04838                          NULL,
04839                          -1),
04840        "Regression failed");
04841     
04842     check( d1 = uves_polynomial_get_coeff_1d(p, 1),
04843        "Error reading polynomial coefficient");
04844     
04845     check( d2 = uves_polynomial_get_coeff_1d(p, 2),
04846        "Error reading polynomial coefficient");
04847     
04848     cpl_table_new_column(linetable, LINETAB_PIXELSIZE, CPL_TYPE_DOUBLE);
04849     
04850     for (i = 0; i < cpl_table_get_nrow(linetable); i++)
04851     {
04852         int x;
04853         int order;
04854         double pixelsize;
04855         double ident;
04856         
04857         check(( x     = cpl_table_get_double(linetable, "X", i, NULL),
04858             order = cpl_table_get_int   (linetable, "Order", i, NULL),
04859             ident = cpl_table_get_double(linetable, "Ident", i, NULL)),
04860           "Error reading line table");
04861         
04862         assure( order != 0, CPL_ERROR_ILLEGAL_INPUT, "Illegal order number: %d", order);
04863         
04864         /* 
04865          * MIDAS approximates
04866          * d(lambda m)/dx (x,m)   =  d1 + 2*d2*x
04867          *
04868          * where the polynomial itself is ... + d1*x + d2*x^2 + ...
04869          */
04870         pixelsize = (d1 + 2*d2* x) / order;
04871 //        pixelsize = uves_polynomial_derivative_2d(dispersion_relation, x, order, 1)/order;
04872         
04873         if (ident > 0.01)
04874         {
04875             cpl_table_set_double(linetable, LINETAB_PIXELSIZE, i, pixelsize);
04876         }
04877         else
04878         {
04879             cpl_table_set_invalid(linetable, LINETAB_PIXELSIZE, i);
04880         }
04881     }
04882     
04883   cleanup:
04884     uves_free_table(&t);
04885     uves_polynomial_delete(&p);
04886     return cpl_error_get_code();
04887 }
04888 
04889 
04890 
04891 /*----------------------------------------------------------------------------*/
04918 /*----------------------------------------------------------------------------*/
04919 static void
04920 align_order_line_table(cpl_table *linetable, const polynomial *absolute_order,
04921                uves_propertylist **linetable_header,
04922                const polynomial *order_locations, int minorder, int maxorder)
04923 {
04924     polynomial *absord = NULL;
04925 
04926     assure ( order_locations  != NULL, CPL_ERROR_NULL_INPUT, 
04927              "Null order locations polynomial!");
04928 
04929     assure ( absolute_order  != NULL, CPL_ERROR_NULL_INPUT, 
04930              "Null absolute order pllynomial!");
04931     assure( cpl_table_has_column(linetable, "X"   ), CPL_ERROR_DATA_NOT_FOUND, 
04932         "Missing line table column 'X'");
04933     assure( cpl_table_has_column(linetable, "Ynew"), CPL_ERROR_DATA_NOT_FOUND, 
04934         "Missing line table column 'Ynew'");
04935     assure( cpl_table_has_column(linetable, "Order"), CPL_ERROR_DATA_NOT_FOUND, 
04936         "Missing line table column 'Order'");
04937     
04938     assure( cpl_table_get_column_type(linetable, "X") == CPL_TYPE_DOUBLE,
04939         CPL_ERROR_TYPE_MISMATCH, "Line table column 'X' has type %s (double expected))",
04940         uves_tostring_cpl_type(cpl_table_get_column_type(linetable, "X")) );
04941     
04942     assure( cpl_table_get_column_type(linetable, "Ynew") == CPL_TYPE_DOUBLE,
04943         CPL_ERROR_TYPE_MISMATCH, "Line table column 'Ynew' has type %s (double expected))",
04944         uves_tostring_cpl_type(cpl_table_get_column_type(linetable, "Ynew")) );
04945     
04946     assure( cpl_table_get_column_type(linetable, "Y") == CPL_TYPE_INT,
04947         CPL_ERROR_TYPE_MISMATCH, "Line table column 'Y' has type %s (integer expected))",
04948         uves_tostring_cpl_type(cpl_table_get_column_type(linetable, "Y")) );
04949 
04950 
04951     if (linetable_header != NULL)
04952     /* then correct first/abs order keywords */
04953     {
04954         int line_first, line_last;
04955         int ord_first, ord_last;
04956             {
04957 
04958                 int maxx;
04959                 int minx;
04960                 int x, y, order, absorder;  /* At chip center */
04961                 int coeff;
04962                 
04963 
04964                 maxx = uves_round_double(cpl_table_get_column_max(linetable, "X"));
04965 
04966                 minx = uves_round_double(cpl_table_get_column_min(linetable, "X"));
04967                 
04968                 assure( 1 <= minx && minx <= maxx, CPL_ERROR_ILLEGAL_INPUT,
04969                         "Illegal min/max line x positions: %d/%d, must be > 1", 
04970                         minx, maxx);
04971         
04972                 /* Center of chip */
04973                 x = (minx + maxx) / 2;
04974                 order = (minorder + maxorder) / 2;
04975 
04976                 y = uves_polynomial_evaluate_2d(order_locations, x, order);
04977                 if (uves_polynomial_derivative_2d(absolute_order, x, y, 2) > 0) {
04978                     coeff = +1;
04979                 }
04980                 else {
04981                     coeff = -1;
04982                 } 
04983 
04984     assure ( order_locations  != NULL, CPL_ERROR_NULL_INPUT, 
04985              "Null order locations polynomial!");
04986 
04987 
04988                 absorder = uves_round_double(uves_polynomial_evaluate_2d(absolute_order, x, y));
04989 
04990 
04991                 uves_msg_debug("Absolute order polynomial at (%d, %d) = %f, "
04992                                "rounding to %d", x, y, 
04993                                uves_polynomial_evaluate_2d(absolute_order, x, y), absorder);
04994 
04995                 ord_first = absorder + (minorder - order) * coeff;
04996                 ord_last  = absorder + (maxorder - order) * coeff;
04997             }
04998 
04999             check( line_first =
05000            uves_pfits_get_firstabsorder(*linetable_header),
05001            "Could not read order number from line table header");
05002         
05003         check( line_last  =
05004            uves_pfits_get_lastabsorder (*linetable_header),
05005            "Could not read order number from line table header");
05006         
05007         uves_msg_debug("Order table range: %d - %d. Line table range: %d - %d",
05008                ord_first, ord_last, line_first, line_last);
05009         
05010         if (line_first != ord_first ||
05011         line_last  != ord_last)
05012         {
05013             uves_msg_warning("Provided line and order tables are incompatible. "
05014                      "Line table contains orders %d - %d. "
05015                      "Order table contains orders %d - %d. "
05016                      "Correcting on the fly",
05017                      line_first, line_last, ord_first, ord_last);
05018             
05019             check( uves_pfits_set_firstabsorder(*linetable_header,
05020                             ord_first),
05021                "Could not write corrected first absolute order number");
05022             check( uves_pfits_set_lastabsorder(*linetable_header,
05023                                ord_last),
05024                "Could not write corrected first absolute order number");
05025 
05026             uves_msg_debug("Setting line table order range = %d - %d",
05027                    ord_first, ord_last);
05028         }
05029     }
05030     /* This 'Y' column is the relative order number in linetables
05031        but the absolute order number (and therefore equal to
05032        the 'order' column) in line guess tables (!!) 
05033     */
05034 
05035     {
05036     double epsilon = 0.01; /* Must be larger than machine precision but
05037                   less than the typical difference between
05038                   absolute/relative numbering (~100) 
05039                    */
05040 
05041     if (fabs(cpl_table_get_column_median(linetable, "Y") - 
05042          cpl_table_get_column_median(linetable, "Order")) > epsilon)
05043 
05044         /* If column 'Y' is different from 'Order', 
05045            then 'Y' is the relative order number and
05046            should be corrected (if there is an inconsistency).
05047 
05048            For now, simply delete the 'Y' column because it is
05049            not used later. If the 'Y' column will be used later,
05050            it must be corrected at this place.
05051         */
05052         {
05053         uves_msg_debug("Removing line table column 'Y'");
05054         cpl_table_erase_column(linetable, "Y");
05055         }
05056     }
05057     
05058   cleanup:
05059     uves_polynomial_delete(&absord);
05060 }
05061 
05062 
05063 /*----------------------------------------------------------------------------*/
05102 /*----------------------------------------------------------------------------*/
05103 void
05104 uves_load_linetable(const cpl_frameset *frames, 
05105                     bool flames,
05106                     const char *chip_name,
05107                     const polynomial *order_locations, int minorder, int maxorder,
05108                     const char **linetable_filename,
05109                     cpl_table **linetable,
05110                     uves_propertylist **linetable_header,
05111                     polynomial **dispersion_relation,
05112                     polynomial **absolute_order,
05113                     enum uves_chip chip, int trace_id, int window)
05114 {
05115     uves_propertylist *primary_header = NULL;
05116     uves_propertylist *header         = NULL;
05117     uves_propertylist *midas_header   = NULL;       /* MIDAS extension header */
05118     int *absorders                   = NULL;       /* Absolute order numbers */
05119     cpl_table *temp                  = NULL;
05120     polynomial *absolute_order_local = NULL;
05121     const char *tags[3];
05122     int number_of_tags = sizeof(tags) / sizeof(char *);
05123     const char *drs_id;
05124     bool format_is_midas;               /* Was file written by CPL or MIDAS? */
05125     int base_extension;                 /* Last extension (e.g. 0) before 
05126                        extension with line table */
05127     int indx;
05128 
05129     if (flames)
05130     {
05131         tags[0] = UVES_GUESS_LINE_TABLE(flames, chip);
05132         tags[1] = UVES_LINE_TABLE(flames, chip);
05133         tags[2] = UVES_LINE_TABLE(flames, chip);
05134         number_of_tags = 3;
05135         
05136         check( *linetable_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
05137            "No line table (%s, %s or %s) found in SOF", tags[0], tags[1], tags[2]);
05138     }
05139     else
05140     {
05141         tags[0] = UVES_LINE_TABLE(flames, chip);
05142         tags[1] = UVES_LINE_TABLE(flames, chip);
05143         tags[2] = UVES_GUESS_LINE_TABLE(flames, chip);
05144         
05145         /* For backwards compatibility with MIDAS, 
05146            also look for LINE_TABLE_chip%d */
05147         if (cpl_frameset_find_const(frames, tags[0]) == NULL &&
05148             cpl_frameset_find_const(frames, tags[1]) == NULL &&
05149             cpl_frameset_find_const(frames, tags[2]) == NULL)
05150         {
05151             uves_msg_debug("No %s", tags[0]);
05152             
05153             if (window >= 1)
05154             {
05155                 /* Look for LINE_TABLE_BLUEwindow */
05156                 
05157                 tags[0] = UVES_LINE_TABLE_MIDAS(chip, window);
05158                 tags[1] = UVES_LINE_TABLE_MIDAS(chip, window);
05159                 tags[2] = UVES_LINE_TABLE_MIDAS(chip, window);
05160                 
05161                 uves_msg_debug("Trying %s", tags[0]);
05162             }
05163             if (window <= 0)
05164             {
05165                 /* Look for any LINE_TABLE_BLUEi */
05166                 tags[0] = UVES_LINE_TABLE_MIDAS(chip, 1);
05167                 tags[1] = UVES_LINE_TABLE_MIDAS(chip, 2);
05168                 tags[2] = UVES_LINE_TABLE_MIDAS(chip, 3);
05169                 
05170                 uves_msg_debug("Trying %s, %s or %s", tags[0], tags[1], tags[2]);
05171             }
05172         }
05173         
05174         check( *linetable_filename = uves_find_frame(frames, tags, number_of_tags, &indx, NULL),
05175            "No line table (%s, %s or %s) found in SOF", tags[0], tags[1], tags[2]);
05176     }
05177     
05178     /* Read primary header */
05179     check( primary_header = uves_propertylist_load(*linetable_filename, 0),
05180        "Could not load primary header of '%s'", *linetable_filename);  
05181 
05182     check_nomsg( uves_warn_if_chip_names_dont_match(primary_header, chip_name, chip) );
05183     
05184     /* Determine format of line table */
05185     if (uves_propertylist_contains(primary_header, UVES_DRS_ID))
05186     {
05187         check( drs_id = uves_pfits_get_drs_id(primary_header), "Error reading DRS ID");
05188         if (strstr(drs_id, "CPL") != NULL || strstr(drs_id, "cpl") != NULL)
05189         {
05190             format_is_midas = false;
05191             uves_msg_debug("Line table was written by CPL");
05192         }
05193         else if (strstr(drs_id, "MIDAS") != NULL || strstr(drs_id, "midas") != NULL)
05194         {
05195             format_is_midas = true;
05196             uves_msg_debug("Line table was written by MIDAS");
05197         }
05198         else
05199         {
05200             assure ( false,
05201                  CPL_ERROR_ILLEGAL_INPUT,
05202                  "Unrecognized line table format, DRS_ID = '%s'", drs_id);
05203         }
05204     }
05205     else
05206     {
05207         format_is_midas = true;
05208         uves_msg_debug("No '%s' keyword found. Assuming MIDAS format", UVES_DRS_ID);
05209     }
05210 
05211     if (format_is_midas || flames)
05212     {
05213         if (!flames)
05214         {
05215             assure( trace_id == 0 && (window == -1 || (1 <= window && window <= 3)), 
05216                 CPL_ERROR_UNSUPPORTED_MODE,
05217                 "Cannot read (fibre, window) = (%d, %d) from MIDAS line table", 
05218                 trace_id, window);
05219             
05220             base_extension = 0;
05221         }
05222         else
05223         {
05224 
05225       if(trace_id > 0) {
05226 
05227             assure( ((1<= trace_id && trace_id <= 9) && (window == -1)), 
05228                 CPL_ERROR_UNSUPPORTED_MODE,
05229                 "Cannot read (fibre, window) = (%d, %d) from MIDAS line table", 
05230                 trace_id, window);
05231             
05232             base_extension = 0;
05233 
05234 
05235       } else {
05236 
05237             uves_msg_warning("Assuming line table is guess table");
05238             base_extension = 0;
05239       }
05240         }
05241     }
05242     else
05243     /* Find table extension containing the line table for the specified trace and window */
05244     {
05245         int nextensions;
05246         bool found;
05247         
05248         check( nextensions = uves_get_nextensions(*linetable_filename),
05249            "Error reading number of extensions of file '%s'", *linetable_filename);
05250         header = NULL;
05251         found = false;
05252 
05253             uves_msg_debug("Number of extensions = %d", nextensions);
05254 
05255         for (base_extension = 1; base_extension < nextensions && !found; base_extension++)
05256         {
05257             int header_trace;
05258             int header_window;
05259             
05260             /* Read header trace & window info */
05261             check(( uves_free_propertylist(&header),
05262                header = uves_propertylist_load(*linetable_filename, base_extension)),
05263                "Could not header of extension %d of '%s'", 
05264               base_extension, *linetable_filename);
05265             
05266             check( header_trace  = uves_pfits_get_traceid     (header),
05267                "Error reading trace ID from header of extension %d of '%s'",
05268                base_extension, *linetable_filename);
05269             
05270             check( header_window = uves_pfits_get_windownumber(header),
05271                "Error reading window number from header of extension %d of '%s'",
05272                base_extension, *linetable_filename);
05273             
05274                     uves_msg_debug("Found (trace, window) = (%d, %d), need (%d, %d)",
05275                                    header_trace, header_window,
05276                                    trace_id, window);
05277 
05278             found = ( (trace_id == header_trace) && 
05279                   (window == -1 || window == header_window) );
05280         }
05281         
05282         assure( found,
05283             CPL_ERROR_ILLEGAL_INPUT,
05284             "Line table (trace, window) = (%d, %d) is not present in file '%s'",
05285             trace_id, window, *linetable_filename);
05286 
05287         /* Let 'base_extension' be the first extension before 
05288            the proper extension was found (0, 3, 6, ...) */
05289         base_extension -= 2;
05290         /* ...and incremented in for-loop */
05291     }
05292 
05293     check( *linetable = cpl_table_load(*linetable_filename,
05294                        base_extension + UVES_LINE_TABLE_EXTENSION,
05295                        1),              /* Mark identified 
05296                                invalid values? (1=yes) */
05297        "Error loading line table from extension %d of file '%s'", 
05298        base_extension + UVES_LINE_TABLE_EXTENSION, *linetable_filename);
05299 
05300     /* Read header of table extension if requested */
05301     if (linetable_header != NULL)
05302     {
05303         check( *linetable_header = 
05304            uves_propertylist_load(*linetable_filename, 
05305                      base_extension + UVES_LINE_TABLE_EXTENSION),
05306            "Could not load header of extension %d of '%s'", 
05307            base_extension + UVES_LINE_TABLE_EXTENSION, *linetable_filename);
05308 
05309         if (format_is_midas)
05310         {
05311             int size = 0;
05312                     cpl_type type;
05313             absorders = uves_read_midas_array(*linetable_header, "ORDER", &size,
05314                                                       &type, NULL);
05315                     
05316                     assure( type == CPL_TYPE_INT, CPL_ERROR_TYPE_MISMATCH,
05317                             "Type of ORDER is %s, int expected",
05318                             uves_tostring_cpl_type(type));
05319 
05320             assure( size == 2, 
05321                 CPL_ERROR_ILLEGAL_INPUT,
05322                 "'ORDER' array has size %d. Size 2 expected.", size);
05323             check(( uves_pfits_set_firstabsorder(*linetable_header, absorders[0]),
05324                 uves_pfits_set_lastabsorder(*linetable_header, absorders[1])),
05325               "Error updating table header");
05326         }        
05327     }
05328     
05329     /* Read the polynomials if requested */
05330     if (format_is_midas)
05331     {
05332         /* Rename & cast order/ident/X columns */
05333         check(( cpl_table_cast_column(*linetable, "X", "xxxx", CPL_TYPE_DOUBLE),
05334             cpl_table_erase_column(*linetable, "X"),
05335             cpl_table_name_column(*linetable, "xxxx", "X")),
05336           "Error casting and renaming column 'X'");
05337         
05338         check(( cpl_table_cast_column(*linetable, "YNEW", "xxxx", CPL_TYPE_DOUBLE),
05339             cpl_table_erase_column(*linetable, "YNEW"),
05340             cpl_table_name_column(*linetable, "xxxx", "Ynew")),
05341           "Error casting and renaming column 'YNEW'");
05342         
05343         check(( cpl_table_cast_column(*linetable, "Y", "xxxx", CPL_TYPE_INT),
05344             cpl_table_erase_column(*linetable, "Y"),
05345             cpl_table_name_column(*linetable, "xxxx", "Y")),
05346            "Error casting and renaming column 'Y'");
05347 
05348         check(( cpl_table_cast_column(*linetable, "ORDER", "Order", CPL_TYPE_INT),
05349             cpl_table_erase_column(*linetable, "ORDER")),
05350            "Error casting and renaming column 'ORDER'");
05351            
05352         check( cpl_table_name_column(*linetable, "IDENT", "Ident"),
05353            "Error renaming column 'IDENT'");
05354 
05355         check( midas_header = uves_propertylist_load(
05356                *linetable_filename, 
05357                base_extension + UVES_LINE_TABLE_EXTENSION),
05358            "Could not load header of extension %d of '%s'",
05359            base_extension + UVES_LINE_TABLE_EXTENSION, *linetable_filename);
05360         
05361         if (dispersion_relation != NULL) {
05362             if (trace_id > 0) {
05363                 check( *dispersion_relation = 
05364                        uves_polynomial_convert_from_plist_midas(midas_header,
05365                                                                 "REGR", trace_id),
05366                        "Error reading polynomial 'REGR%d' from '%s'",
05367                        trace_id,
05368                        *linetable_filename);
05369             }
05370             else {
05371                 check( *dispersion_relation = 
05372                        uves_polynomial_convert_from_plist_midas(midas_header,
05373                                                                 "REGR", -1),
05374                        "Error reading polynomial 'REGR' from '%s'",
05375                        *linetable_filename);
05376             }
05377         }
05378         
05379     
05380       check( absolute_order_local = 
05381              uves_polynomial_convert_from_plist_midas(midas_header, "RORD",-1),
05382              "Error reading polynomial 'RORD' from '%s'", *linetable_filename);
05383       
05384       /* For FLAMES data, it seems that the polynomial is half an order shifted
05385          (for unknown reasons) */
05386         if (flames)
05387             {
05388                 check_nomsg( uves_polynomial_shift(absolute_order_local, 0, 0.5) );
05389             }
05390     }
05391     else
05392     /* CPL format */
05393     {
05394         /* physmod + wavecal recipes use different naming conventions,
05395            workaround for this:
05396         */
05397         if (cpl_table_has_column(*linetable, "YNEW"))
05398         {
05399             cpl_table_name_column(*linetable, "YNEW", "Ynew");
05400         }
05401 
05402         if (dispersion_relation != NULL)
05403         {
05404             check( *dispersion_relation = load_polynomial(
05405                    *linetable_filename,
05406                    base_extension + UVES_LINE_TABLE_EXTENSION_DISPERSION),
05407                "Could not read polynomial from extension %d of file '%s'", 
05408                base_extension + UVES_LINE_TABLE_EXTENSION_DISPERSION,
05409                *linetable_filename);
05410         }
05411 
05412         check( absolute_order_local =
05413            load_polynomial(*linetable_filename, 
05414                    base_extension + UVES_LINE_TABLE_EXTENSION_ABSORDER),
05415            "Could not read polynomial from extension %d of file '%s'",
05416            base_extension + UVES_LINE_TABLE_EXTENSION_ABSORDER, *linetable_filename);
05417     }
05418         
05419     if (absolute_order != NULL)
05420     {
05421         *absolute_order = uves_polynomial_duplicate(absolute_order_local);
05422     }
05423     
05424 
05425     check( align_order_line_table(
05426            *linetable, absolute_order_local, linetable_header, 
05427            order_locations, minorder, maxorder),
05428        "Error while aligning line/order tables");
05429 
05430 
05431     /* Remove all other columns than 'Ident', 'Order', 'X', 'Pixelsize' */
05432     {
05433     const char *colname;
05434 
05435     /* Loop through all columns */
05436 
05437     /* It is undefined behaviour (for a reason!) to loop through
05438        columns while deleting some of them. Therefore, copy the
05439        structure of the linetable to another (empty) table */
05440     
05441     uves_free_table(&temp);
05442     check(( temp = cpl_table_new(0),
05443         cpl_table_copy_structure(temp, *linetable)),
05444            "Error duplicating line table column structure");
05445     
05446     colname = cpl_table_get_column_name(temp);
05447     while (colname != NULL)
05448         {
05449         if (!(strcmp(colname, "X"        ) == 0 ||
05450               strcmp(colname, "Order"    ) == 0 ||
05451               strcmp(colname, "Ident"    ) == 0 ||
05452           strcmp(colname, "FIBRE"    ) == 0 ||
05453           strcmp(colname, "Fibre"    ) == 0 ||
05454               strcmp(colname, LINETAB_PIXELSIZE) == 0))
05455             {
05456             cpl_table_erase_column(*linetable, colname);
05457             uves_msg_debug("Removing unused column '%s'", colname);
05458             }
05459         
05460         /* Call with NULL argument to get the next column name */
05461         colname = cpl_table_get_column_name(NULL);
05462         }
05463     }
05464     
05465     /* support MIDAS
05466      * Calculate 'Pixel' column (lower case) for MIDAS tables 
05467      */
05468     if ( !cpl_table_has_column(*linetable, LINETAB_PIXELSIZE) )
05469     {
05470         check( create_column_pixelsize(*linetable),
05471            "Error adding 'Pixelsize' column");
05472     }
05473 
05474     /* Remove un-identified lines (where Ident = invalid or Ident = zero) ... */
05475     check( uves_erase_invalid_table_rows(*linetable, "Ident"),
05476        "Error deleting rows with illegal 'Ident' value");
05477 
05478     check( uves_erase_table_rows(*linetable, "Ident", CPL_LESS_THAN, 0.01),
05479        "Error deleting rows with illegal 'Ident' value");
05480     
05481     /* Check for any other invalid value */
05482     assure( uves_erase_invalid_table_rows(*linetable, NULL) == 0, CPL_ERROR_ILLEGAL_INPUT,
05483         "After deleting rows with invalid 'Ident' values, "
05484         "the table in extension %d of file '%s' still contains invalid rows",
05485         base_extension + UVES_LINE_TABLE_EXTENSION, *linetable_filename);
05486     
05487     /* Sort line table by 'Order' (ascending), then 'X' (ascending) */
05488     check( uves_sort_table_2(*linetable, "Order", "X", false, false), "Error sorting line table");
05489     
05490   cleanup:
05491     uves_free_propertylist(&primary_header);
05492     uves_free_propertylist(&header);
05493     uves_free_propertylist(&midas_header);
05494     uves_free_table(&temp);
05495     uves_polynomial_delete(&absolute_order_local);
05496     cpl_free(absorders);
05497     if (cpl_error_get_code() != CPL_ERROR_NONE) {
05498     *linetable_filename = NULL;
05499     uves_free_table(linetable);
05500     if (dispersion_relation != NULL) uves_polynomial_delete(dispersion_relation);
05501     if (absolute_order      != NULL) uves_polynomial_delete(absolute_order);
05502     }
05503     return;
05504 }
05505 
05506 /*----------------------------------------------------------------------------*/
05510 /*----------------------------------------------------------------------------*/
05511 void
05512 uves_load_linetable_const(const cpl_frameset *frames, 
05513                           bool flames,
05514                           const char *chip_name,
05515                           const polynomial *order_locations, int minorder, int maxorder,
05516                           const char **linetable_filename,
05517                           const cpl_table **linetable,
05518                           const uves_propertylist **linetable_header,
05519                           const polynomial **dispersion_relation,
05520                           polynomial **absolute_order,
05521                           enum uves_chip chip, int trace_id, int window)
05522 {
05523     uves_load_linetable(frames, flames, chip_name, order_locations, 
05524                         minorder, maxorder, 
05525                         linetable_filename, 
05526                         (cpl_table **)linetable, 
05527                         (uves_propertylist **)linetable_header,
05528                         (polynomial **)dispersion_relation, 
05529                         absolute_order,
05530                         chip, trace_id, window);
05531 }
05532 
05533 
05534 
05535 /*----------------------------------------------------------------------------*/
05550 /*----------------------------------------------------------------------------*/
05551 
05552 cpl_error_code
05553 uves_load_response_curve(const cpl_frameset *frames, const char *chip_name,
05554              const char **response_filename, 
05555              cpl_image **response_curve,
05556              cpl_table **master_response,
05557              uves_propertylist **response_header, enum uves_chip chip)
05558 {
05559     const char *tags[2];
05560     int number_of_tags = sizeof(tags) / sizeof(char *);
05561     int extension;
05562     int indx;
05563     
05564     *response_curve  = NULL;
05565     *response_header = NULL;
05566     *master_response = NULL;
05567     
05568     tags[0]   = UVES_INSTR_RESPONSE (chip);
05569     tags[1]   = UVES_MASTER_RESPONSE(chip);
05570     
05571     check( *response_filename = uves_find_frame(frames, tags, number_of_tags, &indx, 
05572                         NULL), 
05573        "Could not find '%s' in frame set", tags[0]);
05574 
05575  
05576     if (indx == 0)
05577     {
05578         extension = UVES_INSTR_RESPONSE_EXTENSION(chip);
05579         
05580         /* Load the response image
05581            
05582         Note: Even if the response curve was saved as
05583         a FITS file with NAXIS=1, cpl_image_load() will
05584         create an image of size nx1, which is just
05585         what we want
05586         */
05587         check( *response_curve = uves_load_image_file(*response_filename,
05588                                                       /* CPL_TYPE_DOUBLE,  Convert to this type */
05589                             0,               /* plane number */
05590                                                       extension,        /* Extension number */
05591                             
05592 response_header
05593                ),
05594            "Could not load response curve from extension %d of file '%s'", 
05595            extension, *response_filename);
05596 
05597         /* Load the header */
05598 /*
05599         check( *response_header = uves_propertylist_load(*response_filename,
05600                                 extension),
05601            "Could not load header from extension %d of file '%s'", 
05602            extension, *response_filename);
05603 */
05604         check_nomsg( uves_warn_if_chip_names_dont_match(*response_header, chip_name, chip) );
05605     }
05606     else
05607     /* Master response */
05608     {
05609         extension = UVES_MASTER_RESPONSE_EXTENSION(chip);
05610         
05611         check( *master_response = cpl_table_load(*response_filename,
05612                              UVES_LINE_INTMON_TABLE_EXTENSION,
05613                              1),   /* Mark identified 
05614                                   invalid values? (1=yes) */
05615            "Error master response curve from extension %d of file '%s'", 
05616            extension, *response_filename);           
05617 
05618         /* Convert columns to double */
05619         check(( cpl_table_cast_column(*master_response, "LAMBDA", "LAMBDA_double", 
05620                       CPL_TYPE_DOUBLE),
05621             cpl_table_erase_column(*master_response, "LAMBDA"),
05622             cpl_table_name_column(*master_response, "LAMBDA_double", "LAMBDA")),
05623           "Could not cast column 'LAMBDA'");
05624 
05625         check(( cpl_table_cast_column(*master_response, "FLUX_CONV", "FLUX_CONV_double", 
05626                       CPL_TYPE_DOUBLE),
05627             cpl_table_erase_column(*master_response, "FLUX_CONV"),
05628             cpl_table_name_column(*master_response, "FLUX_CONV_double", "FLUX_CONV")),
05629           "Could not cast column 'FLUX_CONV'");
05630 
05631         /* Do not need the header, which also does not contain 
05632            keywords needed for uves_warn_if_chip_names_dont_match() */
05633     }
05634     
05635   cleanup:
05636     if (cpl_error_get_code() != CPL_ERROR_NONE) 
05637     {
05638         *response_filename = NULL;
05639         uves_free_image(response_curve);
05640         uves_free_propertylist(response_header);
05641     }
05642     return cpl_error_get_code();
05643 }
05644 
05645 
05646 /*----------------------------------------------------------------------------*/
05656 /*----------------------------------------------------------------------------*/
05657 cpl_error_code uves_load_lineintmon(const cpl_frameset *frames, 
05658                     const char **line_intmon_filename, 
05659                     cpl_table **line_intmon)
05660 {
05661     const char *tags[1] = {UVES_LINE_INTMON_TABLE};    
05662 
05663     int number_of_tags = sizeof(tags) / sizeof(char *);
05664     int indx;
05665     
05666     /* Get filename */
05667     check( *line_intmon_filename = uves_find_frame(frames, tags, number_of_tags, 
05668                            &indx, NULL),
05669        "No line intensity table (%s) found in SOF", tags[0]);
05670     
05671     /* Load table */
05672     check( *line_intmon = cpl_table_load(*line_intmon_filename,
05673                      UVES_LINE_INTMON_TABLE_EXTENSION,
05674                      1),         /* Mark identified 
05675                             invalid values? (1=yes) */
05676        "Error loading line reference table from extension %d of file '%s'", 
05677        UVES_LINE_INTMON_TABLE_EXTENSION, *line_intmon_filename);
05678 
05679     check(( cpl_table_cast_column(*line_intmon, "WAVE", "Wave", CPL_TYPE_DOUBLE),
05680         cpl_table_erase_column(*line_intmon, "WAVE")),
05681       "Could not cast and rename column");
05682     
05683     /* Sort table by 'Wave' (ascending) */
05684     check(  uves_sort_table_1(*line_intmon, "Wave", false), "Error sorting table");
05685     
05686   cleanup:
05687     if (cpl_error_get_code() != CPL_ERROR_NONE) 
05688     {
05689         *line_intmon_filename = NULL;
05690         uves_free_table(line_intmon);
05691     }
05692     return cpl_error_get_code();
05693 }
05694 
05695 
05696 /*----------------------------------------------------------------------------*/
05708 /*----------------------------------------------------------------------------*/
05709 void
05710 uves_load_corvel(const cpl_frameset *frames,
05711          cpl_table **corvel,
05712          uves_propertylist **corvel_header,
05713          const char **corvel_filename)
05714 {
05715     const char *tags[1];
05716     int number_of_tags = sizeof(tags) / sizeof(char *);
05717     int indx;
05718     int extension;
05719 
05720     tags[0] = FLAMES_CORVEL_MASK;
05721 
05722     assure_nomsg( corvel != NULL, CPL_ERROR_NULL_INPUT );
05723     assure_nomsg( corvel_filename != NULL, CPL_ERROR_NULL_INPUT );
05724 
05725     /* Get filename */
05726     check( *corvel_filename = uves_find_frame(frames, tags, number_of_tags, 
05727                           &indx, NULL),
05728        "No velocity correction table (%s) found in SOF", tags[0]);
05729     
05730     /* Load table */
05731     extension = 1;
05732     check( *corvel = cpl_table_load(*corvel_filename,
05733                     extension,
05734                     1),         /* Mark identified 
05735                            invalid values? (1=yes) */
05736        "Error loading line reference table from extension %d of file '%s'",
05737        extension, *corvel_filename);
05738 
05739     /* Load header */
05740     if (corvel_header != NULL)
05741     {
05742         extension = 0;
05743         check( *corvel_header = uves_propertylist_load(*corvel_filename,
05744                               extension),
05745            "Could not load header from extension %d of file %s",
05746            extension, *corvel_filename);
05747 
05748     }
05749     
05750   cleanup:
05751     if (cpl_error_get_code() != CPL_ERROR_NONE) 
05752     {
05753         *corvel_filename = NULL;
05754         uves_free_table(corvel);
05755     }
05756     return;
05757 }
05758 
05759 /*----------------------------------------------------------------------------*/
05775 /*----------------------------------------------------------------------------*/
05776 cpl_error_code
05777 uves_load_linerefertable(const cpl_frameset *frames, 
05778              const char **line_refer_filename, 
05779              cpl_table **line_refer, uves_propertylist **line_refer_header)
05780 {
05781     const char *tags[1] = {UVES_LINE_REFER_TABLE};    
05782 
05783     int number_of_tags = sizeof(tags) / sizeof(char *);
05784     int indx;
05785     
05786     /* Get filename */
05787     check( *line_refer_filename = uves_find_frame(frames, tags, number_of_tags, 
05788                           &indx, NULL),
05789        "No line reference table (%s) found in SOF", tags[0]);
05790     
05791     /* Load table */
05792     check( *line_refer = cpl_table_load(*line_refer_filename,
05793                        UVES_LINE_REFER_TABLE_EXTENSION,
05794                        1),         /* Mark identified 
05795                               invalid values? (1=yes) */
05796        "Error loading line reference table from extension %d of file '%s'", 
05797        UVES_LINE_REFER_TABLE_EXTENSION, *line_refer_filename);
05798 
05799     /* Load header if requested */
05800     if (line_refer_header != NULL)
05801     {
05802         check( *line_refer_header = uves_propertylist_load(*line_refer_filename, 0),
05803            "Could not load header of line_refer table in '%s'", *line_refer_filename);
05804     }
05805 
05806     assure( uves_erase_invalid_table_rows(*line_refer, NULL) == 0, CPL_ERROR_ILLEGAL_INPUT,
05807         "Table in extension %d of file '%s' contains invalid rows", 
05808         UVES_LINE_REFER_TABLE_EXTENSION, *line_refer_filename);
05809 
05810     check(( cpl_table_cast_column(*line_refer, "WAVE", "Wave", CPL_TYPE_DOUBLE),
05811         cpl_table_erase_column(*line_refer, "WAVE")),
05812        "Could not cast and rename column");
05813     
05814     /* Write uncertainties of wavelengths.
05815        The value 0.002 is finetuned/retro-fitted to get a chi_sq ~ 1 when
05816        using the new catalogue from
05817 
05818        M. T. Murphy, P. Tzanavaris, J. K. Webb, C. Lovis
05819        "Selection of ThAr lines for wavelength calibration of echelle
05820        spectra and implications for variations in the fine-structure constant",
05821        Submitted to MNRAS
05822     */
05823 
05824 #if 0
05825      check(( cpl_table_duplicate_column(*line_refer, "dWave", *line_refer, "Wave"),
05826            cpl_table_divide_scalar   (*line_refer, "dWave", 300000*10)),
05827        "Error writing wavelength uncertainties");
05828 #else
05829      /* we should do this */
05830     check(( cpl_table_new_column(*line_refer, "dWave", CPL_TYPE_DOUBLE),
05831             cpl_table_fill_column_window(*line_refer,
05832                                          "dWave",
05833                                          0,
05834                                          cpl_table_get_nrow(*line_refer), 0.002)),
05835           "Error writing wavelength uncertainties");
05836 #endif
05837     
05838     /* Sort table by 'Wave' (ascending) */
05839     check(  uves_sort_table_1(*line_refer, "Wave", false), "Error sorting table");
05840     
05841   cleanup:
05842     if (cpl_error_get_code() != CPL_ERROR_NONE) {
05843     *line_refer_filename = NULL;
05844     uves_free_table       (line_refer);
05845     if (line_refer_header != NULL) uves_free_propertylist(line_refer_header);
05846     }
05847     return cpl_error_get_code();
05848 }
05849 
05850 /*----------------------------------------------------------------------------*/
05864 /*----------------------------------------------------------------------------*/
05865 cpl_error_code
05866 uves_load_flux_table(const cpl_frameset *frames, const char **flux_table_filename, 
05867              cpl_table **flux_table)
05868 {
05869     const char *tags[1] = {UVES_FLUX_STD_TABLE};
05870 
05871     int number_of_tags = sizeof(tags) / sizeof(char *);
05872     int indx;
05873     
05874     /* Get filename */
05875     check( *flux_table_filename = uves_find_frame(frames, tags, number_of_tags, 
05876                           &indx, NULL), 
05877        "No standard star flux table (%s) in SOF", tags[0]);
05878 
05879     /* Load table */
05880     check( *flux_table = cpl_table_load(*flux_table_filename,
05881                     UVES_FLUX_STD_TABLE_EXTENSION,
05882                     1),         /* Mark identified 
05883                                invalid values? (1=yes) */
05884        "Error loading flux table from extension %d of file '%s'",
05885        UVES_FLUX_STD_TABLE_EXTENSION, *flux_table_filename);
05886 
05887     if (false)
05888         /* Don't do this, it will remove one std (LTT2415) from the table which has TYPE = NULL.
05889            Instead, set type to "NULL" (this is only used for messages) 
05890         */
05891         {
05892             if (uves_erase_invalid_table_rows(*flux_table, NULL) != 0)
05893                 {
05894                     uves_msg_warning("Table in extension %d of file '%s' contains null values",
05895                                      UVES_FLUX_STD_TABLE_EXTENSION, *flux_table_filename);
05896                 }
05897         }
05898     else
05899         {
05900             int i;
05901             for (i = 0; i < cpl_table_get_nrow(*flux_table); i++)
05902                 {
05903                     if (cpl_table_get_string(*flux_table, "TYPE", i) == NULL)
05904                         {
05905                             cpl_table_set_string(*flux_table, "TYPE", i, "NULL");
05906                         }
05907                 }
05908         }
05909     
05910         
05911   cleanup:
05912     if (cpl_error_get_code() != CPL_ERROR_NONE) 
05913     {
05914         *flux_table_filename = NULL;
05915         uves_free_table(flux_table);
05916     }
05917     return cpl_error_get_code();
05918 }
05919 
05920 
05921 /*----------------------------------------------------------------------------*/
05935 /*----------------------------------------------------------------------------*/
05936 cpl_error_code
05937 uves_load_atmo_ext(const cpl_frameset *frames, const char **atmext_table_filename, 
05938            cpl_table **atmext_table)
05939 {
05940     const char *tags[1] = {UVES_EXTCOEFF_TABLE};
05941     
05942     int number_of_tags = sizeof(tags) / sizeof(char *);
05943     int indx;
05944     
05945     /* Get filename */
05946     check( *atmext_table_filename = uves_find_frame(frames, tags, number_of_tags, 
05947                             &indx, NULL), 
05948        "No atmospheric extinction table (%s) found in SOF", tags[0]);
05949 
05950     /* Load table */
05951     check( *atmext_table = cpl_table_load(*atmext_table_filename,
05952                       UVES_EXTCOEFF_TABLE_EXTENSION,
05953                       1),          /* Mark identified 
05954                               invalid values? (1=yes) */
05955        "Error loading atmospheric extinction table from extension %d of file '%s'",
05956        UVES_EXTCOEFF_TABLE_EXTENSION, *atmext_table_filename);
05957     
05958     assure( uves_erase_invalid_table_rows(*atmext_table, NULL) == 0, CPL_ERROR_ILLEGAL_INPUT,
05959         "Table in extension %d of file '%s' contains invalid rows",
05960         UVES_EXTCOEFF_TABLE_EXTENSION, *atmext_table_filename);
05961     
05962     check( uves_sort_table_1(*atmext_table, "LAMBDA", false),
05963        "Error sorting table");
05964     
05965     /* Convert columns to double */
05966     check(( cpl_table_cast_column(*atmext_table, "LAMBDA", "LAMBDA_double", CPL_TYPE_DOUBLE),
05967         cpl_table_erase_column(*atmext_table, "LAMBDA"),
05968         cpl_table_name_column(*atmext_table, "LAMBDA_double", "LAMBDA")),
05969       "Could not cast column 'LAMBDA'");
05970     
05971     check(( cpl_table_cast_column(*atmext_table, "LA_SILLA", "LA_SILLA_double", CPL_TYPE_DOUBLE),
05972         cpl_table_erase_column(*atmext_table, "LA_SILLA"),
05973         cpl_table_name_column(*atmext_table, "LA_SILLA_double", "LA_SILLA")),
05974       "Could not cast column 'LA_SILLA'");
05975     
05976   cleanup:
05977     if (cpl_error_get_code() != CPL_ERROR_NONE) 
05978     {
05979         *atmext_table_filename = NULL;
05980         uves_free_table(atmext_table);
05981     }
05982     return cpl_error_get_code();
05983 }
05984 /*----------------------------------------------------------------------------*/
05992 /*----------------------------------------------------------------------------*/
05993 char *
05994 uves_guess_order_table_filename(enum uves_chip chip) 
05995 {
05996     return uves_local_filename("orderguesstable", chip, -1, -1);
05997 }
05998 
05999 /*----------------------------------------------------------------------------*/
06007 /*----------------------------------------------------------------------------*/
06008 char *
06009 uves_order_table_filename(enum uves_chip chip) 
06010 {
06011     return uves_local_filename("ordertable", chip, -1, -1);
06012 }
06013 
06014 /*----------------------------------------------------------------------------*/
06021 /*----------------------------------------------------------------------------*/
06022 char *uves_ordef_filename(enum uves_chip chip)
06023 {
06024     return uves_local_filename("order_def", chip, -1, -1);
06025 }
06026 
06027 /*----------------------------------------------------------------------------*/
06035 /*----------------------------------------------------------------------------*/
06036 char *
06037 uves_masterdark_filename(enum uves_chip chip) 
06038 {
06039     return uves_local_filename("masterdark", chip, -1, -1);
06040 }
06041 
06042 
06043 /*----------------------------------------------------------------------------*/
06049 /*----------------------------------------------------------------------------*/
06050 char *
06051 uves_flat_ratio_filename(enum uves_chip chip) 
06052 {
06053     return uves_local_filename("ratio", chip, -1, -1);
06054 }
06055 
06056 /*----------------------------------------------------------------------------*/
06063 /*----------------------------------------------------------------------------*/
06064 char *uves_cd_align_filename(enum uves_chip chip)
06065 {
06066     return uves_local_filename("cd_align", chip, -1, -1);
06067 }
06068 
06069 /*----------------------------------------------------------------------------*/
06077 /*----------------------------------------------------------------------------*/
06078 char *
06079 uves_masterflat_filename(enum uves_chip chip) 
06080 {
06081     return uves_local_filename("masterflat", chip, -1, -1);
06082 }
06083 /*----------------------------------------------------------------------------*/
06091 /*----------------------------------------------------------------------------*/
06092 char *
06093 uves_masterflat_bkg_filename(enum uves_chip chip) 
06094 {
06095     return uves_local_filename("masterflat_bkg", chip, -1, -1);
06096 }
06097 
06098 /*----------------------------------------------------------------------------*/
06106 /*----------------------------------------------------------------------------*/
06107 char *
06108 uves_masterbias_filename(enum uves_chip chip) 
06109 {
06110     return uves_local_filename("masterbias", chip, -1, -1);
06111 }
06112 
06113 /*----------------------------------------------------------------------------*/
06121 /*----------------------------------------------------------------------------*/
06122 char *
06123 uves_guess_line_table_filename(enum uves_chip chip)
06124 {
06125     return uves_local_filename("lineguesstable", chip, -1, -1);
06126 }
06127 /*----------------------------------------------------------------------------*/
06135 /*----------------------------------------------------------------------------*/
06136 char *
06137 uves_line_table_filename(enum uves_chip chip)
06138 {
06139     return uves_local_filename("linetable", chip, -1, -1);
06140 }
06141 
06142 /*----------------------------------------------------------------------------*/
06150 /*----------------------------------------------------------------------------*/
06151 char *
06152 uves_line_table_filename_paf(enum uves_chip chip)
06153 {
06154     return uves_local_filename("linetable_paf", chip, -1, -1);
06155 }
06156 
06157 /*----------------------------------------------------------------------------*/
06165 /*----------------------------------------------------------------------------*/
06166 char *
06167 uves_response_curve_filename(enum uves_chip chip)
06168 {
06169     return uves_local_filename("response", chip, -1, -1);
06170 }
06171 
06172 /*----------------------------------------------------------------------------*/
06180 /*----------------------------------------------------------------------------*/
06181 char *
06182 uves_response_curve_2d_filename(enum uves_chip chip)
06183 {
06184     return uves_local_filename("response_2d", chip, -1, -1);
06185 }
06186 
06187 /*----------------------------------------------------------------------------*/
06195 /*----------------------------------------------------------------------------*/
06196 char *
06197 uves_response_red_standard_filename(enum uves_chip chip)
06198 {
06199     return uves_local_filename("red_std", chip, -1, -1);
06200 }
06201 
06202 
06203 /*----------------------------------------------------------------------------*/
06211 /*----------------------------------------------------------------------------*/
06212 char *
06213 uves_response_red_noappend_standard_filename(enum uves_chip chip)
06214 {
06215     return uves_local_filename("red_nonmerged", chip, -1, -1);
06216 }
06217 
06218 /*----------------------------------------------------------------------------*/
06226 /*----------------------------------------------------------------------------*/
06227 char *
06228 uves_response_bkg_standard_filename(enum uves_chip chip)
06229 {
06230     return uves_local_filename("bkg_std", chip, -1, -1);
06231 }
06232 
06233 
06234 /*----------------------------------------------------------------------------*/
06242 /*----------------------------------------------------------------------------*/
06243 char *
06244 uves_order_extract_qc_standard_filename(enum uves_chip chip)
06245 {
06246     return uves_local_filename("order_extract_qc", chip, -1, -1);
06247 }
06248 
06249 /*----------------------------------------------------------------------------*/
06257 /*----------------------------------------------------------------------------*/
06258 char *
06259 uves_response_efficiency_filename(enum uves_chip chip)
06260 {
06261     return uves_local_filename("efficiency", chip, -1, -1);
06262 }
06263 
06264 /*----------------------------------------------------------------------------*/
06272 /*----------------------------------------------------------------------------*/
06273 
06274 char *
06275 uves_scired_red_2d_science_filename(enum uves_chip chip)
06276 {
06277     return uves_local_filename("red_2d_science", chip, -1, -1);
06278 }
06279 
06287 /*----------------------------------------------------------------------------*/
06288 
06289 
06290 
06291 char *
06292 uves_scired_red_science_filename(enum uves_chip chip)
06293 {
06294     return uves_local_filename("red_science", chip, -1, -1);
06295 }
06303 /*----------------------------------------------------------------------------*/
06304 
06305 
06306 
06307 char *
06308 uves_scired_red_noappend_science_filename(enum uves_chip chip)
06309 {
06310     return uves_local_filename("red_nonmerged_science", chip, -1, -1);
06311 }
06312 /*----------------------------------------------------------------------------*/
06320 /*----------------------------------------------------------------------------*/
06321 char *
06322 uves_scired_red_error_filename(enum uves_chip chip)
06323 {
06324     return uves_local_filename("error_red_science", chip, -1, -1);
06325 }
06326 
06327 /*----------------------------------------------------------------------------*/
06335 /*----------------------------------------------------------------------------*/
06336 char *
06337 uves_scired_red_noappend_error_filename(enum uves_chip chip)
06338 {
06339     return uves_local_filename("error_red_nonmerged_science", chip, -1, -1);
06340 }
06341 
06342 /*----------------------------------------------------------------------------*/
06350 /*----------------------------------------------------------------------------*/
06351 char *
06352 uves_scired_red_2d_error_filename(enum uves_chip chip)
06353 {
06354     return uves_local_filename("error_2d_science", chip, -1, -1);
06355 }
06356 
06357 
06358 /*----------------------------------------------------------------------------*/
06366 /*----------------------------------------------------------------------------*/
06367 char *
06368 uves_scired_fluxcal_science_filename(enum uves_chip chip)
06369 {
06370     return uves_local_filename("fluxcal_science", chip, -1, -1);
06371 }
06372 
06373 
06374 /*----------------------------------------------------------------------------*/
06382 /*----------------------------------------------------------------------------*/
06383 char *
06384 uves_scired_fluxcal_science_noappend_filename(enum uves_chip chip)
06385 {
06386     return uves_local_filename("fluxcal_nonmerged_science", chip, -1, -1);
06387 }
06388 /*----------------------------------------------------------------------------*/
06396 /*----------------------------------------------------------------------------*/
06397 char *
06398 uves_scired_fluxcal_error_filename(enum uves_chip chip)
06399 {
06400     return uves_local_filename("fluxcal_error_science", chip, -1, -1);
06401 }
06402 
06403 
06404 /*----------------------------------------------------------------------------*/
06412 /*----------------------------------------------------------------------------*/
06413 char *
06414 uves_scired_fluxcal_error_noappend_filename(enum uves_chip chip)
06415 {
06416     return uves_local_filename("fluxcal_error_nonmerged_science", chip, -1, -1);
06417 }
06418 
06419 
06420 
06428 /*----------------------------------------------------------------------------*/
06429 char *
06430 uves_scired_fluxcal_science_2d_filename(enum uves_chip chip)
06431 {
06432     return uves_local_filename("fluxcal_2d_science", chip, -1, -1);
06433 }
06434 /*----------------------------------------------------------------------------*/
06442 /*----------------------------------------------------------------------------*/
06443 char *
06444 uves_scired_fluxcal_error_2d_filename(enum uves_chip chip)
06445 {
06446     return uves_local_filename("fluxcal_error_2d_science", chip, -1, -1);
06447 }
06448 /*----------------------------------------------------------------------------*/
06456 /*----------------------------------------------------------------------------*/
06457 char *
06458 uves_scired_ff_variance_filename(enum uves_chip chip)
06459 {
06460     return uves_local_filename("variance_ff_science", chip, -1, -1);
06461 }
06462 
06463 /*----------------------------------------------------------------------------*/
06471 /*----------------------------------------------------------------------------*/
06472 char *
06473 uves_scired_ff_variance_2d_filename(enum uves_chip chip)
06474 {
06475     return uves_local_filename("variance_ff_2d_science", chip, -1, -1);
06476 }
06477 
06478 /*----------------------------------------------------------------------------*/
06485 /*----------------------------------------------------------------------------*/
06486 char *
06487 uves_scired_merged_2d_science_filename(enum uves_chip chip)
06488 {
06489     return uves_local_filename("merged_2d_science", chip, -1, -1);
06490 }
06491 
06499 /*----------------------------------------------------------------------------*/
06500 char *
06501 uves_scired_merged_science_filename(enum uves_chip chip)
06502 {
06503     return uves_local_filename("merged_science", chip, -1, -1);
06504 }
06505 /*----------------------------------------------------------------------------*/
06513 /*----------------------------------------------------------------------------*/
06514 char *
06515 uves_scired_merged_sky_filename(enum uves_chip chip)
06516 {
06517     return uves_local_filename("merged_sky", chip, -1, -1);
06518 }
06519 
06520 /*----------------------------------------------------------------------------*/
06528 /*----------------------------------------------------------------------------*/
06529 char *
06530 uves_scired_background_filename(enum uves_chip chip)
06531 {
06532     return uves_local_filename("background", chip, -1, -1);
06533 }
06534 
06535 /*----------------------------------------------------------------------------*/
06543 /*----------------------------------------------------------------------------*/
06544 char *
06545 uves_scired_resampled_filename(enum uves_chip chip)
06546 {
06547     return uves_local_filename("resampled_science", chip, -1, -1);
06548 }
06549 
06550 
06551 
06552 /*----------------------------------------------------------------------------*/
06560 /*----------------------------------------------------------------------------*/
06561 char *
06562 uves_scired_resampled_2d_filename(enum uves_chip chip)
06563 {
06564     return uves_local_filename("resampled_2d_science", chip, -1, -1);
06565 }
06566 
06567 
06568 /*----------------------------------------------------------------------------*/
06576 /*----------------------------------------------------------------------------*/
06577 char *
06578 uves_scired_resampledmf_filename(enum uves_chip chip)
06579 {
06580     return uves_local_filename("resampled_mflat", chip, -1, -1);
06581 }
06582 
06583 /*----------------------------------------------------------------------------*/
06592 /*----------------------------------------------------------------------------*/
06593 char *
06594 uves_scired_rebinned_filename(enum uves_chip chip)
06595 {
06596     return uves_local_filename("resampled_ff_science", chip, -1, -1);
06597 }
06598 
06599 
06608 /*----------------------------------------------------------------------------*/
06609 char *
06610 uves_scired_rebinned_2d_filename(enum uves_chip chip)
06611 {
06612     return uves_local_filename("resampled_ff_2d_science", chip, -1, -1);
06613 }
06614 /*----------------------------------------------------------------------------*/
06622 /*----------------------------------------------------------------------------*/
06623 char *
06624 uves_scired_ordertrace_filename(enum uves_chip chip)
06625 {
06626     return uves_local_filename("ordertrace", chip, -1, -1);
06627 }
06628 
06629 /*----------------------------------------------------------------------------*/
06637 /*----------------------------------------------------------------------------*/
06638 char *
06639 uves_scired_crmask_filename(enum uves_chip chip)
06640 {
06641     return uves_local_filename("cr_mask", chip, -1, -1);
06642 }
06643 
06644 /*----------------------------------------------------------------------------*/
06652 /*----------------------------------------------------------------------------*/
06653 char *
06654 uves_scired_wmap_filename(enum uves_chip chip)
06655 {
06656     return uves_local_filename("wave_map", chip, -1, -1);
06657 }
06658 
06659 /*----------------------------------------------------------------------------*/
06667 /*----------------------------------------------------------------------------*/
06668 char *uves_scired_ext2d_filename(enum uves_chip chip)
06669 {
06670     return uves_local_filename("ext_2d_science", chip, -1, -1);
06671 }
06672 
06673 /*----------------------------------------------------------------------------*/
06681 /*----------------------------------------------------------------------------*/
06682 char *uves_scired_ff2d_filename(enum uves_chip chip)
06683 {
06684     return uves_local_filename("ff_2d_science", chip, -1, -1);
06685 }
06686 
06687 /*----------------------------------------------------------------------------*/
06708 /*----------------------------------------------------------------------------*/
06709 char *
06710 uves_local_filename(const char *prefix, enum uves_chip chip, int trace, int window)
06711 {
06712     char *result = NULL;
06713     const char *chip_string;
06714     const char *suffix = ".fits";     /* Always */
06715     char *t = NULL;
06716     char *w = NULL;
06717 
06718     assure( (trace < 0 && window < 0) ||           /* Empty suffix          */
06719         (trace < 0 && window > 0) ||           /* Window only suffix    */
06720         (trace >= 0 && window > 0),            /* Trace & window suffix */
06721         CPL_ERROR_ILLEGAL_INPUT, "Illegal trace and window numbers: (%d, %d)", 
06722         trace, window);
06723 
06724     /* Chip */
06725     chip_string = uves_chip_tostring_lower(chip);
06726     
06727     /* Trace and window number (possibly empty string) */
06728     check(( t = int_to_string(trace),
06729         w = int_to_string(window)),
06730           "Error creating substrings");
06731 
06732 /* old code:
06733     result = cpl_calloc(strlen(prefix) + 1 + 
06734             strlen(chip_string) + strlen(t) + strlen(w) + strlen(suffix) + 1,
06735             sizeof(char));
06736     
06737     assure_mem( result );
06738     
06739     strcpy(result, prefix);
06740     strcat(result, "_");
06741     strcat(result, chip_string);
06742     strcat(result, t);
06743     strcat(result, w);
06744     strcat(result, suffix);
06745 */
06746     result = uves_sprintf("%s_%s%s%s%s", prefix, chip_string, t, w, suffix);
06747     assure_mem( result );
06748 
06749   cleanup:
06750     cpl_free(t);
06751     cpl_free(w);
06752     if (cpl_error_get_code() != CPL_ERROR_NONE)
06753     {
06754         cpl_free(result); result = NULL;
06755     }
06756     return result;
06757 }
06758 
06759 /*----------------------------------------------------------------------------*/
06770 /*----------------------------------------------------------------------------*/
06771 static char *
06772 int_to_string(int i)
06773 {
06774     char *result = NULL;
06775 
06776     assure( -1 <= i, CPL_ERROR_ILLEGAL_INPUT, "Illegal number (%d)", i);
06777 
06778     if (i == -1)
06779     {
06780         /* Empty string */
06781         result = cpl_calloc(1, sizeof(char));
06782         assure_mem( result );
06783     }
06784     else
06785     {
06786         result = uves_sprintf("_%d", i);
06787     }
06788     
06789   cleanup:
06790     if (cpl_error_get_code() != CPL_ERROR_NONE){
06791     cpl_free(result); result = NULL;
06792     }
06793     return result;
06794 }
06795 
06796 
06797 /*----------------------------------------------------------------------------*/
06807 /*----------------------------------------------------------------------------*/
06808 
06809 cpl_image*
06810 uves_vector_to_image(const cpl_vector* vector,cpl_type type)
06811 {
06812   int i=0;
06813   cpl_image* image=NULL;
06814   int size=0;
06815   const double* pv=NULL;
06816   int* pi=NULL;
06817   float* pf=NULL;
06818   double* pd=NULL;
06819 
06820 
06821       size=cpl_vector_get_size(vector);
06822       image=cpl_image_new(size,1,type);
06823       pv=cpl_vector_get_data_const(vector);
06824       if(type == CPL_TYPE_INT) {
06825         pi=cpl_image_get_data_int(image);
06826         for(i=0;i<size;i++) {
06827       pi[i]=pv[i];
06828     }
06829       } else if (type == CPL_TYPE_FLOAT) {
06830         pf=cpl_image_get_data_float(image);
06831         for(i=0;i<size;i++) {
06832       pf[i]=pv[i];
06833     }
06834       } else if (type == CPL_TYPE_DOUBLE) {
06835         pd=cpl_image_get_data_double(image);
06836         for(i=0;i<size;i++) {
06837       pd[i]=pv[i];
06838     }
06839       } else {
06840         assure( false, CPL_ERROR_INVALID_TYPE,
06841             "No CPL type to represent BITPIX = %d", type);
06842       }
06843 
06844  cleanup:
06845     if (cpl_error_get_code() != CPL_ERROR_NONE){
06846       uves_free_image(&image);
06847     }
06848 
06849     return image;
06850 
06851 }

Generated on 28 Feb 2012 for UVES Pipeline Reference Manual by  doxygen 1.6.1