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

Generated on 8 Mar 2011 for UVES Pipeline Reference Manual by  doxygen 1.6.1