uves_dfs.c

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

Generated on 9 Mar 2012 for UVES Pipeline Reference Manual by  doxygen 1.6.1