flames_midas_def.c

00001 
00002 /*                                                                              *
00003  *   This file is part of the ESO UVES Pipeline                                 *
00004  *   Copyright (C) 2004,2005 European Southern Observatory                      *
00005  *                                                                              *
00006  *   This library is free software; you can redistribute it and/or modify       *
00007  *   it under the terms of the GNU General Public License as published by       *
00008  *   the Free Software Foundation; either version 2 of the License, or          *
00009  *   (at your option) any later version.                                        *
00010  *                                                                              *
00011  *   This program is distributed in the hope that it will be useful,            *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of             *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
00014  *   GNU General Public License for more details.                               *
00015  *                                                                              *
00016  *   You should have received a copy of the GNU General Public License          *
00017  *   along with this program; if not, write to the Free Software                *
00018  *   Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA  *
00019  *                                                                              */
00020 
00021 /*
00022  * $Author: amodigli $
00023  * $Date: 2013/02/12 10:59:25 $
00024  * $Revision: 1.8 $
00025  * $Name: HEAD $
00026  * $Log: flames_midas_def.c,v $
00027  * Revision 1.8  2013/02/12 10:59:25  amodigli
00028  * added assert
00029  *
00030  * Revision 1.7  2012/11/19 09:16:16  jtaylor
00031  * replace all (u)long ints with (u)int32_t in flames
00032  *
00033  * except the fitsio arguments in load_frame() from uves/flames_midas_def.c
00034  * the rest of uves is unchanged
00035  * (uves/uves_deque.c must not be changed for compatibility with cpl)
00036  *
00037  * required for 64 bit compatibility
00038  * the midas fits io does not support 8 byte long integers.
00039  * longs are 4 byte on 32 bit and 8 byte on 64 bit so the simplest fix is
00040  * to replace them all with the size which is known to work.
00041  * An alternative would be to check and fix all io related functions
00042  * this would require adding a 4 byte integer tensor
00043  *
00044  * Revision 1.6  2012/11/19 09:11:52  jtaylor
00045  * fix segfauls with -O0
00046  *
00047  * Revision 1.5  2012/03/02 16:23:15  amodigli
00048  * fixed compiler warnings related to CPL6 upgrade
00049  *
00050  * Revision 1.4  2011/12/08 13:58:29  amodigli
00051  * Fox warnings with CPL6
00052  *
00053  * Revision 1.3  2010/09/24 09:32:02  amodigli
00054  * put back QFITS dependency to fix problem spot by NRI on FIBER mode (with MIDAS calibs) data
00055  *
00056  * Revision 1.1  2009/04/14 07:01:07  amodigli
00057  * added to CVS (moded from flames tree)
00058  *
00059  * Revision 1.73  2008/09/29 06:50:32  amodigli
00060  * add #include <string.h>
00061  *
00062  * Revision 1.72  2008/08/29 09:54:04  amodigli
00063  * fixed compiler warning
00064  *
00065  * Revision 1.71  2008/06/26 08:21:58  amodigli
00066  * more silend init/end of MIDAS interface
00067  *
00068  * Revision 1.70  2007/12/10 07:33:52  amodigli
00069  * added support of D_R8_FORMAT
00070  *
00071  * Revision 1.69  2007/10/23 06:44:19  amodigli
00072  * fixed compilation warnings
00073  *
00074  * Revision 1.68  2007/10/01 17:19:34  amodigli
00075  * added scdprs
00076  *
00077  * Revision 1.67  2007/08/30 08:44:16  amodigli
00078  * fixed problem with null strings in convert_to_history and problems with a lengh of a cards in get_descr_info
00079  *
00080  * Revision 1.66  2007/08/21 13:08:25  jmlarsen
00081  * Removed irplib_access module, largely deprecated by CPL-4
00082  *
00083  * Revision 1.65  2007/08/20 08:56:49  amodigli
00084  * fixed bug on termination null char in flames_midas_sckgetc
00085  *
00086  * Revision 1.64  2007/08/16 06:58:09  amodigli
00087  * commented out assure check in flames_convert_to_history to prevent problem with slitff_l_sigma01 and CPL4: was that assure really needed?
00088  *
00089  * Revision 1.63  2007/08/08 08:00:29  amodigli
00090  * update frame_new_table to support input in '.tfits'
00091  *
00092  * Revision 1.62  2007/07/27 06:44:48  amodigli
00093  * Moved several function declarations from flames_uves.h to other new .h files
00094  *
00095  * Revision 1.61  2007/07/26 16:08:28  jmlarsen
00096  * Manually set table column unit to empty string when no unit is given. CPL-3 did that. CPL-4 not
00097  *
00098  * Revision 1.60  2007/07/25 15:55:12  amodigli
00099  * fixed a problem writing char descriptors not null ternimated evidenced with CPL4
00100  *
00101  * Revision 1.59  2007/07/18 15:27:17  jmlarsen
00102  * Added check for NULL pointer
00103  *
00104  * Revision 1.58  2007/07/03 14:04:48  jmlarsen
00105  * Fixed fixmes
00106  *
00107  * Revision 1.57  2007/06/28 09:34:43  jmlarsen
00108  * More useful error message
00109  *
00110  * Revision 1.56  2007/06/26 13:58:07  jmlarsen
00111  * Expand list of special MIDAS keywords
00112  *
00113  * Revision 1.55  2007/06/25 15:45:33  jmlarsen
00114  * Do not write FIBRESON to HISTORY keyword
00115  *
00116  * Revision 1.54  2007/06/22 15:27:49  jmlarsen
00117  * Support read/write of D_I2_FORMAT
00118  *
00119  * Revision 1.53  2007/06/22 14:52:20  jmlarsen
00120  * Exported dtype_to_cpltype function
00121  *
00122  * Revision 1.52  2007/06/22 09:45:59  jmlarsen
00123  * Changed interface of uves_save_image
00124  *
00125  * Revision 1.51  2007/06/20 13:45:02  jmlarsen
00126  * Make sure not to convert some hardcoded FITS keywords to HISTORY format
00127  *
00128  * Revision 1.50  2007/06/20 11:10:46  jmlarsen
00129  * Use CFITSIO, also for 2d images
00130  *
00131  * Revision 1.49  2007/06/19 12:00:05  jmlarsen
00132  * Changed comment
00133  *
00134  * Revision 1.48  2007/06/12 15:19:07  jmlarsen
00135  * Added support for writing CUNIT
00136  *
00137  * Revision 1.47  2007/06/08 15:37:53  jmlarsen
00138  * Bugfix in SCDWR when creating new descriptor
00139  *
00140  * Revision 1.46  2007/06/08 06:41:23  amodigli
00141  * cleaned output
00142  *
00143  * Revision 1.45  2007/06/06 15:28:38  jmlarsen
00144  * And made it compile
00145  *
00146  * Revision 1.44  2007/06/06 15:14:52  jmlarsen
00147  * Fixed memory error
00148  *
00149  * Revision 1.43  2007/06/06 14:05:13  jmlarsen
00150  * SCCADD return value of OBJECT if existing
00151  *
00152  * Revision 1.42  2007/06/06 08:17:33  amodigli
00153  * replace tab with 4 spaces
00154  *
00155  * Revision 1.41  2007/06/06 07:23:59  jmlarsen
00156  * Use property comments to control conversion to/from HISTORY keywords
00157  *
00158  * Revision 1.40  2007/06/05 06:53:54  jmlarsen
00159  * Fixed buffer overrun in SCDRDC
00160  *
00161  * Revision 1.39  2007/06/04 17:08:20  amodigli
00162  * removed compilation warnings
00163  *
00164  * Revision 1.38  2007/06/04 11:26:42  jmlarsen
00165  * Added SCKGETC_fsp for cpl_frameset pointers
00166  *
00167  * Revision 1.37  2007/06/04 06:34:22  amodigli
00168  * added CPL_TYPE_FLOAT support in convert_to_history
00169  *
00170  * Revision 1.36  2007/05/30 16:07:53  jmlarsen
00171  * Support reading 3d, 4d FITS images
00172  *
00173  * Revision 1.35  2007/05/30 14:49:02  jmlarsen
00174  * Support for 3d, 4d FITS images
00175  *
00176  * Revision 1.34  2007/05/29 14:39:48  jmlarsen
00177  * Readded 3d table functions but map them to simple (2d) table functions
00178  *
00179  * Revision 1.33  2007/05/29 13:46:21  jmlarsen
00180  * Removed 3d table column stubs which were not needed for FLAMES
00181  *
00182  * Revision 1.32  2007/05/18 15:41:24  amodigli
00183  * added some info
00184  *
00185  * Revision 1.31  2007/05/16 15:43:39  jmlarsen
00186  * Initial support for 3d images
00187  *
00188  * Revision 1.30  2007/05/16 14:21:52  amodigli
00189  * added debug statements
00190  *
00191  * Revision 1.29  2007/05/16 10:08:38  jmlarsen
00192  * Added .fits to provided filenames if not given
00193  *
00194  * Revision 1.28  2007/05/14 16:13:57  jmlarsen
00195  * Fixed memory leak
00196  *
00197  * Revision 1.27  2007/05/14 16:04:52  jmlarsen
00198  * Bugfix in SCKRD functions
00199  *
00200  * Revision 1.26  2007/05/14 13:25:31  jmlarsen
00201  * Added support for 'allocated' table rows
00202  *
00203  * Revision 1.25  2007/05/11 13:52:48  jmlarsen
00204  * Implemented image buffer read/write functions
00205  *
00206  * Revision 1.24  2007/05/11 09:41:38  jmlarsen
00207  * Support type double in convert_to_history
00208  *
00209  * Revision 1.23  2007/05/10 14:03:15  jmlarsen
00210  * Added workaround for CPL's TNULL handling
00211  *
00212  * Revision 1.22  2007/05/08 14:26:17  jmlarsen
00213  * Implemented table selection flags
00214  *
00215  * Revision 1.21  2007/05/04 14:45:32  amodigli
00216  * added support for D_I1_FORMAT
00217  *
00218  * Revision 1.20  2007/05/04 10:21:13  jmlarsen
00219  * Set image size properly in SCDCOP
00220  *
00221  * Revision 1.19  2007/04/24 12:49:34  jmlarsen
00222  * Replaced cpl_propertylist -> uves_propertylist which is much faster
00223  *
00224  * Revision 1.18  2007/04/24 09:43:10  jmlarsen
00225  * Renamed uves_propertylist_append -> uves_propertylist_append_property
00226  *
00227  * Revision 1.17  2007/04/23 07:01:10  amodigli
00228  * uncommented BKG_XY_WIN_SZ_X BKG_XY_WIN_SZ_Y BKG_MAX_IO_WIN
00229  *
00230  * Revision 1.16  2007/04/20 14:53:29  jmlarsen
00231  * Allow type conversion in table read/write functions
00232  *
00233  * Revision 1.15  2007/04/16 06:50:37  jmlarsen
00234  * Fixed memory leaks
00235  *
00236  * Revision 1.14  2007/04/10 07:31:35  jmlarsen
00237  * Fixed buffer overrun due to use of strcpy
00238  *
00239  * Revision 1.13  2007/04/03 11:05:31  jmlarsen
00240  * Implemented table module
00241  *
00242  * Revision 1.12  2007/03/23 14:11:49  jmlarsen
00243  * Replaced exit system calls with appropriate error handling
00244  *
00245  * Revision 1.11  2007/03/23 13:44:37  jmlarsen
00246  * Implemented SCKWR- functions
00247  *
00248  * Revision 1.10  2007/03/23 10:25:32  amodigli
00249  * implemented sccadd
00250  *
00251  * Revision 1.9  2007/03/23 10:10:14  jmlarsen
00252  * Implemented catalog interface
00253  *
00254  * Revision 1.8  2007/03/23 08:04:55  jmlarsen
00255  * Work on conversion
00256  *
00257  * Revision 1.7  2007/03/15 15:05:33  jmlarsen
00258  * More implementation
00259  *
00260  * Revision 1.6  2007/03/05 09:40:53  jmlarsen
00261  * Work on SCDCOP
00262  *
00263  * Revision 1.5  2007/02/27 14:09:31  jmlarsen
00264  * Extended interface of uves_find_property
00265  *
00266  * Revision 1.4  2007/01/31 13:14:54  jmlarsen
00267  * Initial implementation of SCFGET
00268  *
00269  * Revision 1.3  2007/01/29 13:09:55  jmlarsen
00270  * Work on conversion to CPL
00271  *
00272  * Revision 1.2  2007/01/15 14:00:23  jmlarsen
00273  * Imported FLAMES sources from MIDAS pipeline
00274  *
00275  * Revision 1.1  2007/01/10 08:06:10  jmlarsen
00276  * Added source files
00277  *
00278  * Revision 1.2  2006/12/01 12:52:31  jmlarsen
00279  * Added flames_pfits module
00280  *
00281  * Revision 1.1  2006/10/20 06:42:09  jmlarsen
00282  * Moved FLAMES source to flames directory
00283  *
00284  * Revision 1.114  2006/10/09 13:03:09  jmlarsen
00285  * Removed explicit uves_msg_softer/louder calls
00286  *
00287  */
00288 
00289 #ifdef HAVE_CONFIG_H
00290 #  include <config.h>
00291 #endif
00292 
00293 /*----------------------------------------------------------------------------*/
00313 /*----------------------------------------------------------------------------*/
00314 
00315 /*-----------------------------------------------------------------------------
00316                             Includes
00317  -----------------------------------------------------------------------------*/
00318 #include <flames_midas_def.h>
00319 
00320 #include <uves_utils_cpl.h>
00321 #include <uves_dfs.h>
00322 #include <uves_dump.h>
00323 #include <uves_utils_wrappers.h>
00324 #include <uves_error.h>
00325 
00326 #include <uves_msg.h>
00327 #include <uves_pfits.h>
00328 #include <assert.h>
00329 
00330 #include <fitsio.h>
00331 #include <string.h>
00332 #include <errno.h>
00333 /*-----------------------------------------------------------------------------
00334                             Defines
00335  -----------------------------------------------------------------------------*/
00336 
00337 #define MAX_OPEN 1024 /* Maximum number of open images/tables files */
00338 
00340 /*-----------------------------------------------------------------------------
00341                             Functions prototypes
00342  -----------------------------------------------------------------------------*/
00343 /*-----------------------------------------------------------------------------
00344                             Variables
00345  -----------------------------------------------------------------------------*/
00346 
00347 struct frame
00348 {
00349     const char *filename;      /* NULL: slot not used */
00350 
00351     bool is_image;             /* Image or table? */
00352     union {
00353         struct {
00354             cpl_image *image;  
00355             cpl_type type;   /* CPL type of image (cannot store this in
00356                                 the CPL image structure, because the image may
00357                                 be logically open before it is actually loaded
00358                                 into memory) */
00359             int dtype;       /* MIDAS image type */
00360         } image;
00361         struct {
00362             cpl_table *table;  /* The actual table columns *and* an
00363                                   'internal' column "Select" to record
00364                                   selections */
00365             cpl_table *colnames;
00366             int maxrow;        /* Number of rows actually used
00367                                   (maybe be less than rows allocated) */
00368         } table;
00369     } data;
00370 
00371     uves_propertylist *header;  /* Primary header, also for tables.
00372                                   NULL: not loaded (yet) */
00373     bool need_to_save;         /* Need to save to disk when closing? */
00374 
00375     /* Invariants:
00376        if need_to_save, then image/table is != NULL
00377        For images:
00378           if image != NULL, then cpl_image_get_type(image) = type 
00379        For tables:
00380           (table == NULL) == (colnames == NULL)
00381           if table != NULL, then table.ncol-1 == colnames.nrow
00382           if table != NULL, table has column "Select"
00383     */
00384 
00385 };
00386 
00387 #define COLNAME "ColName"
00388 
00389 /* There are 3(!) different representations of FITS headers
00390 
00391    1. As seen by the FLAMES code, e.g.
00392 
00393    LHCUTS[3]...
00394    LHCUTS[4]...
00395    ORDERLIM[1]...
00396    ORDERLIM[2]...
00397    ESO OBS ID...
00398 
00399    2. CPL propertylist
00400    
00401    DATAMIN...
00402    DATAMAX...
00403    ORDERLIM = x
00404    ORDERLIM = y
00405    ESO OBS ID...
00406 
00407    3. The actual FITS file
00408    
00409    DATAMIN...
00410    DATAMAX...
00411    HISTORY ORDERLIM 
00412    HISTORY x y
00413    HISTORY
00414    HIERARCH ESO OBS ID...
00415 
00416 */
00417 
00418 struct frame frames[MAX_OPEN];
00419 const char *current_caller = NULL;
00420 
00421 /*-----------------------------------------------------------------------------
00422                             Implementation
00423  -----------------------------------------------------------------------------*/
00424 /*----------------------------------------------------------------------------*/
00437 /*----------------------------------------------------------------------------*/
00438 
00439 static bool invariant(int id)
00440 {
00441     struct frame *frm = &frames[id];
00442 
00443     if (frm->is_image)
00444         {
00445             return
00446                 (!frm->need_to_save || frm->data.image.image != NULL) &&
00447                 (frm->data.image.image == NULL
00448                  || cpl_image_get_type(frm->data.image.image) == frm->data.image.type);
00449         }
00450     else
00451         {
00452             return (!frm->need_to_save || frm->data.table.table != NULL)
00453                 &&
00454                 ((frm->data.table.table == NULL) == (frm->data.table.colnames == NULL))
00455                 &&
00456                 (frm->data.table.table == NULL || 
00457                  cpl_table_get_ncol(frm->data.table.table) - 1 ==
00458                  cpl_table_get_nrow(frm->data.table.colnames)) 
00459                 &&
00460                 (frm->data.table.table == NULL || 
00461                  cpl_table_has_column(frm->data.table.table, "Select"));
00462 
00463         }
00464 }
00465 /*----------------------------------------------------------------------------*/
00470 /*----------------------------------------------------------------------------*/
00471 static bool
00472 frame_is_open(int id)
00473 {
00474     return frames[id].filename != NULL;
00475 }
00476 
00477 /*----------------------------------------------------------------------------*/
00483 /*----------------------------------------------------------------------------*/
00484 static void 
00485 frame_new_image(int id, const char *filename, 
00486                 uves_propertylist *header,
00487                 bool need_to_save,
00488                 cpl_image *image,
00489                 cpl_type type,
00490                 int dtype)
00491 {
00492     if (strstr(filename, ".fits") == filename + strlen(filename) - 5) {
00493         frames[id].filename = uves_sprintf("%s", filename);
00494     } 
00495     else if (strstr(filename, ".bdf") == filename + strlen(filename) - 4) {
00496         /* Replace .bdf -> .fits */
00497         frames[id].filename = uves_sprintf("%sX", filename);
00498         ((char *)frames[id].filename)[strlen(filename) - 3] = 'f';
00499         ((char *)frames[id].filename)[strlen(filename) - 2] = 'i';
00500         ((char *)frames[id].filename)[strlen(filename) - 1] = 't';
00501         ((char *)frames[id].filename)[strlen(filename) - 0] = 's';
00502     }
00503     else {
00504         frames[id].filename = uves_sprintf("%s.fits", filename);
00505     }
00506     frames[id].is_image = true;
00507     frames[id].data.image.image = image;
00508     frames[id].data.image.type  = type;
00509     frames[id].data.image.dtype = dtype;
00510     frames[id].header = header;
00511     frames[id].need_to_save = need_to_save;
00512 
00513     return;
00514 }
00515 /*----------------------------------------------------------------------------*/
00521 /*----------------------------------------------------------------------------*/
00522 static void 
00523 frame_new_table(int id, const char *filename, 
00524                 uves_propertylist *header,
00525                 bool need_to_save,
00526                 cpl_table *table,
00527                 int maxrow,
00528                 cpl_table *colnames)
00529 {
00530     if (strstr(filename, ".fits") == filename + strlen(filename) - 5) {
00531         frames[id].filename = uves_sprintf("%s", filename);
00532     } 
00533     else if (strstr(filename, ".tfits") == filename + strlen(filename) - 6) {
00534         frames[id].filename = uves_sprintf("%s", filename);
00535     } 
00536     else if (strstr(filename, ".tbl") == filename + strlen(filename) - 4) {
00537         /* Replace .tbl -> .fits */
00538         frames[id].filename = uves_sprintf("%sX", filename);
00539         ((char *)frames[id].filename)[strlen(filename) - 3] = 'f';
00540         ((char *)frames[id].filename)[strlen(filename) - 2] = 'i';
00541         ((char *)frames[id].filename)[strlen(filename) - 1] = 't';
00542         ((char *)frames[id].filename)[strlen(filename) - 0] = 's';
00543     } else {
00544         frames[id].filename = uves_sprintf("%s.fits", filename);
00545     }
00546     frames[id].is_image = false;
00547     frames[id].data.table.table = table;
00548     if (table != NULL) {
00549         cpl_table_new_column(table, "Select", CPL_TYPE_INT);
00550         cpl_table_fill_column_window_int(table, "Select",
00551                                          0, cpl_table_get_nrow(table),
00552                                          1); /* initialize to all selected */
00553     }
00554     else {
00555         /* Select column will be created when table is loaded from disk */
00556     }
00557     frames[id].data.table.maxrow = maxrow;
00558     frames[id].data.table.colnames = colnames;
00559     frames[id].header = header;
00560     frames[id].need_to_save = need_to_save;
00561     return;
00562 }
00563 
00564 /*----------------------------------------------------------------------------*/
00570 /*----------------------------------------------------------------------------*/
00571 static void 
00572 frame_free(int id)
00573 {
00574     if (frame_is_open(id))
00575         {
00576             uves_free_string_const(&frames[id].filename);
00577             if (frames[id].is_image)
00578                 {
00579                     uves_free_image(&frames[id].data.image.image);
00580                 }
00581             else
00582                 {
00583                     uves_free_table(&frames[id].data.table.table);
00584                     uves_free_table(&frames[id].data.table.colnames);
00585                 }
00586             uves_free_propertylist(&frames[id].header);
00587         }
00588 }
00589 
00590 /*----------------------------------------------------------------------------*/
00596 /*----------------------------------------------------------------------------*/
00597 static bool
00598 is_special_midas_descr(const char *descr)
00599 {
00600     return 
00601         strcmp(descr, "NPIX") == 0 ||
00602         strcmp(descr, "REFPIX") == 0 ||
00603         strcmp(descr, "START") == 0 ||
00604         strcmp(descr, "STEP") == 0 ||
00605         strcmp(descr, "ROTA") == 0 ||
00606         strcmp(descr, "CUNIT") == 0 ||
00607         strcmp(descr, "IDENT") == 0 ||
00608         strcmp(descr, "O_TIME") == 0 ||
00609         strcmp(descr, "LHCUTS") == 0 ||
00610         strcmp(descr, "O_POS") == 0;
00611 }
00612 
00613 /*----------------------------------------------------------------------------*/
00621 /*----------------------------------------------------------------------------*/
00622 static const char *
00623 convert_to_fits(const char *descr, int indx)
00624 {
00625     /* Special MIDAS keywords are:
00626        (MIDAS manual volume A p. 7-5)    
00627        NAXISn -> NPIXn
00628        CRPIXn -> REFPIXn
00629        CRVALn -> STARTn
00630        CDELTn -> STEPn
00631        CROTAn -> ROTAn
00632        BUNIT  -> CUNIT(1)
00633        CTYPEn -> CUNIT(n+1)
00634        OBJECT -> IDENT
00635        DATE_OBS -> O_TIME(1)
00636 
00637                   LHCUTS(1), LHCUTS(2)
00638           internal in MIDAS,
00639           not converted
00640        DATAMIN -> LHCUTS(3)       (and convert double -> float)
00641        DATAMAX -> LHCUTS(4)
00642        EPOCH   -> O_POS(3)
00643        EQUINOX -> O_POS(3)
00644     */
00645 
00646     const char *fits_descr = NULL;
00647     if      (strcmp(descr, "NPIX"  ) == 0) fits_descr = uves_sprintf("NAXIS%d", indx);
00648     else if (strcmp(descr, "REFPIX") == 0) assure( false, CPL_ERROR_UNSUPPORTED_MODE, "%s", descr);
00649     else if (strcmp(descr, "START" ) == 0) fits_descr = uves_sprintf("CRVAL%d", indx);
00650     else if (strcmp(descr, "STEP"  ) == 0) fits_descr = uves_sprintf("CDELT%d", indx);
00651     else if (strcmp(descr, "ROTA"  ) == 0) assure( false, CPL_ERROR_UNSUPPORTED_MODE, "%s", descr);
00652     else if (strcmp(descr, "CUNIT" ) == 0) 
00653         fits_descr = (indx == 1) ? uves_sprintf("BUNIT") : uves_sprintf("CTYPE%d", indx);
00654     else if (strcmp(descr, "IDENT" ) == 0) fits_descr = uves_sprintf("OBJECT");
00655     else if (strcmp(descr, "O_TIME") == 0) assure( false, CPL_ERROR_UNSUPPORTED_MODE, "%s", descr);
00656     else if (strcmp(descr, "LHCUTS") == 0) 
00657     {
00658         fits_descr = 
00659         (indx == 1) ? uves_sprintf("LHCUTS1") :    /* For now, write these keywords for indx 1,2 */
00660         (indx == 2) ? uves_sprintf("LHCUTS2") :
00661         (indx == 3) ? uves_sprintf("DATAMIN") : uves_sprintf("DATAMAX");
00662     }
00663     else if (strcmp(descr, "O_POS" ) == 0) assure( false, CPL_ERROR_UNSUPPORTED_MODE, "%s", descr);
00664         
00665     if (fits_descr == NULL)
00666     {
00667         fits_descr = uves_sprintf("%s", descr);
00668     }
00669 
00670   cleanup:
00671     return fits_descr;
00672 }
00673 
00674 /*----------------------------------------------------------------------------*/
00699 /*----------------------------------------------------------------------------*/
00700 static void
00701 convert_to_history(uves_propertylist **header)
00702 {
00703     int plist_size, i;
00704     const char *new_name  = NULL;
00705     char *v = NULL;
00706     cpl_table *new_values = NULL;
00707     cpl_property *new_prop = NULL;
00708     uves_propertylist *result = NULL;  /* Cannot change type of one property,
00709                                          need to copy to new list */
00710     result = uves_propertylist_new();
00711 
00712     plist_size = uves_propertylist_get_size(*header);
00713     for (i = 0; i < plist_size; i++) {
00714         cpl_property *p = uves_propertylist_get(*header, i);
00715         const char *name = cpl_property_get_name(p);
00716         int j;
00717 
00718         if (cpl_property_get_comment(p) != NULL &&
00719             strcmp(cpl_property_get_comment(p), "PROCESSED") == 0) {
00720             /* already processed, ignore */
00721         }
00722         else if ((strlen(name) > 8 && strncmp(name, "ESO ", 4) != 0) 
00723                  ||
00724                  (cpl_property_get_comment(p) != NULL &&
00725                   strcmp(cpl_property_get_comment(p), "MIDAS_DESC") == 0)) {
00726 
00727             int n_prop;
00728             
00729             uves_free_string_const(&new_name);
00730             switch (cpl_property_get_type(p)) {
00731             case CPL_TYPE_STRING:
00732                 new_name = uves_sprintf("'%s','C'", name);
00733                 break;
00734             case CPL_TYPE_INT:
00735                 new_name = uves_sprintf("'%s','I'", name);
00736                 break;
00737             case CPL_TYPE_FLOAT:
00738                 new_name = uves_sprintf("'%s','R*4'", name);
00739                 break;
00740             case CPL_TYPE_DOUBLE:
00741                 new_name = uves_sprintf("'%s','R*8'", name);
00742                 break;
00743             default:
00744                 assure(false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me %s %s", name,
00745                        uves_tostring_cpl_type(cpl_property_get_type(p)));
00746                 break;
00747             }
00748 
00749             uves_free_table(&new_values);
00750             new_values = cpl_table_new(2);
00751             cpl_table_new_column(new_values, "Val", CPL_TYPE_STRING);
00752             n_prop = 0;
00753             
00754             /* And collect this and any subsequent properties with same name */
00755             for (j = i; j < plist_size; j++) {
00756           cpl_property *p2;
00757 
00758           check_nomsg( p2 = uves_propertylist_get(*header, j) );
00759                 if (strcmp(cpl_property_get_name(p2), name) == 0) {
00760                     uves_msg_debug("Found %s", name);
00761 
00762                     /* Here, we would like to remove p2 from the list
00763                        in order not to process it again, but uves_propertylists
00764                        don't support that */
00765                     cpl_property_set_comment(p2, "PROCESSED");
00766             
00767                     assure( cpl_property_get_type(p2) == cpl_property_get_type(p),
00768                             CPL_ERROR_TYPE_MISMATCH,
00769                             "Found property %s with type %s and with type %s",
00770                             name, 
00771                             uves_tostring_cpl_type(cpl_property_get_type(p)),
00772                             uves_tostring_cpl_type(cpl_property_get_type(p2)));
00773             
00774                     uves_free_string(&v);
00775                     switch (cpl_property_get_type(p2)) {
00776                     case CPL_TYPE_STRING:
00777                       if(strlen(cpl_property_get_string(p2)) > 0) {
00778                         v = uves_sprintf("%s", cpl_property_get_string(p2));
00779               } else {
00780             uves_msg_debug("Empty string descriptor");
00781             v=cpl_malloc(1);
00782                         *v='\0';
00783               }
00784               break;
00785                     case CPL_TYPE_INT:
00786               v = uves_sprintf("%d", cpl_property_get_int(p2));
00787               break;
00788                     case CPL_TYPE_FLOAT:
00789                       v = uves_sprintf("%g", cpl_property_get_float(p2));
00790                       break;
00791                     case CPL_TYPE_DOUBLE:
00792                       v = uves_sprintf("%g", cpl_property_get_double(p2));
00793                       break;
00794                     default:
00795                       assure(false, CPL_ERROR_UNSUPPORTED_MODE, 
00796                              "Implement me %s %s", name,
00797                              uves_tostring_cpl_type(cpl_property_get_type(p2)));
00798                       break;
00799                     }
00800 
00801 
00802             assure(v != NULL, CPL_ERROR_UNSPECIFIED,"Allocation failure");
00803                     assure( strlen(v) <= 80 - strlen("HISTORY "),
00804                             CPL_ERROR_UNSUPPORTED_MODE,
00805                             "Value (%s) too long string",
00806                             v);
00807           
00808                  
00809 
00810                     /* Increase table size as necessary */
00811                     if (n_prop >= cpl_table_get_nrow(new_values))
00812                         {
00813                             cpl_table_set_size(new_values, 
00814                                                2*cpl_table_get_nrow(new_values));
00815                         }
00816                         
00817                     check_nomsg( cpl_table_set_string(new_values, "Val", n_prop, v) );
00818                     n_prop += 1;
00819                 }
00820             }
00821             cpl_table_set_size(new_values, n_prop);
00822 
00823             /* if (strcmp(name, "SIGMAFRAME") == 0) {
00824                cpl_table_dump(new_values, 0, cpl_table_get_nrow(new_values), stderr);
00825                uves_print_uves_propertylist(*header, 0, uves_propertylist_get_size(*header));
00826                } */
00827                         
00828             /* Convert to 1+n+1 HISTORY entries */
00829             uves_propertylist_append_string(result, "HISTORY", new_name);
00830             for (j = 0; j < cpl_table_get_nrow(new_values); j++)
00831                 {
00832                     uves_propertylist_append_string(result, "HISTORY",
00833                                                     cpl_table_get_string(new_values, "Val", j));
00834                 }
00835             uves_propertylist_append_string(result, "HISTORY", "");
00836 
00837 
00838         }
00839         else {
00840             uves_free_property(&new_prop);
00841             new_prop = cpl_property_duplicate(p);
00842             uves_propertylist_append_property(result, new_prop);
00843         }
00844 
00845     }
00846 
00847     uves_free_propertylist(header);
00848     *header = uves_propertylist_duplicate(result);
00849     
00850   cleanup:
00851     uves_free_string_const(&new_name);
00852     uves_free_string(&v);
00853     uves_free_table(&new_values);
00854     uves_free_property(&new_prop);
00855     uves_free_propertylist(&result);
00856     return;    
00857 }
00858 
00859 /*----------------------------------------------------------------------------*/
00879 /*----------------------------------------------------------------------------*/
00880 static uves_propertylist *
00881 load_header(const char *filename,
00882         int extension)
00883 {
00884     uves_propertylist *fitsheader = NULL;
00885     uves_propertylist *result = NULL;
00886     int plist_size, i;
00887     const char *new_name = NULL;
00888     const char *new_value = NULL;
00889 
00890     const char *desc_name = NULL;
00891     const void *values = NULL;
00892     
00893     check( fitsheader = uves_propertylist_load(filename, extension),
00894        "Could not load extension %d header from file %s", extension, filename);
00895 
00896     result = uves_propertylist_new();
00897     plist_size = uves_propertylist_get_size(fitsheader);
00898     for (i = 0; i < plist_size; i++) {
00899         cpl_property *p = uves_propertylist_get(fitsheader, i);
00900         const char *name = cpl_property_get_name(p);
00901         bool convert_from_midas = false;
00902         
00903         if (strcmp(name, "HISTORY") == 0)
00904             {
00905                 const char *value;
00906                 
00907                 if (cpl_property_get_type(p) == CPL_TYPE_STRING)
00908                     {
00909                         value = cpl_property_get_string(p);
00910                         
00911                         /* If a MIDAS descriptor is encoded here.
00912                            Must match "'.+'"
00913                         */
00914                         if ((int)strlen(value) >= 3 && 
00915                             value[0] == '\'' &&
00916                             strstr(value+2, "'") != NULL)
00917                             {
00918                                 /* Get descriptor name. */
00919                                 uves_free_string_const(&desc_name);
00920                                 desc_name = cpl_strdup(value+1);
00921                                 *(strstr(desc_name, "'")) = '\0';
00922                                 
00923                                 convert_from_midas = !is_special_midas_descr(desc_name);
00924                                 
00925                                 /* i.e. don't convert e.g
00926                                    HISTORY 'LHCUTS'
00927                                 */
00928                             }
00929                     }
00930                 else
00931                     {
00932                         uves_msg_warning("%s has HISTORY property of non-string type (%s)",
00933                                          filename, 
00934                                          uves_tostring_cpl_type(cpl_property_get_type(p)));
00935                     }
00936             }
00937         
00938         if (convert_from_midas) {
00939             int length, j;
00940             int ncards;
00941             cpl_type type;
00942             
00943             uves_free(values); values = NULL;
00944             check( values = 
00945                    uves_read_midas_array(fitsheader, desc_name, &length, &type,
00946                                          &ncards),
00947                    "Could not get values of HISTORY descriptor '%s'", desc_name);
00948             
00949             i += ncards-1;
00950             
00951             /* Create new properties */
00952             for (j = 0; j < ((type == CPL_TYPE_STRING) ? 1 : length); j++) {
00953 
00954                 uves_free_string_const(&new_name);
00955                 new_name = uves_sprintf("%s", desc_name);
00956                 
00957                 switch(type) {
00958                 case CPL_TYPE_INT:
00959                     uves_propertylist_append_c_int(result, new_name, ((int*)values)[j], "MIDAS_DESC");
00960                     break;
00961                 case CPL_TYPE_FLOAT:
00962                     uves_propertylist_append_c_float(result, new_name, ((float*)values)[j], "MIDAS_DESC");
00963                     break;
00964                 case CPL_TYPE_DOUBLE:
00965                     uves_propertylist_append_c_double(result, new_name, ((double*)values)[j], "MIDAS_DESC");
00966                     break;
00967                 case CPL_TYPE_STRING:
00968                     uves_propertylist_append_c_string(result, new_name, (char *)values, "MIDAS_DESC");
00969                     break;
00970                 default:
00971                     assure( false, CPL_ERROR_UNSUPPORTED_MODE,
00972                             "Type is %s", uves_tostring_cpl_type(type));
00973                 }
00974             }
00975         }
00976         else {
00977             uves_propertylist_append_property(result, p);
00978         }
00979     }
00980     
00981   cleanup:
00982     uves_free_string_const(&new_name);
00983     uves_free_string_const(&new_value);
00984     uves_free_string_const(&desc_name);
00985     uves_free_propertylist(&fitsheader);
00986     uves_free(values); values = NULL;
00987     if (cpl_error_get_code() != CPL_ERROR_NONE)
00988     {
00989         uves_free_propertylist(&result);
00990     }
00991     return result;
00992 
00993 }
00994 /*----------------------------------------------------------------------------*/
00999 /*----------------------------------------------------------------------------*/
01000 cpl_type
01001 flames_midas_image_dtype_to_cpltype(int dtype)
01002 {
01003     cpl_type type = CPL_TYPE_INVALID;
01004 
01005     switch(dtype) {
01006     case D_OLD_FORMAT: type = CPL_TYPE_FLOAT; break;
01007     case D_R4_FORMAT: type = CPL_TYPE_FLOAT; break;
01008     case D_R8_FORMAT: type = CPL_TYPE_DOUBLE; break;
01009     case D_I1_FORMAT: type = CPL_TYPE_INT; break;
01010     case D_I2_FORMAT: type = CPL_TYPE_INT; break;
01011     case D_I4_FORMAT: type = CPL_TYPE_INT; break;
01012     default:
01013         assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me %d",
01014                 dtype);
01015         break;
01016     }
01017 
01018   cleanup:
01019     return type;
01020 }
01021 /*----------------------------------------------------------------------------*/
01029 /*----------------------------------------------------------------------------*/
01030 
01031 static void
01032 load_frame_header(int id)
01033 {
01034     int extension = 0; /* For tables and images */
01035 
01036     passure( invariant(id), " ");
01037 
01038     passure( frame_is_open(id), " ");
01039 
01040     if (frames[id].header == NULL)
01041     {
01042             /* Convert MIDAS HISTORY descriptors to internal format */
01043             check( frames[id].header = load_header(frames[id].filename,
01044                                              extension),
01045                    "Error loading header from %s", frames[id].filename);
01046 
01047             uves_msg_debug("Loaded %s header (%ld FITS cards)",
01048                            frames[id].filename,
01049                            uves_propertylist_get_size(frames[id].header));
01050     }
01051     
01052     passure( invariant(id), " ");
01053 
01054   cleanup:
01055     return;
01056 }
01057 
01058 /*----------------------------------------------------------------------------*/
01066 /*----------------------------------------------------------------------------*/
01067 static void
01068 set_column_format_unit_tnull(cpl_table *t, const uves_propertylist *theader)
01069 {
01070     const char *colname;
01071 
01072     int tfield; /* number of columns */
01073     char *key_type = NULL;
01074     char *key_form = NULL;
01075     char *key_unit = NULL;
01076     char *key_null = NULL;
01077     char *val_type = NULL;
01078     char *val_form = NULL;
01079     char *val_unit = NULL;
01080     int val_null;
01081 
01082     check_nomsg( tfield = uves_propertylist_get_int(theader, "TFIELDS"));
01083 
01084     for(colname = cpl_table_get_column_name(t);
01085         colname != NULL;
01086         colname = cpl_table_get_column_name(NULL)) {
01087         bool found = false;
01088         int i;
01089         for (i = 1; i <= tfield && !found; i++) {
01090             uves_free_string(&key_type);
01091             uves_free_string(&key_form);
01092             uves_free_string(&key_unit);
01093             uves_free_string(&key_null);
01094             uves_free_string(&val_type);
01095             uves_free_string(&val_form);
01096             uves_free_string(&val_unit);
01097             key_type = uves_sprintf("TTYPE%d", i); /* column name */
01098             key_form = uves_sprintf("TFORM%d", i);
01099             key_unit = uves_sprintf("TUNIT%d", i);
01100             key_null = uves_sprintf("TNULL%d", i);
01101             
01102             /* remove trailing blanks */
01103             val_type = cpl_strdup(uves_propertylist_get_string(theader, key_type));
01104             if (strlen(val_type) > 0) {
01105                 while (val_type[strlen(val_type)-1] == ' ') {
01106                     val_type[strlen(val_type)-1] = '\0';
01107                 }
01108             }
01109             
01110             if (strcmp(val_type, colname) == 0)  {
01111                 found = true;
01112                 if (uves_propertylist_contains(theader, key_form))  {
01113                     val_form = cpl_strdup(uves_propertylist_get_string(theader, key_form));
01114                     if (strlen(val_form) > 0) {
01115                         while (val_form[strlen(val_form)-1] == ' ') {
01116                             val_form[strlen(val_form)-1] = '\0';
01117                         }
01118                     }
01119                     
01120                     cpl_table_set_column_format(t, colname, val_form);
01121                 }
01122                 if (uves_propertylist_contains(theader, key_unit))  {
01123                     val_unit = cpl_strdup(uves_propertylist_get_string(theader, key_unit));
01124                     if (strlen(val_unit) > 0) {
01125                         while (val_unit[strlen(val_unit)-1] == ' ') {
01126                             val_unit[strlen(val_unit)-1] = '\0';
01127                         }
01128                     }
01129                     
01130                     cpl_table_set_column_unit(t, colname, val_unit);
01131                 }
01132                 else {
01133                     /* FLAMES C code expects the unit to be always non-NULL,
01134                        therefore set it to an empty string. 
01135 
01136                        This was guaranteed by CPL-3.x which always wrote 
01137                        the TUNIT keyword when saving.
01138 
01139                        But with CPL-4, the TUNIT keyword is not always present.
01140                     */
01141                     cpl_table_set_column_unit(t, colname, "        ");
01142                 }
01143 
01144                 if (cpl_table_get_column_type(t, colname) == CPL_TYPE_INT &&
01145                     uves_propertylist_contains(theader, key_null))  {
01146                     val_null = uves_propertylist_get_int(theader, key_null);
01147 
01148                     cpl_table_fill_invalid_int(t, colname, val_null);
01149                 }
01150             }
01151         }
01152     }
01153     
01154   cleanup:
01155     uves_free_string(&key_type);
01156     uves_free_string(&key_form);
01157     uves_free_string(&key_unit);
01158     uves_free_string(&key_null);
01159     uves_free_string(&val_type);
01160     uves_free_string(&val_form);
01161     uves_free_string(&val_unit);
01162     return;
01163 }
01164 
01165 /*----------------------------------------------------------------------------*/
01171 /*----------------------------------------------------------------------------*/
01172 static void
01173 load_frame(int id)
01174 {
01175     uves_propertylist *theader = NULL;
01176     cpl_imagelist *ilist = NULL;
01177     fitsfile *fptr = NULL;
01178 
01179     /* doesn't have to hold here: passure( invariant(id), " "); */
01180     passure( frame_is_open(id), " ");
01181 
01182     if (frames[id].is_image) {
01183         if (frames[id].data.image.image == NULL) {
01184             long naxes[4];
01185             long firstpixel[4] = {1, 1, 1, 1};
01186             int naxis;
01187             int fio_status = 0;            
01188             
01189             uves_msg_debug("Loading image %s (type %s) to memory", 
01190                            frames[id].filename, 
01191                            uves_tostring_cpl_type(frames[id].data.image.type));
01192             
01193             /* Use CFITSIO. CPL doesn't handle 4d images */
01194 
01195             fits_open_file(&fptr, frames[id].filename, READONLY, &fio_status);
01196             
01197             assure( fio_status == 0, CPL_ERROR_FILE_IO,
01198                     "Failed to open %s for reading", frames[id].filename );
01199     
01200             /* Get the image dimension */
01201             fits_get_img_dim(fptr, &naxis, &fio_status);
01202             assure( naxis == 1 || naxis == 2 || naxis == 3 || naxis == 4,
01203                     CPL_ERROR_ILLEGAL_INPUT, "Illegal dimension: %d", naxis);
01204             
01205             /* Get the file size */
01206             naxes[0] = 1;
01207             naxes[1] = 1;
01208             naxes[2] = 1;
01209             naxes[3] = 1;
01210             fits_get_img_size(fptr, naxis, naxes, &fio_status);
01211             assure( fio_status == 0, CPL_ERROR_FILE_IO,
01212                     "Failed to get %s image size", frames[id].filename);
01213 
01214 
01215             frames[id].data.image.image = cpl_image_new(naxes[0] * naxes[1] * naxes[2] * naxes[3], 1,
01216                                                         frames[id].data.image.type);
01217 
01218             switch(frames[id].data.image.type) {
01219             case CPL_TYPE_DOUBLE:
01220                 fits_read_pix(fptr, TDOUBLE, firstpixel, naxes[0] * naxes[1] * naxes[2] * naxes[3],
01221                               NULL, cpl_image_get_data_double(frames[id].data.image.image),
01222                               NULL, &fio_status);
01223                 break;
01224             case CPL_TYPE_FLOAT:
01225                 fits_read_pix(fptr, TFLOAT, firstpixel, naxes[0] * naxes[1] * naxes[2] * naxes[3],
01226                               NULL, cpl_image_get_data_float(frames[id].data.image.image),
01227                               NULL, &fio_status);
01228                 break;
01229             case CPL_TYPE_INT:
01230                 fits_read_pix(fptr, TINT, firstpixel, naxes[0] * naxes[1] * naxes[2] * naxes[3],
01231                               NULL, cpl_image_get_data_int(frames[id].data.image.image),
01232                               NULL, &fio_status);
01233                 break;
01234             default:
01235                 assure( false, CPL_ERROR_INVALID_TYPE,
01236                         "Illegal type %s", uves_tostring_cpl_type(frames[id].data.image.type));
01237 
01238             }
01239             
01240             fits_close_file(fptr, &fio_status) ;
01241             assure( fio_status == 0, CPL_ERROR_FILE_IO,
01242                     "Failed to load image %s", frames[id].filename);
01243  
01244         }
01245     }
01246     else
01247         {
01248             if (frames[id].data.table.table == NULL)
01249                 {
01250                     int extension = 1;
01251                     int mark_invalid_values = 1; /* 1=yes */
01252                     const char *name;
01253                     int row;
01254 
01255                     uves_msg_debug("Loading table %s to memory", frames[id].filename);
01256 
01257                     check( frames[id].data.table.table = 
01258                            cpl_table_load(frames[id].filename,
01259                                           extension,
01260                                           mark_invalid_values),
01261                            "Error loading table from %s", frames[id].filename);
01262                     
01263                     if (!cpl_table_has_column(frames[id].data.table.table, "Select")) {
01264                         cpl_table_new_column(frames[id].data.table.table, "Select", 
01265                                              CPL_TYPE_INT);
01266                         cpl_table_fill_column_window_int(
01267                             frames[id].data.table.table, "Select",
01268                             0, cpl_table_get_nrow(frames[id].data.table.table),
01269                             1);
01270                     }
01271                     
01272                     frames[id].data.table.maxrow = cpl_table_get_nrow(frames[id].data.table.table);
01273 
01274                     check( theader = uves_propertylist_load(frames[id].filename, extension),
01275                            "Error loading table header from %s", frames[id].filename);
01276                     
01277                     /* Assign numbers to columns */
01278                     frames[id].data.table.colnames = 
01279                         cpl_table_new(cpl_table_get_ncol(frames[id].data.table.table) - 1);
01280                     cpl_table_new_column(frames[id].data.table.colnames, COLNAME, CPL_TYPE_STRING);
01281                     
01282                     for(name = cpl_table_get_column_name(frames[id].data.table.table), row = 0;
01283                         name != NULL;
01284                         name = cpl_table_get_column_name(NULL)) {
01285                         if (strcmp(name, "Select") != 0) {
01286                             cpl_table_set_string(frames[id].data.table.colnames, COLNAME, row, name);
01287                             row++;
01288                         }
01289                     }
01290                     
01291                     /* Workaround here: cpl_table_load ignores the table column
01292                        units/formats and TNULL, so read + set those manually */
01293                     check( set_column_format_unit_tnull(frames[id].data.table.table, theader),
01294                            "Error loading table %s format/units", frames[id].filename);
01295                 }
01296         }
01297     
01298     passure( invariant(id), " ");
01299            
01300   cleanup:
01301     uves_free_imagelist(&ilist);
01302     uves_free_propertylist(&theader);
01303     return;
01304 }
01305 
01306 /*----------------------------------------------------------------------------*/
01317 /*----------------------------------------------------------------------------*/
01318 static cpl_property **
01319 create_descr(uves_propertylist *header,
01320          const char *descr,
01321          char type, int length,
01322          int nexist)
01323 {
01324     const char *fits_descr = NULL;
01325     const char *previous_descr = NULL;
01326     cpl_property **cards = NULL;
01327     int i;
01328     cpl_property *new_prop = NULL;
01329 
01330     passure( header != NULL, " ");
01331     assure( length >= 1, CPL_ERROR_ILLEGAL_INPUT, "Length = %d", length);
01332 
01333     cards = cpl_malloc((length+1) * sizeof(cpl_property *));
01334 
01335     if (nexist > 0)
01336     {
01337         i = 0;
01338         check( previous_descr = convert_to_fits(descr, i + nexist),
01339            "Could not convert %s to FITS", descr);
01340     }
01341     else
01342     {
01343         previous_descr = uves_sprintf("----");
01344     }
01345 
01346     for (i = 1; i <= length; i++)
01347     {
01348             const char *comment;
01349 
01350             uves_free_string_const(&fits_descr);
01351             check( fits_descr = convert_to_fits(descr, i + nexist),
01352                    "Could not convert %s to FITS", descr);
01353 
01354             uves_msg_debug("Creating property %s (%d of %d, type = '%c')", fits_descr,
01355                            nexist + i, nexist + length, type);
01356 
01357             if (strcmp(descr, fits_descr) == 0 &&
01358                 strncmp(descr, "CTYPE", 5) != 0 &&
01359                 strncmp(descr, "CDELT", 5) != 0 &&
01360                 strncmp(descr, "CRVAL", 5) != 0 &&
01361                 strncmp(descr, "CRPIX", 5) != 0 &&
01362                 strncmp(descr, "ESO QC", 6) != 0 &&
01363                 strcmp(descr, "BUNIT") != 0 &&
01364                 strcmp(descr, "COLS") != 0 &&
01365                 strcmp(descr, "ROWS") != 0 &&
01366                 strcmp(descr, "PIXMAX") != 0 &&
01367                 strcmp(descr, "STARTX") != 0 &&
01368                 strcmp(descr, "STARTY") != 0 &&
01369                 strcmp(descr, "STEPX") != 0 &&
01370                 strcmp(descr, "STEPY") != 0 &&
01371                 strcmp(descr, "YSHIFT") != 0 &&
01372                 strcmp(descr, "DATAMIN") != 0 &&
01373                 strcmp(descr, "DATAMAX") != 0 &&
01374                 strcmp(descr, "NFLATS") != 0 &&
01375                 strcmp(descr, "RON") != 0 &&
01376                 strcmp(descr, "GAIN") != 0 &&
01377                 strcmp(descr, "FIBRESON") != 0)
01378                 {
01379                 /* Then it is a MIDAS descriptor which must be
01380                    stored in HISTORY keywords */
01381                 comment = "MIDAS_DESC";
01382             }
01383             else {
01384                 /* It is a descriptor recognized by the FITS format
01385                    (such as NAXIS1), which should not be converted
01386                    into HISTORY format */
01387                 comment = NULL;
01388             }
01389                 
01390 
01391             switch(type)
01392                 {
01393                 case 'I': uves_propertylist_append_c_int   (header, fits_descr, 0, comment)  ; break;
01394                 case 'R': uves_propertylist_append_c_float (header, fits_descr, 0.0, comment); break;
01395                 case 'C': uves_propertylist_append_c_string(header, fits_descr, "0", comment); break;
01396                 case 'D': uves_propertylist_append_c_double(header, fits_descr, 0.0, comment); break;
01397                 default: assure( false, CPL_ERROR_UNSUPPORTED_MODE, "%c", type); break;
01398                 }
01399 
01400             /* If name changes with index, get the first occurence */
01401 
01402         cards[i-1] = uves_find_property(header,
01403                         fits_descr, 
01404                         strcmp(fits_descr, previous_descr) != 0 ?
01405                         0 :  i-1 + nexist);
01406         
01407         passure( cards[i-1] != NULL, "%s %d %d", fits_descr, i-1, nexist);
01408 
01409         uves_free_string_const(&previous_descr);
01410         previous_descr = uves_sprintf("%s", fits_descr);
01411     }
01412 
01413     cards[length] = NULL;
01414 
01415   cleanup:
01416     uves_free_property(&new_prop);
01417     uves_free_string_const(&fits_descr);
01418     uves_free_string_const(&previous_descr);
01419     return cards;
01420 }
01421 
01422 /*----------------------------------------------------------------------------*/
01441 /*----------------------------------------------------------------------------*/
01442 static cpl_property **
01443 get_descr_info(int id, const char *descr, 
01444                char *type, int *length, int *bytelem)
01445 {
01446 
01447 
01448   *bytelem=*bytelem; //to remove compilation warning: this is not used
01449 
01450     cpl_property **cards = NULL;
01451     cpl_type t;
01452     const char *fits_descr = NULL;
01453     const char *previous_fits_descr = NULL;
01454     *type = ' ';
01455 
01456     passure( invariant(id), " ");
01457 
01458     assure( frame_is_open(id), CPL_ERROR_ILLEGAL_INPUT,
01459         "Frame no. %d is not open", id);
01460     
01461     check( load_frame_header(id),
01462        "Could not load header of file %s", frames[id].filename);
01463 
01464     cards = cpl_calloc(1, sizeof(cpl_property *));
01465     assure_mem( cards );
01466     
01467     *length = 0;
01468     do {
01469         *length += 1;
01470         cards = cpl_realloc(cards, (*length)*sizeof(cpl_property *));
01471         
01472         uves_free_string_const(&previous_fits_descr);
01473         previous_fits_descr = uves_sprintf("%s", fits_descr != NULL ? fits_descr : "----");
01474         
01475         uves_free_string_const(&fits_descr);
01476         fits_descr = convert_to_fits(descr, *length);
01477         
01478         uves_msg_debug("Searching for %d. occurence of %s", 
01479                        strcmp(fits_descr, previous_fits_descr) == 0 ?
01480                        *length : 1,
01481                        fits_descr);
01482         //uves_msg_debug("prev=%s curr=%s",previous_fits_descr,fits_descr);
01483         cards[*length-1] =
01484             uves_find_property(frames[id].header,
01485                                fits_descr, 
01486                                strcmp(fits_descr, previous_fits_descr) == 0 ?
01487                                *length - 1 : 0);
01488     }
01489     while (cards[*length-1] != NULL);
01490     
01491     *length -= 1;
01492 
01493     if (cards[0] != NULL)
01494     {
01495         t = cpl_property_get_type(cards[0]);
01496        
01497         switch(t)
01498         {
01499         case CPL_TYPE_INT   : *type = 'I'; break;
01500         case CPL_TYPE_FLOAT : *type = 'R'; break;
01501         case CPL_TYPE_STRING: *type = 'C'; break;
01502         case CPL_TYPE_DOUBLE: *type = 'D'; break;
01503         default: *type = ' '; break;
01504         }
01505 
01506         uves_msg_debug("Type is %c", *type);
01507     //AMO: Here the check on the length was *length == 1
01508         assure( *type != 'C' || *length <= 3, CPL_ERROR_UNSUPPORTED_MODE,
01509             "Cannot handle string array descriptor %s %s of length %d",
01510         descr, cpl_property_get_string(cards[0]),*length );
01511     
01512         if (*type == 'C')
01513         {
01514     //AMO: Here the check on the length was *length == 1
01515             passure( *length <= 3, "%d", *length );
01516             /* ... but we must return the string length,
01517                not the number of cards */
01518             *length = strlen(cpl_property_get_string(cards[0]));
01519         }
01520     }
01521     else
01522     {
01523         uves_msg_debug("%s not found", fits_descr);
01524         cpl_free(cards); cards = NULL;
01525         *length = 0;
01526     }
01527 
01528     passure( invariant(id), " ");
01529     
01530   cleanup:
01531     uves_free_string_const(&fits_descr);
01532     uves_free_string_const(&previous_fits_descr);
01533     if (cpl_error_get_code() != CPL_ERROR_NONE)
01534     {
01535         cpl_free(cards); cards = NULL;
01536     }
01537 
01538     return cards;
01539 }
01540 
01541 /*----------------------------------------------------------------------------*/
01551 /*----------------------------------------------------------------------------*/
01552 int flames_midas_scspro(const char *name)
01553 {
01554     int i;
01555 
01556     assure( current_caller == NULL, CPL_ERROR_ILLEGAL_INPUT,
01557         "MIDAS mode already running");
01558 
01559     uves_msg_debug("Initializing %s", name);
01560     current_caller = uves_sprintf("%s", name);
01561 
01562     assure( strcmp(name, "-1") != 0, CPL_ERROR_UNSUPPORTED_MODE,
01563         "Running outside MIDAS mode not supported");
01564 
01565     /* Reset all file handles */
01566     for (i = 0; i < MAX_OPEN; i++)
01567     {
01568         frames[i].filename = NULL;
01569     }
01570 
01571   cleanup:
01572     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01573 }
01574 
01575 /*----------------------------------------------------------------------------*/
01580 /*----------------------------------------------------------------------------*/
01581 
01582 int flames_midas_scsepi(void)
01583 {
01584     if (current_caller == NULL)
01585     {
01586         uves_msg_warning("MIDAS mode not running, "
01587                  "nothing to stop");
01588     }
01589     else
01590     {
01591             /* Check for unallocated resources */
01592             int i;
01593             for (i = 0; i < MAX_OPEN; i++)
01594                 {
01595                     if (frame_is_open(i))
01596                         {
01597                             uves_msg_warning("%s: %s no. %d: %s not deallocated",
01598                                              current_caller,
01599                                              frames[i].is_image ? "Image" : "Table",
01600                                              i, frames[i].filename);
01601 
01602                             frame_free(i);
01603                         }
01604                 }
01605 
01606         uves_msg_debug("Ending %s", current_caller);
01607         uves_free_string_const(&current_caller);
01608     }
01609 
01610     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01611 }
01612 
01613 /*----------------------------------------------------------------------------*/
01629 /*----------------------------------------------------------------------------*/
01630 int flames_midas_error_macro(const char *file, const char *function, int line,
01631                  int status)
01632 {
01633     uves_msg_debug("%s:%s() execution failed at %s:%s():%d", 
01634            current_caller != NULL ? current_caller : "???",
01635            function, file, function, line);
01636     
01637     return status;
01638 }
01639 
01640 /*----------------------------------------------------------------------------*/
01647 /*----------------------------------------------------------------------------*/
01648 
01649 int flames_midas_fail_macro(const char *file, const char *function, int line)
01650 { 
01651     const char *f = cpl_strdup(current_caller != NULL ? current_caller : "???");
01652     uves_msg_error("%s execution failed. Exit from MIDAS mode", f);
01653 
01654     uves_msg_debug("  at %s:%s():%d", file, function, line);
01655 
01656     flames_midas_scsepi();
01657 
01658     assure( false, CPL_ERROR_UNSPECIFIED, "%s failed", f);
01659 
01660   cleanup:
01661     uves_free_string_const(&f);
01662     return 1;
01663 }
01664 
01665 /*----------------------------------------------------------------------------*/
01675 /*----------------------------------------------------------------------------*/
01676 int flames_midas_sckwri(int *key, const int *values, 
01677             int felem, int maxvals, int *unit)
01678 {
01679     int i;
01680     if (unit) {} //to remove compilation warning: this is not used
01681 
01682     assure_nomsg( key != NULL, CPL_ERROR_NULL_INPUT );
01683 
01684     uves_msg_debug("Writing %d elements to integer keyword", maxvals);
01685 
01686     for (i = 0; i < maxvals; i++) {
01687         key[(felem-1) + i] = values[i];
01688     }
01689 
01690   cleanup:
01691     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01692 }
01693 
01694 /*----------------------------------------------------------------------------*/
01704 /*----------------------------------------------------------------------------*/
01705 int flames_midas_sckwrd(double *key, const double *values, 
01706             int felem, int maxvals, int *unit)
01707 {
01708     int i;
01709     if (unit) {} //to remove compilation warning: this is not used
01710     
01711     assure_nomsg( key != NULL, CPL_ERROR_NULL_INPUT );
01712 
01713     uves_msg_debug("Writing %d elements to double keyword", maxvals);
01714 
01715     for (i = 0; i < maxvals; i++) {
01716         key[(felem-1) + i] = values[i];
01717     }
01718 
01719     //fixme: is unit used? MIDAS doc. says it's unsupported
01720 
01721   cleanup:
01722     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01723 }
01724 
01725 
01726 /*----------------------------------------------------------------------------*/
01737 /*----------------------------------------------------------------------------*/
01738 int flames_midas_sckwrc(char *key, int noelem,
01739             const char *values, int felem, int maxvals, int *unit)
01740 {
01741     if (unit) {} //to remove compilation warning: this is not used
01742     assure_nomsg( noelem == 1, CPL_ERROR_UNSUPPORTED_MODE); 
01743     //fixme: remove from interface if this is always the case
01744 
01745     uves_msg_debug("Writing %d elements to character keyword", maxvals);
01746 
01747     strncpy(key+(felem-1), values, maxvals);
01748 
01749     //fixme: is unit used?
01750   cleanup:
01751     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01752 }
01753 
01754 /*----------------------------------------------------------------------------*/
01765 /*----------------------------------------------------------------------------*/
01766 int flames_midas_sckgetc(const char *key, 
01767              int felem, int maxvals, 
01768              int *actvals, char *values)
01769 {
01770 
01771     assure_nomsg( key    != NULL, CPL_ERROR_NULL_INPUT );
01772     assure_nomsg( values != NULL, CPL_ERROR_NULL_INPUT );
01773     assure_nomsg( actvals!= NULL, CPL_ERROR_NULL_INPUT );
01774 
01775     strncpy(values, key + (felem - 1), maxvals);
01776     values[strlen(key)+1] = '\0';
01777     *actvals = strlen(values);
01778 
01779     /*
01780       uves_msg_warning("Copy %s to %s",
01781                    key, values);
01782     
01783     */
01784 
01785   cleanup:
01786     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01787 }
01788 
01789 /*----------------------------------------------------------------------------*/
01799 /*----------------------------------------------------------------------------*/
01800 int flames_midas_sckgetc_fs(const cpl_frameset *key, 
01801                             int felem, int maxvals, 
01802                             int *actvals, const cpl_frameset **values)
01803 {
01804     maxvals=maxvals; //to remove compilation warning: this is not used
01805     assure_nomsg( key != NULL, CPL_ERROR_NULL_INPUT );
01806     assure( felem == 1, CPL_ERROR_ILLEGAL_INPUT,
01807             "felem = %d", felem );
01808     assure_nomsg( actvals != NULL, CPL_ERROR_NULL_INPUT );
01809     assure_nomsg( values  != NULL, CPL_ERROR_NULL_INPUT );
01810 
01811     *values = key;
01812 
01813   cleanup:
01814     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01815 }
01816 
01817 /*----------------------------------------------------------------------------*/
01827 /*----------------------------------------------------------------------------*/
01828 int flames_midas_sckgetc_fsp(cpl_frameset **key, 
01829                             int felem, int maxvals, 
01830                             int *actvals, cpl_frameset ***values)
01831 {
01832     maxvals=maxvals; //to remove compilation warning: this is not used
01833     assure_nomsg( key != NULL, CPL_ERROR_NULL_INPUT );
01834     assure( felem == 1, CPL_ERROR_ILLEGAL_INPUT,
01835             "felem = %d", felem );
01836     assure_nomsg( actvals != NULL, CPL_ERROR_NULL_INPUT );
01837     assure_nomsg( values  != NULL, CPL_ERROR_NULL_INPUT );
01838 
01839     *values = key;
01840 
01841   cleanup:
01842     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01843 }
01844 
01845 /*----------------------------------------------------------------------------*/
01857 /*----------------------------------------------------------------------------*/
01858 int flames_midas_sckrdd(const double *key, int felem, int maxvals, 
01859             int *actvals, double *values, int *unit, int *null)
01860 {
01861     int i;
01862     if (unit) {} //to remove compilation warning: this is not used
01863     if (null) {} //to remove compilation warning: this is not used
01864 
01865     assure_nomsg( key != NULL, CPL_ERROR_NULL_INPUT );
01866 
01867     *actvals = 0;
01868     for (i = 0; i < maxvals; i++)
01869     {
01870         values[i] = key[(felem-1)+i];
01871         (*actvals)++;
01872     }
01873 
01874     /* unit, null not implemented in MIDAS */
01875 
01876   cleanup:
01877     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01878 }
01879 
01880 /*----------------------------------------------------------------------------*/
01892 /*----------------------------------------------------------------------------*/
01893 int flames_midas_sckrdr(const float *key, int felem, int maxvals, 
01894             int *actvals, float *values, int *unit, int *null)
01895 {
01896     int i;
01897     if (unit) {} //to remove compilation warning: this is not used
01898     if (null) {} //to remove compilation warning: this is not used
01899 
01900     assure_nomsg( key != NULL, CPL_ERROR_NULL_INPUT );
01901 
01902     *actvals = 0;
01903     for (i = 0; i < maxvals; i++)
01904     {
01905         values[i] = key[(felem-1)+i];
01906         (*actvals)++;
01907     }
01908 
01909     /* unit, null not implemented in MIDAS */
01910 
01911   cleanup:
01912     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01913 }
01914 
01915 /*----------------------------------------------------------------------------*/
01927 /*----------------------------------------------------------------------------*/
01928 int flames_midas_sckrdi(const int *key, int felem, int maxvals, 
01929             int *actvals, int *values, int *unit, int *null)
01930 {
01931     int i;
01932     if (unit) {} //to remove compilation warning: this is not used
01933     if (null) {} //to remove compilation warning: this is not used
01934 
01935     *actvals = 0;
01936     for (i = 0; i < maxvals; i++)
01937     {
01938         values[i] = key[(felem-1)+i];
01939         (*actvals)++;
01940     }
01941 
01942     /* unit, null not implemented in MIDAS */
01943 
01944 /*  cleanup: */
01945     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01946 }
01947 
01948 /*----------------------------------------------------------------------------*/
01961 /*----------------------------------------------------------------------------*/
01962 int flames_midas_sckrdc(const char *key, int noelm, int felem, int maxvals, 
01963             int *actvals, char *values, int *unit, int *null)
01964 {
01965     /* This function is only used in calls, like this
01966        
01967          SCKRDC("H_RON_L",16,1,1,&actvals, h_ron_l, &unit, &null)
01968 
01969      where  noelm is the string length and felem = maxvals = 1   */
01970     if (unit) {} //to remove compilation warning: this is not used
01971     if (null) {} //to remove compilation warning: this is not used
01972 
01973     assure( felem == 1, CPL_ERROR_UNSUPPORTED_MODE, "Implement me" );
01974     assure( maxvals == 1, CPL_ERROR_UNSUPPORTED_MODE, "Implement me" );
01975 
01976     strncpy(values, key + (felem - 1), noelm);
01977     values[noelm] = '\0';
01978     *actvals = strlen(values);
01979 
01980     /* unit, null not implemented in MIDAS */
01981 
01982   cleanup:
01983     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01984 }
01985 
01986 /*----------------------------------------------------------------------------*/
01997 /*----------------------------------------------------------------------------*/
01998 static int
01999 sckfnd(const char the_type, const void *key, char *type, int *noelem, int *bytelem)
02000 {
02001     *noelem=*noelem; //to remove compilation warning: this is not used
02002     *bytelem=*bytelem; //to remove compilation warning: this is not used
02003     if (key == NULL)
02004     {
02005         uves_msg_debug("Keyword is NULL");   
02006         *type = ' ';
02007     }
02008     else
02009     {
02010         *type = the_type;
02011     }
02012     /* Fixme: what about noelem  (needs to be passed from the caller) */
02013     
02014 //  cleanup:
02015     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02016 }
02017 
02018 /*----------------------------------------------------------------------------*/
02022 /*----------------------------------------------------------------------------*/
02023 int flames_midas_sckfnd_double(const double *key, char *type, int *noelem, int *bytelem)
02024 {
02025     return sckfnd('D', key, type, noelem, bytelem);
02026 }
02027 /*----------------------------------------------------------------------------*/
02031 /*----------------------------------------------------------------------------*/
02032 int flames_midas_sckfnd_float(const float *key, char *type, int *noelem, int *bytelem)
02033 {
02034     return sckfnd('R', key, type, noelem, bytelem);
02035 }
02036 
02037 /*----------------------------------------------------------------------------*/
02041 /*----------------------------------------------------------------------------*/
02042 int flames_midas_sckfnd_int(const int *key, char *type, int *noelem, int *bytelem)
02043 {
02044     return sckfnd('I', key, type, noelem, bytelem);
02045 }
02046 
02047 /*----------------------------------------------------------------------------*/
02051 /*----------------------------------------------------------------------------*/
02052 int flames_midas_sckfnd_string(const char *key, char *type, int *noelem, int *bytelem)
02053 {
02054     return sckfnd('C', key, type, noelem, bytelem);
02055 }
02056 
02057 /*----------------------------------------------------------------------------*/
02063 /*----------------------------------------------------------------------------*/
02064 
02065 int flames_midas_sctput(const char *msg, 
02066             const char *function, const char *file, int line)
02067 {
02068     if (strncmp(msg, "Error", 5) == 0)
02069     {
02070         uves_msg_error("%s:%d: %s", file, line, msg);
02071     }
02072     else if (strncmp(msg, "Warning", 7) == 0)
02073     {
02074         uves_msg_warning("%s: %s", function, msg);
02075     }
02076     else
02077     {
02078             /* indented */
02079         uves_msg_low("%s: %s", function, msg);
02080     }
02081 
02082 //  cleanup:
02083     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02084 }
02085 
02086 /*----------------------------------------------------------------------------*/
02114 /*----------------------------------------------------------------------------*/
02115 int flames_midas_scfinf(const char *name, int fno, int *ibuf)
02116 {
02117     FILE *file;
02118     uves_propertylist *header = NULL;
02119 
02120     uves_msg_debug("fno = %d", fno);
02121 
02122     if (name == NULL) return 1;
02123     
02124     /* Test for existence */
02125     file = fopen(name, "r");
02126     if (file == NULL)
02127         {
02128             uves_msg_debug("File %s could not be opened", name);
02129             return 1;
02130         }
02131     uves_msg_debug("File %s could be opened", name);
02132     fclose(file);
02133     
02134     if (fno == 3) {
02135         /* The FLAMES code needs only the information about the
02136            file type which is written to ibuf[0] */
02137         if (uves_get_nextensions(name) > 0) {
02138             ibuf[0] = F_TBL_TYPE;
02139         }
02140         else {
02141             ibuf[0] = F_IMA_TYPE;
02142         }
02143     }
02144     else if (fno == 4)
02145     {
02146             /* The FLAMES code needs only the data type
02147                which is written to ibuf[1] */
02148             int bitpix;
02149 
02150             check( header = uves_propertylist_load(name, 0),
02151                    "Could not load %s primary header", name);
02152 
02153             check( bitpix = uves_pfits_get_bitpix(header),
02154                    "Could not get BITPIX from %s", name);
02155 
02156             uves_msg_debug("BITPIX is %d", bitpix);
02157 
02158             switch (bitpix) {
02159             case  16: ibuf[1] = D_I2_FORMAT; break; /* 16 bit signed integer */
02160             case  32: ibuf[1] = D_I4_FORMAT; break; /* 32 bit signed integer */
02161             case -32: ibuf[1] = D_R4_FORMAT; break; /* 32 bit floating point */
02162             case -64: ibuf[1] = D_R8_FORMAT; break; /* 64 bit floating point */
02163             default:
02164                 assure( false, CPL_ERROR_UNSUPPORTED_MODE,
02165                         "Cannot convert BITPIX = %d to DATTYPE",
02166                         bitpix);
02167                 break;
02168             }
02169     }
02170     else if (fno == 99)
02171     {
02172             /* Just test for file existence */
02173     }
02174     else
02175     {
02176         assure( false, CPL_ERROR_UNSUPPORTED_MODE,
02177                     "fno = %d is not needed by FLAMES code", fno);
02178     }
02179     
02180   cleanup:
02181     uves_free_propertylist(&header);
02182     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02183 }
02184 
02185 /*----------------------------------------------------------------------------*/
02195 /*----------------------------------------------------------------------------*/
02196 int flames_midas_scfopn(const char *name, int dattype, int newopn, int filtype,
02197             int *imno)
02198 {
02199     uves_msg_debug("Trying to open %s", name);
02200 
02201     if (filtype == F_IMA_TYPE) {
02202 
02203         if (newopn == 0) {
02204             
02205             /* Find first open slot */
02206             int i;
02207             bool found = false;
02208             for (i = 0; !found && i < MAX_OPEN; i++)
02209                 {
02210                     if (!frame_is_open(i))
02211                         {
02212                             cpl_type type;
02213                             
02214                             found = true;
02215                             *imno = i;
02216                             
02217                             type = flames_midas_image_dtype_to_cpltype(dattype);
02218                             
02219                             frame_new_image(*imno, name, NULL, false,
02220                                             NULL, type, dattype);
02221                             
02222                             uves_msg_debug("Opened image no. %d: %s as type %s",
02223                                            i, name, 
02224                                            uves_tostring_cpl_type(type));
02225                         }
02226                 }
02227             
02228             assure( found, CPL_ERROR_UNSUPPORTED_MODE,
02229                     "Cannot open more than %d image files",
02230                     MAX_OPEN);
02231         }
02232         else
02233             {
02234                 
02235                 assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me");
02236             }
02237     }
02238     else
02239     {
02240             assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me");
02241     }
02242 
02243   cleanup:
02244     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02245 }
02246 
02247 /*----------------------------------------------------------------------------*/
02261 /*----------------------------------------------------------------------------*/
02262 int flames_midas_scfcre(const char *name, int dattype, int iomode, int filtype, 
02263                         int size, int *imno)
02264 {
02265     if (filtype == F_IMA_TYPE)
02266     {
02267         if (iomode == F_O_MODE) /* output: create empty header */
02268         {
02269 
02270             /* Find first open slot */
02271             int i;
02272             bool found = false;
02273                     cpl_type type;
02274 
02275             for (i = 0; !found && i < MAX_OPEN; i++)
02276             {
02277 
02278                 if (!frame_is_open(i))
02279                 {
02280                     found = true;
02281                     *imno = i;
02282                     
02283                     uves_msg_debug("Opened image no. %d: %s",
02284                            i, name);
02285                 }
02286             }
02287             
02288             assure( found, CPL_ERROR_UNSUPPORTED_MODE,
02289                 "Cannot open more than %d image files",
02290                 MAX_OPEN);
02291             
02292                     type = flames_midas_image_dtype_to_cpltype(dattype);
02293                    
02294                     /* Create Nx1 image, set proper size later */
02295                     frame_new_image(*imno, name, uves_propertylist_new(), true,
02296                                     cpl_image_new(size, 1, type), type, dattype);
02297 
02298                 }
02299 
02300         else
02301         {
02302             assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me");
02303         }
02304     }
02305     else
02306     {
02307         assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me");
02308     }
02309 
02310 
02311     passure( invariant(*imno), " ");
02312 
02313   cleanup:
02314     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02315 }
02316 
02317 /*----------------------------------------------------------------------------*/
02323 /*----------------------------------------------------------------------------*/
02324 static int
02325 frame_close(int id)
02326 {
02327     cpl_property **cards = NULL;
02328     fitsfile *fptr = NULL;
02329     int fio_status = 0;
02330 
02331     passure( invariant(id), " ");
02332     if (!frame_is_open(id))  {
02333 
02334 
02335         uves_msg_warning("%s number %d is not open, cannot close", 
02336                          frames[id].is_image ? "Image" : "Table",
02337                          id);
02338 
02339     }
02340     else {
02341         if (frames[id].need_to_save) {
02342             char type;
02343             int bytelem;
02344             int naxis;
02345             
02346             uves_msg_debug("Saving frame %s to disk", frames[id].filename);
02347             
02348             check( load_frame(id),
02349                    "Could not load frame %s", frames[id].filename);
02350                     
02351             check( load_frame_header(id),
02352                    "Could not load %s header", frames[id].filename);
02353                     
02354             check( cards = get_descr_info(id, "NPIX",
02355                                           &type, &naxis, &bytelem),
02356                    "Could not get info on descriptor NPIX");
02357                     
02358             check( convert_to_history(&frames[id].header),
02359                    "Could not convert header");
02360 
02361             /* Note header is free'd below, so changing it is ok */
02362              if (frames[id].is_image)
02363                 {
02364 
02365 
02366                     bool save_as_bitpix16 =
02367                         (frames[id].data.image.dtype == D_I1_FORMAT ||
02368                          frames[id].data.image.dtype == D_I2_FORMAT);
02369                     /* Save D_I1_FORMAT / D_I2_FORMAT  (masks) as 16 bit unsigned, 
02370                        otherwise 32 bit signed */
02371 
02372                     bool save_as_1d = (naxis == 1);
02373                     /* Don't save 2d images as 1d, we will loose START/STEP descriptors */
02374 
02375                     assure( naxis == 1 || naxis == 2 || naxis == 3 || naxis == 4,
02376                             CPL_ERROR_UNSUPPORTED_MODE,
02377                             "Cannot save image with NAXIS = %d", naxis);
02378 
02379                     uves_msg_debug("Saving %dd image", naxis);
02380                     
02381                     check( uves_save_image(frames[id].data.image.image,
02382                                            frames[id].filename,
02383                                            frames[id].header,
02384                                            save_as_bitpix16,
02385                                            save_as_1d),
02386                            "Error saving image %s", frames[id].filename);
02387 
02388                     if (naxis == 2 || naxis == 3 || naxis == 4) {
02389                         int NAXIS[4];
02390                         int unit, null;
02391                         int actvals;
02392                         char dummy[100]; /* More than length of FITS key record */
02393                         char err_message[81];  /* long enough according to CFITSIO doc. */
02394                         int current_naxis;   /* As written by the previous uves_save_image()
02395                                                 call */
02396                         
02397                         assure( 0 == flames_midas_scdrdi(id, "NPIX",
02398                                                          1, naxis,
02399                                                          &actvals, NAXIS,
02400                                                          &unit, &null), 
02401                                 CPL_ERROR_ILLEGAL_INPUT,
02402                                 "Failed to read NPIX");
02403                         
02404                         assure( actvals == naxis, CPL_ERROR_ILLEGAL_INPUT,
02405                                 "naxis = %d but actvals = %d", naxis, actvals);
02406                                 
02407                         /* CPL and QFITS cannot change a FITS header without 
02408                            load/saving the data buffer
02409                            so use CFITSIO for this basic task */
02410 
02411                         fits_open_file(&fptr, frames[id].filename, READWRITE, &fio_status);
02412                         
02413                         assure( fio_status == 0, CPL_ERROR_ILLEGAL_OUTPUT,
02414                                 "Failed to open file %s", frames[id].filename);
02415 
02416                         /* Move to beginning of header, then to location of NAXIS (which should already exist) */
02417                         fits_read_record(fptr, 0, dummy, &fio_status);
02418                         /* fits_read_card(fptr, (char*)"NAXIS", dummy, &fio_status); */
02419                         fits_read_key(fptr, TINT, (char*)"NAXIS", &current_naxis, NULL, &fio_status);
02420 
02421                         fits_update_key(fptr, TINT, (char*)"NAXIS", &naxis, (char*)"Empty unit", &fio_status);
02422                         fits_update_key(fptr, TINT, (char*)"NAXIS1", &NAXIS[0], (char*)"Empty unit", &fio_status);
02423 
02424                         if (current_naxis < 2) {
02425                             fits_insert_card(fptr, (char*)"NAXIS2", &fio_status);
02426                         }
02427                         fits_update_key(fptr, TINT, (char*)"NAXIS2", &NAXIS[1], (char*)"Empty unit", &fio_status);
02428                         
02429                         if (naxis >= 3) {
02430                             fits_insert_card(fptr, (char*)"NAXIS3", &fio_status);
02431                             fits_update_key(fptr, TINT, (char*)"NAXIS3", &NAXIS[2], (char*)"Empty unit", &fio_status);
02432                         }
02433                         
02434                         if (naxis >= 4) {
02435                             fits_insert_card(fptr, (char*)"NAXIS4", &fio_status);
02436                             fits_update_key(fptr, TINT, (char*)"NAXIS4", &NAXIS[3], (char*)"Empty unit", &fio_status);
02437                         }
02438                         
02439                         fits_close_file(fptr, &fio_status);
02440                         
02441                         if (fio_status != 0) fits_read_errmsg(err_message);
02442                         assure( fio_status == 0, CPL_ERROR_ILLEGAL_OUTPUT,
02443                                 "Error '%s' code %d while updating %s FITS header", 
02444                                 err_message, fio_status, frames[id].filename);
02445                     }
02446 
02447                 }
02448             else
02449                 {
02450                     cpl_table_set_size(frames[id].data.table.table,
02451                                        frames[id].data.table.maxrow);
02452                   
02453                     check( uves_table_save(frames[id].data.table.table,
02454                                            frames[id].header, /* Primary header */
02455                                            NULL,                /* Ext. header */
02456                                            frames[id].filename,
02457                                            CPL_IO_DEFAULT),
02458                            "Error saving table %s", frames[id].filename);
02459                 }
02460                     
02461             frames[id].need_to_save = false;
02462 
02463         }
02464         else
02465             {
02466                 uves_msg_debug("Closing %s %s (don't save to disk)", 
02467                                frames[id].is_image ? "image" : "table",
02468                                frames[id].filename);
02469             }
02470             
02471         frame_free(id);
02472 
02473     }
02474     
02475     passure( !frame_is_open(id), " ");
02476     passure( invariant(id), " ");
02477 
02478   cleanup:
02479     cpl_free(cards); cards = NULL;
02480     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02481 }
02482     
02483 /*----------------------------------------------------------------------------*/
02490 /*----------------------------------------------------------------------------*/
02491 int flames_midas_scfclo(int imno)
02492 {
02493     return frame_close(imno);
02494 }
02495 
02496 /*----------------------------------------------------------------------------*/
02508 /*----------------------------------------------------------------------------*/
02509 int flames_midas_scfget(int imno, int felem, int size, int *actsize, char *bufadr)
02510 {
02511   //cpl_type type;
02512 
02513     passure( invariant(imno), " ");
02514 
02515     assure( frame_is_open(imno) && frames[imno].is_image, CPL_ERROR_ILLEGAL_INPUT,
02516             "Image no. %d is not open", imno);
02517 
02518     check( load_frame(imno),
02519        "Could not load image %s", frames[imno].filename);
02520 
02521     assure( (felem-1) + size <=
02522         cpl_image_get_size_x(frames[imno].data.image.image)*
02523         cpl_image_get_size_y(frames[imno].data.image.image),
02524         CPL_ERROR_ACCESS_OUT_OF_RANGE,
02525         "Cannot read %d bytes of CPL image of size %" CPL_SIZE_FORMAT "x%" CPL_SIZE_FORMAT " position %d",
02526         size, 
02527         cpl_image_get_size_x(frames[imno].data.image.image),
02528         cpl_image_get_size_y(frames[imno].data.image.image),
02529         felem-1);
02530 
02531     switch(frames[imno].data.image.type) {
02532     case CPL_TYPE_INT:
02533     {
02534         int *buffer;
02535         int i;
02536         buffer = cpl_image_get_data_int(frames[imno].data.image.image);
02537         buffer += (felem-1);
02538         
02539         switch(frames[imno].data.image.dtype) {
02540         case D_I1_FORMAT:
02541             for (i = 0; i < size; i++)
02542                 {
02543                     ((char *)bufadr)[i] = buffer[i];
02544                 }
02545             break;
02546         case D_I2_FORMAT:
02547         case D_I4_FORMAT:
02548             for (i = 0; i < size; i++)
02549                 {
02550                     ((int32_t *)bufadr)[i] = buffer[i];
02551                 }
02552             break;
02553         default:
02554             assure_nomsg( false, CPL_ERROR_UNSUPPORTED_MODE );
02555             break;
02556         }
02557         *actsize = size;
02558     }
02559     break;
02560     case CPL_TYPE_FLOAT:
02561     {
02562         float *buffer;
02563         int i;
02564         buffer = cpl_image_get_data_float(frames[imno].data.image.image);
02565         buffer += (felem-1);
02566         
02567         for (i = 0; i < size; i++)
02568             {
02569                 ((float *)bufadr)[i] = buffer[i];
02570             }
02571         *actsize = size;
02572     }
02573     break;
02574     default:
02575         assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Type is %s",
02576                 uves_tostring_cpl_type(frames[imno].data.image.type));
02577         break;
02578     }
02579     
02580     passure( invariant(imno), " ");
02581 
02582   cleanup: 
02583     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02584 }
02585 
02586 
02587 /*----------------------------------------------------------------------------*/
02597 /*----------------------------------------------------------------------------*/
02598 int flames_midas_scfput(int imno, int felem, int size, const char *bufadr)
02599 {
02600     int i;
02601 
02602     passure( invariant(imno), " ");
02603 
02604     assure( frame_is_open(imno) && frames[imno].is_image, CPL_ERROR_ILLEGAL_INPUT,
02605         "Image no. %d is not open", imno);
02606 
02607     /* Load image if necessary, then overwrite part, or all of data buffer */
02608     check( load_frame(imno),
02609            "Could not load image %s", frames[imno].filename);
02610 
02611     assure( (felem-1) + size <=
02612         cpl_image_get_size_x(frames[imno].data.image.image)*
02613         cpl_image_get_size_y(frames[imno].data.image.image),
02614         CPL_ERROR_ACCESS_OUT_OF_RANGE,
02615         "Cannot write %d pixels to CPL image of size %" CPL_SIZE_FORMAT "x%" CPL_SIZE_FORMAT " position %d",
02616         size, 
02617         cpl_image_get_size_x(frames[imno].data.image.image),
02618         cpl_image_get_size_y(frames[imno].data.image.image),
02619         felem-1);
02620 
02621     uves_msg_debug("Writing %d pixels to image %s",
02622                    size, frames[imno].filename);
02623 
02624     switch(frames[imno].data.image.type) {
02625     case CPL_TYPE_INT:
02626     {
02627         int *buffer;
02628         buffer = cpl_image_get_data_int(frames[imno].data.image.image);
02629         buffer += (felem-1);
02630 
02631         switch(frames[imno].data.image.dtype) {
02632         case D_I1_FORMAT:
02633             for (i = 0; i < size; i++)
02634                 {
02635                     buffer[i] = ((char *)bufadr)[i];
02636                 }
02637             break;
02638         case D_I2_FORMAT:
02639         case D_I4_FORMAT:
02640             for (i = 0; i < size; i++)
02641                 {
02642                     buffer[i] = ((int *)bufadr)[i];
02643                 }
02644             break;
02645         default:
02646             assure_nomsg( false, CPL_ERROR_UNSUPPORTED_MODE );
02647             break;
02648         }
02649     }
02650     break;
02651     case CPL_TYPE_FLOAT:
02652     {
02653         float *buffer;
02654         buffer = cpl_image_get_data_float(frames[imno].data.image.image);
02655         buffer += (felem-1);
02656         
02657         for (i = 0; i < size; i++)
02658             {
02659                 buffer[i] = ((float *)bufadr)[i];
02660             }
02661     }
02662     break;
02663     case CPL_TYPE_DOUBLE:
02664     {
02665         double *buffer;
02666         buffer = cpl_image_get_data_double(frames[imno].data.image.image);
02667         buffer += (felem-1);
02668         
02669         for (i = 0; i < size; i++)
02670             {
02671                 buffer[i] = ((double *)bufadr)[i];
02672             }
02673     }
02674     break;
02675     default:
02676         assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Type is %s", 
02677                 uves_tostring_cpl_type(frames[imno].data.image.type));
02678         break;
02679     }
02680     
02681     frames[imno].need_to_save = true;  /* Memory buffer has changed */
02682 
02683     passure( invariant(imno), " ");
02684 
02685   cleanup:
02686     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02687 }
02688 
02689 /*----------------------------------------------------------------------------*/
02703 /*----------------------------------------------------------------------------*/
02704 int flames_midas_scdfnd(int id, const char *descr, 
02705             char *type, int *noelem, int *bytelem)
02706 {
02707   cpl_property **cards = NULL;
02708 
02709   passure( invariant(id), " ");
02710   assure_nomsg( descr != NULL, CPL_ERROR_NULL_INPUT );
02711 
02712   if (strcmp(descr, "LHCUTS") == 0)
02713     {
02714       int datamin_noelem, datamax_noelem;
02715       char datamin_type, datamax_type;
02716                 
02717       *noelem = 2; /* LHCUTS1 and LHCUTS2 always exist */
02718       *type ='R';
02719             
02720       flames_midas_scdfnd(id, "DATAMIN", &datamin_type, &datamin_noelem, bytelem);
02721       flames_midas_scdfnd(id, "DATAMAX", &datamax_type, &datamax_noelem, bytelem);
02722             
02723       assure( datamin_noelem <= 1, CPL_ERROR_ILLEGAL_INPUT,
02724           "Multiple (%d) DATAMIN keywords found", datamin_noelem);
02725 
02726       assure( datamax_noelem <= 1, CPL_ERROR_ILLEGAL_INPUT,
02727           "Multiple (%d) DATAMIN keywords found", datamax_noelem);
02728 
02729       if (datamin_noelem > 0)
02730     {
02731       *noelem = 3;
02732       assure( datamin_type == 'D', CPL_ERROR_TYPE_MISMATCH,
02733           "DATAMIN has type %c, %c expected", datamin_type, 'D');
02734 
02735       if (datamax_noelem > 0)
02736         {
02737           *noelem = 4;
02738           assure( datamax_type == 'D', CPL_ERROR_TYPE_MISMATCH,
02739               "DATAMAX has type %c, %c expected", datamax_type, 'D');
02740         }
02741     }
02742 
02743     }
02744   else
02745     {
02746       check( cards = get_descr_info(id, descr,
02747                     type, noelem, bytelem),
02748          "Could not get info on descriptor %s", descr);
02749             
02750       if (cards == NULL)
02751     {
02752       *type = ' ';
02753       uves_msg_debug("Descriptor %s not found",descr);
02754     }
02755       else
02756     {
02757       uves_msg_debug("Found descriptor %s, type = %c, length = %d",
02758                descr, *type, *noelem);
02759     }
02760     }
02761 
02762   passure( invariant(id), " ");
02763 
02764  cleanup:
02765   cpl_free(cards); cards = NULL;
02766 
02767   return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02768 }
02769 
02770 
02771 
02772 /*----------------------------------------------------------------------------*/
02786 /*----------------------------------------------------------------------------*/
02787 int flames_midas_scdprs(int id, const char *descr, 
02788             char *type, int *noelem, int *bytelem)
02789 {
02790   cpl_property **cards = NULL;
02791 
02792   passure( invariant(id), " ");
02793   assure_nomsg( descr != NULL, CPL_ERROR_NULL_INPUT );
02794 
02795   if (strcmp(descr, "LHCUTS") == 0)
02796     {
02797       int datamin_noelem, datamax_noelem;
02798       char datamin_type, datamax_type;
02799                 
02800       *noelem = 2; /* LHCUTS1 and LHCUTS2 always exist */
02801       *type ='R';
02802             
02803       flames_midas_scdfnd(id, "DATAMIN", &datamin_type, &datamin_noelem, bytelem);
02804       flames_midas_scdfnd(id, "DATAMAX", &datamax_type, &datamax_noelem, bytelem);
02805             
02806       assure( datamin_noelem <= 1, CPL_ERROR_ILLEGAL_INPUT,
02807           "Multiple (%d) DATAMIN keywords found", datamin_noelem);
02808 
02809       assure( datamax_noelem <= 1, CPL_ERROR_ILLEGAL_INPUT,
02810           "Multiple (%d) DATAMIN keywords found", datamax_noelem);
02811 
02812       if (datamin_noelem > 0)
02813     {
02814       *noelem = 3;
02815       assure( datamin_type == 'D', CPL_ERROR_TYPE_MISMATCH,
02816           "DATAMIN has type %c, %c expected", datamin_type, 'D');
02817 
02818       if (datamax_noelem > 0)
02819         {
02820           *noelem = 4;
02821           assure( datamax_type == 'D', CPL_ERROR_TYPE_MISMATCH,
02822               "DATAMAX has type %c, %c expected", datamax_type, 'D');
02823         }
02824     }
02825 
02826     }
02827   else
02828     {
02829       check( cards = get_descr_info(id, descr,
02830                     type, noelem, bytelem),
02831          "Could not get info on descriptor %s", descr);
02832             
02833       if (cards == NULL)
02834     {
02835       *type = ' ';
02836       uves_msg_debug("Descriptor %s not found",descr);
02837           cpl_free(cards); cards = NULL;
02838       return 1;
02839     }
02840       else
02841     {
02842       uves_msg_debug("Found descriptor %s, type = %c, length = %d",
02843                descr, *type, *noelem);
02844     }
02845     }
02846 
02847   passure( invariant(id), " ");
02848 
02849  cleanup:
02850   cpl_free(cards); cards = NULL;
02851 
02852   return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02853 }
02854 
02855 /*----------------------------------------------------------------------------*/
02870 /*----------------------------------------------------------------------------*/
02871 static int
02872 scdrd(char expected_type, int id, const char *descr, 
02873       int felem, int maxvals,
02874       int *actvals, void *values,
02875       int *unit, int *null)
02876 {
02877     char type;
02878     int length;
02879     int bytelem;
02880     cpl_property **cards = NULL;
02881     int i;
02882     if (unit) {} //to remove compilation warning: this is not used
02883     if (null) {} //to remove compilation warning: this is not used
02884 
02885     passure( invariant(id), " ");
02886 
02887     check( cards = get_descr_info(id, descr, &type,
02888                                   &length, &bytelem),
02889        "Could not get info on descriptor %s", descr);
02890 
02891     assure( cards != NULL, CPL_ERROR_DATA_NOT_FOUND,
02892         "Descriptor %s not found in file %s", descr, frames[id].filename);
02893 
02894     /* Allow conversion R -> D */
02895     assure( (expected_type == 'D' && type == 'R') 
02896             ||
02897             type == expected_type, CPL_ERROR_TYPE_MISMATCH,
02898         "Descriptor %s has type %c, %c expected",
02899         descr, type, expected_type);
02900 
02901     passure( type != 'C' || felem == 1, "'%c' %d", type, felem);
02902 
02903     *actvals = 0;
02904     //uves_msg_warning("length=%d",length);
02905     for (i = felem-1; i < length; i++)
02906     {
02907         if (*actvals < maxvals)
02908         {
02909             uves_msg_debug("Getting %d of %d (max %d) values of descriptor %s",
02910                    *actvals + 1, length - (felem-1), maxvals, descr);
02911 
02912             switch(type) {
02913             case 'I': 
02914                 ((int *)values)[i-(felem-1)]    = cpl_property_get_int(cards[i]); 
02915                 uves_msg_debug("Value = %d", ((int *)values)[i-(felem-1)]);
02916                 break;
02917             case 'D': 
02918                 ((double *)values)[i-(felem-1)] = cpl_property_get_double(cards[i]);
02919                 uves_msg_debug("Value = %g", ((double *)values)[i-(felem-1)]);
02920                 break;
02921             case 'R': 
02922                 switch(expected_type) {
02923                 case 'R':
02924                     ((float *)values)[i-(felem-1)]  = cpl_property_get_float(cards[i]); 
02925                     uves_msg_debug("Value = %g", ((float *)values)[i-(felem-1)]);
02926                     break;
02927                 case 'D':
02928                     ((double *)values)[i-(felem-1)]  = cpl_property_get_float(cards[i]); 
02929                     uves_msg_debug("Value = %g", ((double *)values)[i-(felem-1)]);
02930                     break;
02931                 default:
02932                     passure( false, " ");
02933                     break;
02934                 }
02935                 break;
02936             case 'C':
02937                 ((char *)values)[i-(felem-1)]   = cpl_property_get_string(cards[0])[i]; 
02938                 uves_msg_debug("Value = %c", ((char *)values)[i-(felem-1)]);
02939                 break;
02940             default: 
02941                 assure( false, CPL_ERROR_INVALID_TYPE, "Type is %c", type); 
02942                 break;
02943             }
02944             *actvals += 1;
02945         }
02946     }
02947 
02948     if (type == 'C' && *actvals < maxvals)
02949     {
02950         /* length is the string length,
02951            terminate with 0
02952            This character does not count in actvals
02953                but is include in maxvals
02954         */
02955         ((char *)values)[length-(felem-1)] = '\0';
02956     }
02957     
02958     /* unit, null not implemented by MIDAS */
02959 
02960     passure( invariant(id), " ");
02961 
02962   cleanup:
02963     cpl_free(cards); cards = NULL;
02964 
02965     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02966 }
02967 /*----------------------------------------------------------------------------*/
02974 /*----------------------------------------------------------------------------*/
02975 int flames_midas_scdrdi(int id, const char *descr, 
02976             int felem, int maxvals,
02977             int *actvals, int *values,
02978             int *unit, int *null)
02979 {
02980     char *char_values = NULL;
02981 
02982 #if 0
02983     if (strcmp(descr, "MAXFIBRES") == 0)
02984     {
02985         char_values = cpl_malloc(maxvals + 1);
02986         assure_mem( char_values );
02987         char_values[0] = '\0';
02988 
02989         assure( felem == 1, CPL_ERROR_UNSUPPORTED_MODE,
02990             "first element no. (%d) is not 1", felem);
02991 
02992         check( scdrd('C', imno, descr, felem, maxvals, actvals, char_values, unit, null),
02993            "Reading %s as string failed", descr);
02994 
02995         assure( strlen(char_values) == 1, CPL_ERROR_ILLEGAL_INPUT,
02996             "MAXFIBRES value (%s) has length different from 1",
02997             char_values);
02998 
02999         /* We have a string of length 1, convert to integer */
03000         errno = 0;
03001         values[0] = atoi(char_values);
03002         assure( errno == 0, CPL_ERROR_ILLEGAL_OUTPUT,
03003             "Conversion of %s to integer failed", char_values);
03004 
03005         cpl_msg_debug("Got value %s (%d)", char_values, values[0]);
03006     }
03007     else
03008 #endif
03009     {
03010         /* Ok to return here, nothing alloc'ed */
03011         return scdrd('I', id, descr, felem, maxvals, actvals, values, unit, null);
03012     }
03013 
03014 /*  cleanup: */
03015     uves_free_string(&char_values);
03016     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03017 }
03018 
03019 /*----------------------------------------------------------------------------*/
03025 /*----------------------------------------------------------------------------*/
03026 int flames_midas_scdrdd(int id, const char *descr, 
03027             int felem, int maxvals,
03028             int *actvals, double *values,
03029             int *unit, int *null)
03030 {
03031     return scdrd('D', id, descr, felem, maxvals, actvals, values, unit, null);
03032 }
03033 
03034 /*----------------------------------------------------------------------------*/
03040 /*----------------------------------------------------------------------------*/
03041 int flames_midas_scdrdr(int id, const char *descr, 
03042             int felem, int maxvals,
03043             int *actvals, float *values,
03044             int *unit, int *null)
03045 {
03046     if (strcmp("LHCUTS", descr) == 0 && felem < 3)
03047     {
03048             int i;
03049             bool success = true;
03050             
03051             for (i = felem; i < felem+maxvals; i++)
03052                 {
03053                     double val;
03054                     if (1 <= i && i <= 2)
03055                         {
03056                             uves_msg_debug("Do not read LHCUTS%d", i);
03057                         }
03058                     else if (i == 3)
03059                         {
03060                             success = success &&
03061                                 (flames_midas_scdrdd(id, "DATAMIN", i, 1,
03062                                                      actvals,
03063                                                      &val,
03064                                                      unit, null)) == 0;
03065 
03066                             values[i-felem] = (float) val;
03067                         }
03068                     else if (i == 4)
03069                         {
03070                             success = success &&
03071                                 (flames_midas_scdrdd(id, "DATAMAX", i, 1,
03072                                                      actvals,
03073                                                      &val,
03074                                                      unit, null)) == 0;
03075                             values[i-felem] = (float) val;
03076                         }
03077                     else
03078                         {
03079                             success = false;
03080                         }
03081                 }
03082             return success ? 0 : 1;
03083     }
03084     else
03085     {
03086             return scdrd('R', id, descr, felem, maxvals, actvals, values, unit, null);
03087     }
03088 }
03089 
03090 /*----------------------------------------------------------------------------*/
03100 /*----------------------------------------------------------------------------*/
03101 int flames_midas_scdrdc(int id, const char *descr, 
03102             int noelem,
03103             int felem, int maxvals,
03104             int *actvals, char *values,
03105             int *unit, int *null)
03106 {
03107     int returnvalue = 1;
03108     
03109     assure( noelem == sizeof(char), CPL_ERROR_UNSUPPORTED_MODE, "Implement me" );
03110     assure( felem  == 1, CPL_ERROR_UNSUPPORTED_MODE, "Implement me" );
03111    
03112     returnvalue = scdrd('C', id, descr, felem, maxvals, actvals, values, unit, null);
03113     
03114   cleanup:
03115     return returnvalue;    
03116 }
03117 
03118 
03119 
03120 /*----------------------------------------------------------------------------*/
03138 /*----------------------------------------------------------------------------*/
03139 static int
03140 scdwr(char type_to_write, int id, const char *descr, const void *values, 
03141       int felem, int nval, const int *unit)
03142 {
03143     char type = '-';
03144     int length, bytelem, i;
03145     cpl_property **cards = NULL;
03146     cpl_property **cards_extra = NULL;
03147 
03148 
03149     passure( invariant(id), " ");
03150 
03151     assure( frame_is_open(id), CPL_ERROR_ILLEGAL_INPUT,
03152         "Frame no. %d is not open", id);
03153 
03154     check( cards = get_descr_info(id, descr, 
03155                                   &type, &length, &bytelem),
03156        "Could not get info on descriptor %s", descr);
03157     
03158     if (cards == NULL) {
03159         int number_of_cards = (type_to_write == 'C') ? 1 : (felem-1)+nval;
03160         int nexisting = 0;
03161         
03162         type = type_to_write;
03163         check( cards = create_descr(frames[id].header, descr, type,
03164                                     number_of_cards, nexisting),
03165                "Could not create %d %s descriptors",
03166                number_of_cards, descr);
03167     }
03168     else {
03169         assure( type == type_to_write ||
03170                 (type == 'D' && type_to_write == 'R'),
03171                 CPL_ERROR_TYPE_MISMATCH,
03172                 "Cannot write type %c data to type %c descriptor %s",
03173                 type_to_write, type, descr);
03174         
03175         if (type_to_write != 'C' &&
03176             (felem-1) + nval > length)
03177             /* Create additional descriptors */
03178             {
03179                 int number_of_extra = (felem-1) + nval - length;
03180                 int ncards;
03181                 
03182                 /* Count existing descriptors */
03183                 ncards = 0;
03184                 while(cards[ncards] != NULL) ncards++;
03185                 
03186                 uves_msg_debug("Only %d existing %s descriptor(s), add another %d",
03187                                ncards, descr, number_of_extra);
03188                 
03189                 check( cards_extra
03190                        = create_descr(frames[id].header, descr, type,
03191                                       number_of_extra, ncards),
03192                        "Could not create %d %s descriptors",
03193                        number_of_extra, descr);
03194                 
03195                 /* Append to existing */
03196                 cards = cpl_realloc(cards, (ncards + number_of_extra + 1)*sizeof(cpl_property *));
03197                 
03198                 for (i = ncards; i < ncards + number_of_extra; i++)
03199                     {
03200                         cards[i] = cards_extra[i-ncards];
03201                     }
03202                 
03203                 cards[ncards+number_of_extra] = NULL;
03204             }
03205         else {
03206             uves_msg_debug("Do not add new cards for descriptor %s", descr);
03207         }
03208     }
03209 
03210     /* Properties now exist in correct number, with correct type */
03211     for (i = 0; i < ((type_to_write == 'C') ? 1 : nval); i++) {
03212         if (type_to_write == 'I') {
03213             uves_msg_debug("Writing %d. of %d values (%d) to cards[%d]",
03214                            i+1,
03215                            ((type_to_write == 'C') ? 1 : nval),
03216                            ((const int *)values)[i],
03217                            (felem-1) + i);
03218         }
03219         else {
03220             uves_msg_debug("Writing %d. of %d values to cards[%d]", 
03221                            i+1,
03222                            ((type_to_write == 'C') ? 1 : nval),
03223                            (felem-1) + i);
03224         }
03225         
03226         /* Allow conversion float -> double */
03227         switch(type_to_write) {
03228         case 'I': cpl_property_set_int (cards[(felem-1) + i], ((const int *)values)[i]); break;
03229         case 'R': 
03230             switch(type) {
03231             case 'R':
03232                 cpl_property_set_float (cards[(felem-1) + i], ((const float *)values)[i]); break;
03233             case 'D':
03234                 cpl_property_set_double(cards[(felem-1) + i], ((const float *)values)[i]); break;
03235             default:
03236                 assure( false, CPL_ERROR_UNSUPPORTED_MODE,
03237                         "Cannot write type '%c' values to type '%c' descriptor",
03238                         type_to_write, type);
03239                 break;
03240             }
03241             break;
03242         case 'C': cpl_property_set_string(cards[(felem-1) + i], (const char *)values); break;
03243         case 'D': cpl_property_set_double(cards[(felem-1) + i], ((const double *)values)[i]); break;
03244         default: 
03245             assure( false,CPL_ERROR_UNSUPPORTED_MODE, "Implement me"); break;
03246         }
03247 
03248     }
03249     
03250     /* unit not implemented by MIDAS */
03251     
03252     frames[id].need_to_save = true;
03253     /* and in order to be able to save the header with CPL,
03254        we need to also have the image in memory (if not already) */
03255     check( load_frame(id),
03256            "Could not load frame %s", frames[id].filename );
03257 
03258     passure( invariant(id), " ");
03259 
03260   cleanup:
03261     cpl_free(cards); cards = NULL;
03262     cpl_free(cards_extra); cards_extra = NULL;
03263     
03264     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03265 }
03266 
03267 /*----------------------------------------------------------------------------*/
03273 /*----------------------------------------------------------------------------*/
03274 int flames_midas_scdwri(int id, const char *descr, const int *values, 
03275             int felem, int nval, const int *unit)
03276 {
03277     if (strcmp(descr, "NPIX") == 0)
03278     /* MIDAS  NPIXi maps to FITS NAXISi */
03279     {
03280         cpl_type type;
03281         int *buffer_int=NULL;
03282         float *buffer_float=NULL;
03283         double *buffer_double=NULL;
03284         int size=0;
03285         
03286         assure( nval == 1 || nval == 2 || nval == 3 || nval == 4, 
03287                 CPL_ERROR_UNSUPPORTED_MODE,
03288                 "Only 2d, 3d and 4d (not %dd) images supported", 
03289                 nval);
03290         
03291         assure( frames[id].is_image, CPL_ERROR_ILLEGAL_INPUT,
03292                 "Cannot write NPIX to table %s", frames[id].filename);
03293         
03294         switch(nval) {
03295         case 1: size = values[0]; break;
03296         case 2: size = values[0] * values[1]; break;
03297         case 3: size = values[0] * values[1] * values[2]; break;
03298             case 4: size = values[0] * values[1] * values[2] * values[3]; break;
03299         default:
03300             passure( false, "Impossible");
03301             break;
03302         }
03303 
03304         if (frames[id].data.image.image == NULL) {
03305             frames[id].data.image.image = 
03306                 cpl_image_new(size, 1, 
03307                               frames[id].data.image.type);
03308         }
03309         
03310         assure( size == 
03311                 cpl_image_get_size_x(frames[id].data.image.image) *
03312                 cpl_image_get_size_y(frames[id].data.image.image), 
03313                 CPL_ERROR_INCOMPATIBLE_INPUT,
03314                 "Cannot set image %s NAXIS to %d because the "
03315                 "image memory buffer size is %" CPL_SIZE_FORMAT "",
03316                 frames[id].filename, 
03317                 size,
03318                 cpl_image_get_size_x(frames[id].data.image.image) *
03319                 cpl_image_get_size_y(frames[id].data.image.image));
03320         
03321         /* Now unwrap + wrap the image structure, but keep
03322            the buffer unchanged */
03323         type = cpl_image_get_type(frames[id].data.image.image);
03324         if (nval == 2) {
03325             /* This is redundant now that NAXIS is overwritten when closing */
03326             uves_msg_debug("Setting image %s (type %s) size to %dx%d",
03327                            frames[id].filename,
03328                            uves_tostring_cpl_type(type),
03329                            values[0], values[1]);
03330             switch(type) {
03331             case CPL_TYPE_INT   : buffer_int    = cpl_image_get_data_int(frames[id].data.image.image); break;
03332             case CPL_TYPE_FLOAT : buffer_float  = cpl_image_get_data_float(frames[id].data.image.image); break;
03333             case CPL_TYPE_DOUBLE: buffer_double = cpl_image_get_data_double(frames[id].data.image.image); break;
03334             default:
03335                 assure( false, CPL_ERROR_INVALID_TYPE, "Type is %s",
03336                         uves_tostring_cpl_type(type));
03337                 break;
03338             }
03339 
03340                 
03341             /* Deallocate, except buffer */
03342             cpl_image_unwrap(frames[id].data.image.image);
03343                 
03344             switch(type) {
03345             case CPL_TYPE_INT   : frames[id].data.image.image = cpl_image_wrap_int   (values[0], values[1], buffer_int); break;
03346             case CPL_TYPE_FLOAT : frames[id].data.image.image = cpl_image_wrap_float (values[0], values[1], buffer_float); break;
03347             case CPL_TYPE_DOUBLE: frames[id].data.image.image = cpl_image_wrap_double(values[0], values[1], buffer_double); break;
03348             default:
03349                 assure( false, CPL_ERROR_INVALID_TYPE, "Type is %s",
03350                         uves_tostring_cpl_type(type));
03351                 break;
03352             }
03353 
03354         }
03355         else {
03356             /* for 3d, 4d images don't change the CPL
03357                image axes. NAXISi will be overwritten when saving */
03358         }
03359     }
03360     
03361     scdwr('I', id, descr, values, felem, nval, unit);
03362     
03363   cleanup:
03364     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03365 }
03366 
03367 /*----------------------------------------------------------------------------*/
03373 /*----------------------------------------------------------------------------*/
03374 int flames_midas_scdwrd(int id, const char *descr, const double *values, 
03375                         int felem, int nval, const int *unit)
03376 {
03377     if (strcmp("CRPIX", descr) == 0 ||
03378         strcmp("CRVAL", descr) == 0 ||
03379         strcmp("CDELT", descr) == 0) {
03380         int i;
03381         bool success = true;
03382         
03383         for (i = felem; i < felem+nval; i++) {
03384             char descr_i[10];
03385             
03386             sprintf(descr_i, "%s%i", descr, i);
03387             success = success &&
03388                 (flames_midas_scdwrd(id, descr_i, &values[i-felem], 
03389                                      felem, 1, unit) == 0);
03390         }
03391 
03392         return success ? 0 : 1;
03393     }
03394     
03395     return scdwr('D', id, descr, values, felem, nval, unit);
03396 }
03397 
03398 /*----------------------------------------------------------------------------*/
03404 /*----------------------------------------------------------------------------*/
03405 int flames_midas_scdwrr(int id, const char *descr, const float *values, 
03406                         int felem, int nval, const int *unit)
03407 {
03408     if (strcmp("LHCUTS", descr) == 0 && felem < 3) {
03409         int i;
03410         bool success = true;
03411             
03412         for (i = felem; i < felem+nval; i++)
03413             {
03414                 if (1 <= i && i <= 2)
03415                     {
03416                         uves_msg_debug("Do not write LHCUTS%d", i);
03417                     }
03418                 else if (i == 3)
03419                     {
03420                         double val = (double) values[i-felem-1];
03421                         success = success &&
03422                             (flames_midas_scdwrd(id, "DATAMIN", &val, 
03423                                                  1, 1, unit) == 0);
03424                     }
03425                 else if (i == 4)
03426                     {
03427                         double val = (double) values[i-felem-1];
03428                         success = success &&
03429                             (flames_midas_scdwrd(id, "DATAMAX", &val,
03430                                                  1, 1, unit) == 0);
03431                     }
03432                 else
03433                     {
03434                         success = false;
03435                     }
03436             }
03437         return success ? 0 : 1;
03438     }
03439     else
03440     {
03441         return scdwr('R', id, descr, values, felem, nval, unit);
03442     }
03443 }
03444 
03445 /*----------------------------------------------------------------------------*/
03455 /*----------------------------------------------------------------------------*/
03456 int flames_midas_scdwrc(int id, const char *descr, int noelm, const char *values, 
03457                         int felem, int nval, const int *unit)
03458 {
03459     int returnvalue = 1;
03460     char* tmp_string=NULL;
03461 
03462     if (strcmp(descr, "CUNIT") == 0) {
03463         if (noelm == 1) {
03464             char val[17];
03465             int i;
03466 
03467             assure( nval % 16 == 0, CPL_ERROR_UNSUPPORTED_MODE,
03468                     "nval = %d", nval );
03469             /* nval used in FLAMES code are 32, 48, 64 and 80 */
03470 
03471 
03472             strncpy(val, values, 16);
03473             val[16] = '\0';
03474             returnvalue = flames_midas_scdwrc(id, "BUNIT", 1, val, felem, 16, unit);
03475             
03476             for (i = 1; i < nval/16; i++) {
03477                 const char *ctype_i;
03478                 
03479                 switch(i) {
03480                 case 1: ctype_i = "CTYPE1"; break;
03481                 case 2: ctype_i = "CTYPE2"; break;
03482                 case 3: ctype_i = "CTYPE3"; break;
03483                 case 4: ctype_i = "CTYPE4"; break;
03484                 default:
03485                     return 1;
03486                     break;
03487                 }
03488                 
03489                 strncpy(val, values+i*16, 16);
03490                 val[16] = '\0';
03491                 
03492                 if (returnvalue == 0) {
03493                     returnvalue = flames_midas_scdwrc(id, ctype_i, 1, val, felem, 16, unit);
03494                 }
03495             }
03496         }
03497         else {
03498             /* The FLAMES C code has only one call like this.
03499                Implement it by 3 manual calls.
03500             */
03501             assure( nval == 3, CPL_ERROR_UNSUPPORTED_MODE,
03502                     "noelm = %d, nval = %d", noelm, nval);
03503             
03504             /* Yes, here noelm and nval are swapped */
03505             returnvalue = flames_midas_scdwrc(id, "BUNIT",  1, values+0, felem, noelm, unit);
03506             if (returnvalue == 0) {
03507                 returnvalue = flames_midas_scdwrc(id, "CTYPE1", 1, values+1, felem, noelm, unit);
03508             }
03509             if (returnvalue == 0) {
03510                 returnvalue = flames_midas_scdwrc(id, "CTYPE2", 1, values+2, felem, noelm, unit);
03511             }
03512         }
03513     }
03514     else {
03515         assure( noelm == sizeof(char), CPL_ERROR_UNSUPPORTED_MODE, "Implement me" );
03516         assure( felem == 1, CPL_ERROR_UNSUPPORTED_MODE, "Implement me" );
03517         
03518         /* nval is the string length */
03519         tmp_string=cpl_calloc((nval+1),sizeof(char));
03520         strncpy(tmp_string,values,nval);    
03521         returnvalue = scdwr('C', id, descr, tmp_string, felem, nval, unit);
03522         
03523     }
03524     
03525   cleanup:
03526     cpl_free(tmp_string);
03527     return returnvalue;    
03528 }
03529 
03530 /*----------------------------------------------------------------------------*/
03537 /*----------------------------------------------------------------------------*/
03538 int flames_midas_scddel(int id, const char *descr)
03539 {
03540     cpl_property **cards = NULL;
03541     char type;
03542     int length, bytelem;
03543     const char *fits_descr = NULL;
03544     const char *name_regexp = NULL;
03545 
03546     passure( invariant(id), " ");
03547 
03548     assure( frame_is_open(id), CPL_ERROR_ILLEGAL_INPUT,
03549         "Frame no. %d is not open", id );
03550 
03551     /* Need to convert from MIDAS names to CPL propertylist names */
03552     check( cards = get_descr_info(id, descr, &type,
03553                                   &length, &bytelem),
03554        "Could not get info on descriptor %s", descr);
03555 
03556     if (cards != NULL)
03557         {
03558             int i;
03559             
03560             frames[id].need_to_save = true;
03561 
03562             for (i = 1; i <= length; i++)
03563                 {
03564                     int invert = 0;
03565                     uves_free_string_const(&fits_descr);        
03566                     check( fits_descr = convert_to_fits(descr, i),
03567                            "Could not convert %s to FITS", descr);
03568 
03569                     /* uves_propertylist_erase() will  erase only the first
03570                        property with the given name. We want to erase all matches
03571                     */
03572 
03573                     uves_free_string_const(&fits_descr);        
03574                     name_regexp = uves_sprintf("^%s$", fits_descr);
03575                     uves_propertylist_erase_regexp(frames[id].header, name_regexp, invert);
03576                 }
03577     }
03578 
03579     passure( invariant(id), " ");
03580 
03581   cleanup:
03582     uves_free_string_const(&fits_descr);        
03583     uves_free_string_const(&name_regexp);
03584     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03585 }
03586 
03587 /*----------------------------------------------------------------------------*/
03608 /*----------------------------------------------------------------------------*/
03609 
03610 static int scdcop(int from, int to, int mask, bool copy_naxis)
03611 {
03612     const char *key = NULL;
03613     passure( invariant(from), " ");
03614     passure( invariant(to  ), " ");
03615 
03616     assure( frame_is_open(from), CPL_ERROR_ILLEGAL_INPUT,
03617             "Image no. %d is not open", from);
03618     
03619     assure( frame_is_open(to), CPL_ERROR_ILLEGAL_INPUT,
03620             "Image no. %d is not open", to);
03621     
03622     check( load_frame_header(from),
03623        "Could not load header of file %s", frames[from].filename);
03624 
03625     check( load_frame_header(to),
03626        "Could not load header of file %s", frames[to].filename);
03627 
03628     switch (mask) {
03629     case 1:
03630         /* copy all */
03631         if (0)
03632             {
03633                 /* This would just append */
03634                 uves_propertylist_append(frames[to].header, frames[from].header);
03635             }
03636         else
03637             {
03638                 /* overwrites existing descriptors */
03639                 if (copy_naxis) {
03640                     uves_propertylist_copy_property_regexp(frames[to].header, 
03641                                                            frames[from].header,
03642                                                            ".*", 0);
03643                 }
03644                 else {
03645                     uves_propertylist_copy_property_regexp(frames[to].header, 
03646                                                            frames[from].header,
03647                                                            "^NAXIS", 1);
03648                 }
03649             }
03650         uves_msg_debug("%s header now contains %ld descriptors",
03651                        frames[to].filename, uves_propertylist_get_size(frames[to].header));
03652         
03653         break;
03654     case 3:
03655         assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me");     
03656         break;
03657     default:
03658         /* Not needed for FLAMES code */
03659         assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me");
03660     }
03661 
03662     /* Need to change size of image */
03663     if (frames[from].is_image && copy_naxis) {
03664         int naxis = uves_propertylist_get_int(frames[from].header, "NAXIS");
03665         int axis;
03666         int unit;
03667         int n[2];
03668 
03669         uves_msg_debug("Manually propagating NPIX");
03670 
03671         assure( naxis == 2, CPL_ERROR_UNSUPPORTED_MODE,
03672                 "NAXIS = %d", naxis );
03673 
03674         for (axis = 1; axis <= naxis; axis++) {
03675             uves_free_string_const(&key);
03676             key = uves_sprintf("NAXIS%d", axis);
03677             n[axis-1] = uves_propertylist_get_int(frames[from].header, key);
03678         }
03679 
03680         check_nomsg( flames_midas_scdwri(to, "NPIX", n,
03681                                          1, 2, &unit));
03682     }
03683     
03684     frames[to].need_to_save = true;
03685     check( load_frame(to),
03686        "Could not load image %s", frames[to].filename);
03687 
03688     passure( invariant(from), " ");
03689     passure( invariant(to  ), " ");
03690 
03691   cleanup:
03692     uves_free_string_const(&key);
03693     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03694 }
03695 
03696 /*----------------------------------------------------------------------------*/
03703 /*----------------------------------------------------------------------------*/
03704 int flames_midas_scdcop(int from, int to, int mask)
03705 {
03706     return scdcop(from, to, mask, true);
03707 }
03708 
03709 /*----------------------------------------------------------------------------*/
03716 /*----------------------------------------------------------------------------*/
03717 int flames_midas_scdcop_nonaxis(int from, int to, int mask)
03718 {
03719     return scdcop(from, to, mask, false);
03720 }
03721 
03722 /*----------------------------------------------------------------------------*/
03733 /*----------------------------------------------------------------------------*/
03734 int flames_midas_sccsho(const cpl_frameset *catfile,
03735                         int *noent, 
03736                         int *last)
03737 {
03738     *last=*last; //to remove compilation warning: this is not used
03739     assure_nomsg( catfile != NULL, CPL_ERROR_NULL_INPUT );
03740     assure_nomsg( noent != NULL, CPL_ERROR_NULL_INPUT );
03741 
03742     *noent = cpl_frameset_get_size(catfile);
03743 
03744     //fixme: is 'last' used by any caller? If so, how is it different from 'noent'?
03745     
03746   cleanup:
03747     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03748 }
03749 
03750 
03751 /*----------------------------------------------------------------------------*/
03759 /*----------------------------------------------------------------------------*/
03760 int flames_midas_sccfnd(const cpl_frameset *catfile, 
03761                         int frmno, 
03762                         char *frame)
03763 {
03764     const cpl_frame *f;
03765     
03766     assure_nomsg( catfile != NULL, CPL_ERROR_NULL_INPUT );
03767     assure_nomsg( frame != NULL, CPL_ERROR_NULL_INPUT );
03768     frame[0] = '\0';
03769 
03770     check( f = cpl_frameset_get_frame_const(catfile, frmno-1), /* CPL counts from zero */
03771            "Could not get frame no. %d from catalog", frmno);
03772 
03773     strcpy(frame, cpl_frame_get_filename(f));
03774 
03775     uves_msg_debug("Returning frame %s", cpl_frame_get_filename(f));
03776 
03777   cleanup:
03778     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03779 }
03780 /*----------------------------------------------------------------------------*/
03797 /*----------------------------------------------------------------------------*/
03798 int flames_midas_sccget(const cpl_frameset *catfile,
03799                         int flag,
03800                         char *name, char *ident, 
03801                         int *no)
03802 {
03803     const char *fits_descr = NULL;
03804     uves_propertylist *header = NULL;
03805     
03806     assure_nomsg( catfile != NULL, CPL_ERROR_NULL_INPUT );
03807     assure_nomsg( no      != NULL, CPL_ERROR_NULL_INPUT );
03808     assure_nomsg( name    != NULL, CPL_ERROR_NULL_INPUT );
03809     assure_nomsg( flag == 0 || ident != NULL, CPL_ERROR_NULL_INPUT );
03810 
03811     if (*no == cpl_frameset_get_size(catfile))
03812         {
03813             *name = ' ';
03814             *no += 1;
03815 
03816             uves_msg_debug("Returning frame ' '");
03817         }
03818     else
03819         {
03820             const cpl_frame *f;
03821             check( f = cpl_frameset_get_frame_const(catfile, *no),
03822                    "Could not get frame no. %d from catalog", *no);
03823             
03824             *no += 1;
03825             strcpy(name, cpl_frame_get_filename(f));
03826 
03827             if (flag != 0) {
03828                 const char *ident_value;
03829                 
03830                 check( header = uves_propertylist_load(name, 0),
03831                        "Failed to load %s header", name);
03832 
03833                 if (false) {
03834                     check_nomsg( fits_descr = convert_to_fits(ident, 1) );
03835                 }
03836                 else {
03837                     fits_descr = uves_sprintf("%s", "OBJECT");
03838                 }
03839 
03840                 if (uves_propertylist_contains(header, fits_descr)) {
03841                     check_nomsg( ident_value = 
03842                                  uves_propertylist_get_string(header, fits_descr));
03843                 }
03844                 else {
03845                     ident_value = " ";
03846                 }
03847                 
03848 
03849                 /* Unsafe by design of this function */
03850                 strcpy(ident, ident_value);
03851 
03852                 /* Pad with blanks until strlen = 40 */
03853                 {
03854                     int i;
03855                     i = strlen(ident);
03856                     while (i <= 39) {
03857                         ident[i] = ' ';
03858                         i++;
03859                     }
03860                     ident[i] = '\0';
03861                 }
03862                 
03863                 uves_msg_debug("Returning ident '%s'", ident);
03864 
03865                 /* previously 
03866                    strcpy(ident, cpl_frame_get_tag(f));
03867                 */
03868                }
03869 
03870             uves_msg_debug("Returning frame %s", name);
03871         }
03872     
03873 
03874   cleanup: 
03875     uves_free_propertylist(&header);
03876     uves_free_string_const(&fits_descr);
03877 
03878     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03879 }
03880 
03881 /*----------------------------------------------------------------------------*/
03894 /*----------------------------------------------------------------------------*/
03895 int flames_midas_scccre(cpl_frameset **catfile, 
03896                         int type,
03897                         int flag)
03898 {
03899     assure_nomsg( catfile != NULL, CPL_ERROR_NULL_INPUT );
03900 
03901     /* These parameters always have these values in the FLAMES code */
03902     assure( type == F_IMA_TYPE, CPL_ERROR_UNSUPPORTED_MODE,
03903             "Implement me");
03904     assure(flag == 0, CPL_ERROR_UNSUPPORTED_MODE,
03905            "Implement me");
03906 
03907     *catfile = cpl_frameset_new();
03908 
03909   cleanup: 
03910     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03911 }
03912 
03913 /*----------------------------------------------------------------------------*/
03926 /*----------------------------------------------------------------------------*/
03927 int flames_midas_sccadd(cpl_frameset *catfile,
03928             const char *name,
03929             const char *ident)
03930 {
03931   //const char *fits_descr = NULL;
03932     cpl_frame* frame = NULL;
03933     //uves_propertylist *header = NULL;
03934 
03935     assure_nomsg( catfile != NULL, CPL_ERROR_NULL_INPUT );
03936     assure_nomsg( name    != NULL, CPL_ERROR_NULL_INPUT );
03937     assure_nomsg( ident   != NULL, CPL_ERROR_NULL_INPUT );
03938 
03939     frame = cpl_frame_new();
03940     cpl_frame_set_filename(frame, name);
03941     cpl_frame_set_tag(frame, "dummy"); /* need for cpl_frameset_insert() */
03942     cpl_frameset_insert(catfile, frame);
03943 
03944     /* In principle, we should here update the 
03945        OBJECT fits card with the provided ident string.
03946        However this ident string is always a blank. 
03947        Therefore do not update OBJECT which is very difficult to do with CPL */
03948 
03949     {
03950         int i = 0;
03951         while(ident[i] != '\0') {
03952             assure( ident[i] == ' ', CPL_ERROR_UNSUPPORTED_MODE,
03953                     "Blank ident string expected. Received '%s'",
03954                     ident);
03955             i++;
03956         }
03957     }
03958 
03959     /* previously
03960        cpl_frame_set_tag(frame, ident);
03961     */
03962 
03963   cleanup: 
03964     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03965 }
03966 
03967 /*----------------------------------------------------------------------------*/
03973 /*----------------------------------------------------------------------------*/
03974 static cpl_type
03975 table_dtype_to_cpltype(int dtype, int alen)
03976 {
03977     cpl_type type = CPL_TYPE_INVALID;
03978 
03979     /* Only these combinations are used in FLAMES code */
03980     assure( dtype == D_I4_FORMAT ||
03981             dtype == D_R8_FORMAT ||
03982             dtype == D_R4_FORMAT ||
03983             dtype == D_C_FORMAT, CPL_ERROR_UNSUPPORTED_MODE,
03984             "dtype = %d", dtype);
03985     
03986     assure( dtype == D_C_FORMAT || alen == 1, CPL_ERROR_UNSUPPORTED_MODE,
03987             "dtype = %d, alen = %d", dtype, alen);
03988     
03989     switch(dtype) {
03990     case D_I4_FORMAT: type = CPL_TYPE_INT; break;
03991     case D_R4_FORMAT: type = CPL_TYPE_FLOAT; break;
03992     case D_R8_FORMAT: type = CPL_TYPE_DOUBLE; break;
03993     case D_C_FORMAT: type = CPL_TYPE_STRING; break;
03994     default:
03995         /* impossible */
03996         passure( false, " ");
03997         break;
03998     }    
03999 
04000   cleanup:
04001     return type;
04002 }
04003 
04004 /*----------------------------------------------------------------------------*/
04010 /*----------------------------------------------------------------------------*/
04011 static int
04012 sizeof_cpltype(cpl_type type)
04013 {
04014     switch(type) {
04015         /* These correspondences are documented in CPL */
04016     case CPL_TYPE_INT:    return sizeof(int); break;
04017     case CPL_TYPE_FLOAT:  return sizeof(float); break;
04018     case CPL_TYPE_DOUBLE: return sizeof(double); break;
04019     case CPL_TYPE_STRING: return sizeof(char); break;
04020     default:
04021         assure( false, CPL_ERROR_UNSUPPORTED_MODE,
04022                 "Cannot convert CPL type %s", uves_tostring_cpl_type(type));
04023         break;
04024     }
04025 
04026   cleanup:
04027     return 0;
04028 }
04029 
04030 /*----------------------------------------------------------------------------*/
04036 /*----------------------------------------------------------------------------*/
04037 static int
04038 table_cpltype_to_dtype(cpl_type type)
04039 {
04040     int dtype = -1;
04041     
04042     switch(type) {
04043     case CPL_TYPE_INT:    dtype = D_I4_FORMAT; break;
04044     case CPL_TYPE_FLOAT:  dtype = D_R4_FORMAT; break;
04045     case CPL_TYPE_DOUBLE: dtype = D_R8_FORMAT; break;
04046     case CPL_TYPE_STRING: dtype = D_C_FORMAT; break;
04047     default:
04048         assure( false, CPL_ERROR_UNSUPPORTED_MODE,
04049                 "Cannot convert CPL type %s", uves_tostring_cpl_type(type));
04050         break;
04051     }
04052 
04053   cleanup:
04054     return dtype;
04055 }
04056 
04057 /*----------------------------------------------------------------------------*/
04064 /*----------------------------------------------------------------------------*/
04065 static const char *
04066 table_colname_from_number(int tid, int column)
04067 {
04068     const char *name = NULL;
04069 
04070     passure( invariant(tid), " ");
04071     
04072     assure( frame_is_open(tid) && !frames[tid].is_image, CPL_ERROR_ILLEGAL_INPUT,
04073         "Table %d is not open", tid);
04074     
04075     check( load_frame(tid), "Could not load table %s", frames[tid].filename);
04076 
04077     assure( 1 <= column && column <= cpl_table_get_nrow(frames[tid].data.table.colnames),
04078             CPL_ERROR_ACCESS_OUT_OF_RANGE,
04079             "Illegal column number %d. Table has %" CPL_SIZE_FORMAT " row(s)",
04080             column, cpl_table_get_nrow(frames[tid].data.table.colnames));
04081 
04082     name = cpl_table_get_string(frames[tid].data.table.colnames, COLNAME,
04083                                 column - 1);
04084 
04085   cleanup:
04086     return name;
04087 }
04088 
04089 /*----------------------------------------------------------------------------*/
04103 /*----------------------------------------------------------------------------*/
04104 int flames_midas_tctopn(const char *name, int mode, int allrow, int *tid)
04105 {
04106     assure( allrow == -1 || mode == F_O_MODE, CPL_ERROR_INCOMPATIBLE_INPUT,
04107             "allrow = %d, mode = %d", allrow, mode);
04108 
04109     if (mode == F_I_MODE || mode == F_IO_MODE || mode == F_O_MODE)
04110     {
04111         /* Find first open slot */
04112         int i;
04113         bool found = false;
04114         for (i = 0; !found && i < MAX_OPEN; i++)
04115         {
04116             if (! frame_is_open(i))
04117             {
04118                 found = true;
04119                 *tid = i;
04120 
04121                 if (mode == F_I_MODE || mode == F_IO_MODE)   /* Input */
04122                     {
04123                         frame_new_table(i, name, NULL, false,
04124                                         NULL, 0, NULL);
04125                     }
04126                 else if (mode == F_O_MODE)   /* Output */
04127                     {
04128                         cpl_table *colnames = cpl_table_new(0);
04129                         cpl_table_new_column(colnames,
04130                                              COLNAME, CPL_TYPE_STRING);
04131                         
04132                         frame_new_table(i, name, uves_propertylist_new(), true,
04133                                         cpl_table_new(allrow), 0, colnames);
04134                         
04135                     }
04136                 
04137                 uves_msg_debug("Opened table no. %d: %s",
04138                        i, name);
04139             }
04140         }
04141         
04142         assure( found, CPL_ERROR_UNSUPPORTED_MODE,
04143             "Cannot open more than %d table files",
04144             MAX_OPEN);
04145     }
04146     else
04147     {
04148         assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me");
04149     }
04150 
04151     passure( invariant(*tid), " ");
04152 
04153   cleanup:
04154     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04155 }
04156 
04157 /*----------------------------------------------------------------------------*/
04164 /*----------------------------------------------------------------------------*/
04165 int flames_midas_tctclo(int tid)
04166 {
04167     return frame_close(tid);
04168 }
04169 
04170 /*----------------------------------------------------------------------------*/
04184 /*----------------------------------------------------------------------------*/
04185 int flames_midas_tccser(int tid, const char *colref, int *column)
04186 {
04187     bool found;
04188     int i;
04189 
04190     passure( invariant(tid), " ");
04191 
04192     /* The MIDAS interface supports the following, but there is no reason
04193        to do that for the FLAMES code */
04194     assure( colref[0] != ':' &&
04195             colref[0] != '#', CPL_ERROR_UNSUPPORTED_MODE, "Illegal column name: %s",
04196             colref);
04197 
04198     assure( frame_is_open(tid) && !frames[tid].is_image, CPL_ERROR_ILLEGAL_INPUT,
04199         "Table %d is not open", tid);
04200 
04201     check( load_frame(tid), "Could not load table %s", frames[tid].filename);
04202 
04203     *column = -1;
04204     found = false;
04205     for (i = 0; i < cpl_table_get_nrow(frames[tid].data.table.colnames) && !found; i++)
04206         {
04207             const char *name = cpl_table_get_string(frames[tid].data.table.colnames, COLNAME, i);
04208             if (strcmp(name, colref) == 0)
04209                 {
04210                     *column = i + 1; /* counting from 1 */
04211                     found = true;
04212                 }
04213     }
04214 
04215     if (!found) 
04216         {
04217             uves_msg_warning("Table %s has no column %s",
04218                              frames[tid].filename, colref);
04219         }
04220 
04221     passure( invariant(tid), " ");
04222 
04223   cleanup:
04224     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04225 }
04226 
04227 /*----------------------------------------------------------------------------*/
04236 /*----------------------------------------------------------------------------*/
04237 int flames_midas_tciget(int tid, int *column, int *row)
04238 {
04239   //const char *name;
04240 
04241     passure( invariant(tid), " ");
04242 
04243     assure( frame_is_open(tid) && !frames[tid].is_image, CPL_ERROR_ILLEGAL_INPUT,
04244         "Table %d is not open", tid);
04245 
04246     check( load_frame(tid), "Could not load table %s", frames[tid].filename);
04247 
04248     *column = cpl_table_get_ncol(frames[tid].data.table.table) - 1;
04249     /* Return actual number of rows, not allocated */
04250     //*row    = cpl_table_get_nrow(frames[tid].data.table.table);
04251     *row    = frames[tid].data.table.maxrow;
04252 
04253     passure( invariant(tid), " ");
04254 
04255   cleanup:
04256     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04257 }
04258 
04259 /*----------------------------------------------------------------------------*/
04272 /*----------------------------------------------------------------------------*/
04273 int flames_midas_tcbget(int tid, int column, int *dtype, int *items, int *bytes)
04274 {
04275     const char *colname;
04276 
04277     check_nomsg( colname = table_colname_from_number(tid, column) );
04278 
04279     check_nomsg( *dtype = table_cpltype_to_dtype(
04280                      cpl_table_get_column_type(frames[tid].data.table.table, 
04281                                                colname)) );
04282 
04283     /* Note! 
04284        This function is only used in flames_create_full_ordertable.c,
04285        so it only has to work in that case.
04286     */
04287 
04288     *items = 1;
04289 
04290     if (*dtype == D_C_FORMAT) 
04291         {
04292             *bytes = 80 * sizeof_cpltype(
04293                 table_dtype_to_cpltype(*dtype, *items) );
04294         }
04295     else 
04296         {
04297             *bytes = (*items) * sizeof_cpltype(
04298                 table_dtype_to_cpltype(*dtype, *items) );
04299         }
04300 
04301   cleanup:
04302     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04303 }
04304 
04305 /*----------------------------------------------------------------------------*/
04312 /*----------------------------------------------------------------------------*/
04313 int flames_midas_tcdget(int tid, int *store)
04314 {
04315     tid=tid; //to remove compilation warning: this is not used
04316     *store=*store; //to remove compilation warning: this is not used
04317     assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me");
04318   cleanup: return 1;
04319 }
04320 
04321 /*----------------------------------------------------------------------------*/
04330 /*----------------------------------------------------------------------------*/
04331 int flames_midas_tcfget(int tid, int column, char *form, int *dtype)
04332 {
04333     const char *colname;
04334     const char *format;
04335 
04336     check_nomsg( colname = table_colname_from_number(tid, column));
04337     
04338     check_nomsg( *dtype = table_cpltype_to_dtype(
04339                      cpl_table_get_column_type(frames[tid].data.table.table, colname)));
04340 
04341     check_nomsg( format = cpl_table_get_column_format(frames[tid].data.table.table, colname));
04342 
04343     strcpy(form, format);
04344     
04345   cleanup: 
04346     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04347 }
04348 
04349 /*----------------------------------------------------------------------------*/
04357 /*----------------------------------------------------------------------------*/
04358 int flames_midas_tclget(int tid, int column, char *label)
04359 {
04360     const char *colname;
04361 
04362     label[0] = '\0';
04363     check_nomsg( colname = table_colname_from_number(tid, column));
04364 
04365     /* It's up to the caller to allocate enough space */
04366     strcpy(label, colname);
04367     
04368   cleanup:
04369     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04370 }
04371 
04372 /*----------------------------------------------------------------------------*/
04380 /*----------------------------------------------------------------------------*/
04381 int flames_midas_tcuget(int tid, int column, char *unit)
04382 {
04383     const char *colname;
04384     const char *u;
04385 
04386     unit[0] = '\0';
04387     //uves_msg("column=%s \n",column);
04388     check_nomsg( colname = table_colname_from_number(tid, column));
04389     check_nomsg( u = cpl_table_get_column_unit(frames[tid].data.table.table, colname));
04390     assure( u != NULL, CPL_ERROR_ILLEGAL_INPUT, "Column %s unit not set", colname);
04391     
04392     strcpy(unit, u);
04393     
04394   cleanup: 
04395     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04396 }
04397 /*----------------------------------------------------------------------------*/
04406 /*----------------------------------------------------------------------------*/
04407 int flames_midas_tclser(int tid, const char *label, int *column)
04408 {
04409     /* This function seems to be the same as flames_midas_tccser(),
04410        except that
04411        flames_midas_tccser() is case sensitive and allows prefixing
04412        the column name with : or #
04413 
04414        But these subtle differences are not used by the FLAMES code, so
04415        just call that other function */
04416     return flames_midas_tccser(tid, label, column);
04417 }
04418 
04419 /*----------------------------------------------------------------------------*/
04437 /*----------------------------------------------------------------------------*/
04438 int flames_midas_tccini(int tid, int dtype, int alen, 
04439                         const char *form, const char *unit, const char *label, 
04440                         int *column)
04441 {
04442     cpl_type type;
04443 
04444     passure( invariant(tid), " ");
04445     
04446     assure( frame_is_open(tid) && !frames[tid].is_image, CPL_ERROR_ILLEGAL_INPUT,
04447         "Table %d is not open", tid);
04448     
04449     check( load_frame(tid), "Could not load table %s", frames[tid].filename);
04450     
04451     check_nomsg( type = table_dtype_to_cpltype(dtype, alen) );
04452 
04453     uves_msg_debug("Creating column %s (unit = %s, format = %s)",
04454                    label, unit, form);
04455 
04456     /* Create the column */
04457     assure( !cpl_table_has_column(frames[tid].data.table.table, label),
04458             CPL_ERROR_ILLEGAL_OUTPUT,
04459             "Column %s already exists", label);
04460     cpl_table_new_column       (frames[tid].data.table.table, label, type);
04461     cpl_table_set_column_format(frames[tid].data.table.table, label, form);
04462     cpl_table_set_column_unit  (frames[tid].data.table.table, label, unit);
04463 
04464     /* Initialize column to avoid garbage (CPL doesn't initialize NULL elements) */
04465     switch(type) {
04466     case CPL_TYPE_INT   : cpl_table_fill_invalid_int   (frames[tid].data.table.table, label, -1); break;
04467     case CPL_TYPE_FLOAT : cpl_table_fill_invalid_float (frames[tid].data.table.table, label, -1); break;
04468     case CPL_TYPE_DOUBLE: cpl_table_fill_invalid_double(frames[tid].data.table.table, label, -1); break;
04469     case CPL_TYPE_STRING: /* Do nothing, already NULL */ break;
04470     default:
04471         passure( false, " " );
04472         break;
04473     }
04474 
04475     /* Update description of columns */
04476     *column = cpl_table_get_ncol(frames[tid].data.table.table) - 1;
04477     cpl_table_set_size  (frames[tid].data.table.colnames, *column);  /* This is O(n^2) in the number of 
04478                                                              columns (i.e. slow if there are
04479                                                              many columns, but the CPL table 
04480                                                              handling is like that anyway. */
04481     cpl_table_set_string(frames[tid].data.table.colnames, COLNAME, *column-1, label);
04482 
04483     passure( invariant(tid), " ");
04484 
04485   cleanup:
04486     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04487 }
04488 
04489 /*----------------------------------------------------------------------------*/
04504 /*----------------------------------------------------------------------------*/
04505 static int
04506 tcerd(cpl_type type, int tid, int row, int column,
04507       void *value, int *null)
04508 {
04509     const char *colname;
04510     const char *val_str;
04511 
04512     check_nomsg( colname = table_colname_from_number(tid, column));
04513 
04514     /* Check disabled, allow type conversion 
04515     assure( cpl_table_get_column_type(frames[tid].data.table.table, colname)
04516             == type, CPL_ERROR_TYPE_MISMATCH, "Column %s type is %s, type %s expected",
04517             colname, uves_tostring_cpl_type(cpl_table_get_column_type(frames[tid].data.table.table, colname)),
04518             uves_tostring_cpl_type(type) );
04519     */
04520 
04521     assure( 1 <= row && row <= cpl_table_get_nrow(frames[tid].data.table.table),
04522             CPL_ERROR_ACCESS_OUT_OF_RANGE,
04523             "Cannot read row %d of %" CPL_SIZE_FORMAT " row table",
04524             row, cpl_table_get_nrow(frames[tid].data.table.table));
04525 
04526     switch(type) {
04527     case CPL_TYPE_INT:
04528         ((int *)value)[0] = cpl_table_get(frames[tid].data.table.table,
04529                                           colname, row - 1,
04530                                           null);
04531         break;
04532     case CPL_TYPE_FLOAT:
04533         ((float *)value)[0] = cpl_table_get(frames[tid].data.table.table,
04534                                             colname, row - 1,
04535                                             null);
04536         break;
04537     case CPL_TYPE_DOUBLE:
04538         ((double *)value)[0] = cpl_table_get(frames[tid].data.table.table,
04539                                              colname, row - 1,
04540                                              null);
04541         break;
04542     case CPL_TYPE_STRING:
04543         val_str = cpl_table_get_string(frames[tid].data.table.table,
04544                                        colname, row - 1);
04545         if (val_str == NULL)
04546             {
04547                 if (null != NULL) *null = 1;
04548                 ((char *)value)[0] = '\0';
04549             }
04550         else
04551             {
04552                 if (null != NULL) *null = 0;
04553                 strcpy((char *)value, val_str);
04554             }
04555         break;
04556     default:
04557         assure( false, CPL_ERROR_INVALID_TYPE, "Type is %s", uves_tostring_cpl_type(type));
04558         break;
04559     }
04560 
04561   cleanup:
04562     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04563 }
04564 
04565 /*----------------------------------------------------------------------------*/
04572 /*----------------------------------------------------------------------------*/
04573 int flames_midas_tcerdc(int tid, int row, int column, char *values, int *null)
04574 {
04575     return tcerd(CPL_TYPE_STRING, tid, row, column, values, null);
04576 }
04577 
04578 /*----------------------------------------------------------------------------*/
04582 /*----------------------------------------------------------------------------*/
04583 int flames_midas_tcerdi(int tid, int row, int column, int *value, int *null)
04584 {
04585     return tcerd(CPL_TYPE_INT, tid, row, column, value, null);
04586 }
04587 
04588 /*----------------------------------------------------------------------------*/
04592 /*----------------------------------------------------------------------------*/
04593 int flames_midas_tcerdr(int tid, int row, int column, float *value, int *null)
04594 {
04595     return tcerd(CPL_TYPE_FLOAT, tid, row, column, value, null);
04596 }
04597 
04598 /*----------------------------------------------------------------------------*/
04602 /*----------------------------------------------------------------------------*/
04603 int flames_midas_tcerdd(int tid, int row, int column,
04604             double *value, int *null)
04605 {
04606     return tcerd(CPL_TYPE_DOUBLE, tid, row, column, value, null);
04607 }
04608 
04609 /*----------------------------------------------------------------------------*/
04621 /*----------------------------------------------------------------------------*/
04622 static int tcewr(cpl_type type, int tid, int row, int column, const void *value)
04623 {
04624     const char *colname;
04625     
04626     check_nomsg( colname = table_colname_from_number(tid, column));
04627     
04628     /* Check disabled, allow type mismatch and conversion (as in MIDAS)
04629     assure( cpl_table_get_column_type(frames[tid].data.table.table, colname)
04630             == type, CPL_ERROR_TYPE_MISMATCH, "Column %s has type %s; %s expected",
04631             colname, uves_tostring_cpl_type(cpl_table_get_column_type(frames[tid].data.table.table, colname)),
04632             uves_tostring_cpl_type(type) );
04633     */
04634 
04635     assure( row <= cpl_table_get_nrow(frames[tid].data.table.table),
04636             CPL_ERROR_ACCESS_OUT_OF_RANGE,
04637             "Cannot write row %d from %" CPL_SIZE_FORMAT " row table",
04638             row, cpl_table_get_nrow(frames[tid].data.table.table));
04639 
04640     if (row > frames[tid].data.table.maxrow) {
04641         frames[tid].data.table.maxrow = row;
04642     }
04643 
04644     switch(type) {
04645     case CPL_TYPE_INT:    
04646         cpl_table_set(frames[tid].data.table.table, colname, row - 1, ((const int *)value)[0]); 
04647         break;
04648     case CPL_TYPE_FLOAT:
04649         cpl_table_set(frames[tid].data.table.table, colname, row - 1, ((const float *)value)[0]); 
04650         break;
04651     case CPL_TYPE_DOUBLE: 
04652         cpl_table_set(frames[tid].data.table.table, colname, row - 1, ((const double *)value)[0]); 
04653         break;
04654     case CPL_TYPE_STRING:
04655         cpl_table_set_string(frames[tid].data.table.table, colname, row - 1, (const char *)value); 
04656         break;
04657     default:
04658         assure( false, CPL_ERROR_INVALID_TYPE, "Type is %s", uves_tostring_cpl_type(type));
04659         break;
04660     }
04661 
04662   cleanup:
04663     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04664 }
04665 
04666 /*----------------------------------------------------------------------------*/
04673 /*----------------------------------------------------------------------------*/
04674 int flames_midas_tcewrc(int tid, int row, int column, const char *value)
04675 {
04676     /* Write full string, including commas */
04677     return tcewr(CPL_TYPE_STRING, tid, row, column, value);
04678 }
04679 
04680 /*----------------------------------------------------------------------------*/
04684 /*----------------------------------------------------------------------------*/
04685 int flames_midas_tcewrd(int tid, int row, int column, const double *value)
04686 {
04687     return tcewr(CPL_TYPE_DOUBLE, tid, row, column, value);
04688 }
04689 
04690 /*----------------------------------------------------------------------------*/
04694 /*----------------------------------------------------------------------------*/
04695 int flames_midas_tcewri(int tid, int row, int column, const int *value)
04696 {
04697     return tcewr(CPL_TYPE_INT, tid, row, column, value);
04698 }
04699 /*----------------------------------------------------------------------------*/
04703 /*----------------------------------------------------------------------------*/
04704 int flames_midas_tcewrr(int tid, int row, int column, const float *value)
04705 {
04706     return tcewr(CPL_TYPE_FLOAT, tid, row, column, value);
04707 }
04708 
04709 /*----------------------------------------------------------------------------*/
04713 /*----------------------------------------------------------------------------*/
04714 static int
04715 tcard(cpl_type type, int tid, int row, int column,
04716       int index, int items, void *value)
04717 {
04718     assure( index == 1 && (
04719                 type == CPL_TYPE_STRING ||
04720                 items == 1),
04721             CPL_ERROR_UNSUPPORTED_MODE,
04722             "index, items = %d, %d", index, items);
04723 
04724     return tcerd(type, tid, row, column, value, NULL);
04725 
04726   cleanup:
04727     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04728 }
04729 
04730 /*----------------------------------------------------------------------------*/
04742 /*----------------------------------------------------------------------------*/
04743 int flames_midas_tcardc(int tid, int row, int col, int index, int items, char *value)
04744 {
04745     return tcard(CPL_TYPE_STRING, tid, row, col, index, items, value);
04746 }
04747 
04748 /*----------------------------------------------------------------------------*/
04759 /*----------------------------------------------------------------------------*/
04760 int flames_midas_tcardd(int tid, int row, int col, int index, int items, double *value)
04761 {
04762     return tcard(CPL_TYPE_DOUBLE, tid, row, col, index, items, value);
04763 }
04764 
04765 /*----------------------------------------------------------------------------*/
04769 /*----------------------------------------------------------------------------*/
04770 int flames_midas_tcardi(int tid, int row, int col, int index, int items, int *value)
04771 {
04772     return tcard(CPL_TYPE_INT, tid, row, col, index, items, value);
04773 }
04774 
04775 /*----------------------------------------------------------------------------*/
04779 /*----------------------------------------------------------------------------*/
04780 int flames_midas_tcardr(int tid, int row, int col, int index, int items, float *value)
04781 {
04782     return tcard(CPL_TYPE_FLOAT, tid, row, col, index, items, value);
04783 }
04784 
04785 
04786 /*----------------------------------------------------------------------------*/
04790 /*----------------------------------------------------------------------------*/
04791 static int
04792 tcawr(cpl_type type, int tid, int row, int col, int index, int items, const void *value)
04793 {
04794     assure( index == 1 && (
04795                 type == CPL_TYPE_STRING ||
04796                 items == 1),
04797             CPL_ERROR_UNSUPPORTED_MODE,
04798             "index, items = %d, %d", index, items);
04799     
04800     return tcewr(type, tid, row, col, value);
04801     
04802   cleanup:
04803     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04804 }
04805 
04806 /*----------------------------------------------------------------------------*/
04817 /*----------------------------------------------------------------------------*/
04818 int flames_midas_tcawrc(int tid, int row, int col, int index, int items, const char *value)
04819 {
04820     return tcawr(CPL_TYPE_STRING, tid, row, col, index, items, value);
04821 }
04822 /*----------------------------------------------------------------------------*/
04833 /*----------------------------------------------------------------------------*/
04834 int flames_midas_tcawrd(int tid, int row, int col, int index, int items, const double *value)
04835 {
04836     return tcawr(CPL_TYPE_DOUBLE, tid, row, col, index, items, value);
04837 }
04838 /*----------------------------------------------------------------------------*/
04842 /*----------------------------------------------------------------------------*/
04843 int flames_midas_tcawri(int tid, int row, int col, int index, int items, const int *value)
04844 {
04845     return tcawr(CPL_TYPE_INT, tid, row, col, index, items, value);
04846 }
04847 
04848 /*----------------------------------------------------------------------------*/
04852 /*----------------------------------------------------------------------------*/
04853 int flames_midas_tcawrr(int tid, int row, int col, int index, int items, const float *value)
04854 {
04855     return tcawr(CPL_TYPE_FLOAT, tid, row, col, index, items, value);
04856 }
04857 
04858 /*----------------------------------------------------------------------------*/
04866 /*----------------------------------------------------------------------------*/
04867 int flames_midas_tcsget(int tid, int row, int *value)
04868 {
04869     passure( invariant(tid), " ");
04870     
04871     assure( frame_is_open(tid) && !frames[tid].is_image, CPL_ERROR_ILLEGAL_INPUT,
04872         "Table %d is not open", tid);
04873     
04874     check( load_frame(tid), "Could not load table %s", frames[tid].filename);
04875 
04876     assure( 1 <= row && row <= cpl_table_get_nrow(frames[tid].data.table.table),
04877             CPL_ERROR_ACCESS_OUT_OF_RANGE,
04878             "Cannot read row %d  of %" CPL_SIZE_FORMAT " row table %s", row,
04879             cpl_table_get_nrow(frames[tid].data.table.table),
04880             frames[tid].filename);
04881 
04882     *value = cpl_table_get_int(frames[tid].data.table.table,
04883                                "Select",
04884                                row - 1, NULL);
04885 
04886   cleanup:
04887     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04888 }
04889 
04890 /*----------------------------------------------------------------------------*/
04898 /*----------------------------------------------------------------------------*/
04899 int flames_midas_tcsput(int tid, int row, const int *value)
04900 {
04901     passure( invariant(tid), " ");
04902     
04903     assure( frame_is_open(tid) && !frames[tid].is_image, CPL_ERROR_ILLEGAL_INPUT,
04904         "Table %d is not open", tid);
04905     
04906     check( load_frame(tid), "Could not load table %s", frames[tid].filename);
04907 
04908     assure( 1 <= row && row <= cpl_table_get_nrow(frames[tid].data.table.table),
04909             CPL_ERROR_ACCESS_OUT_OF_RANGE,
04910             "Cannot write to row %d of %" CPL_SIZE_FORMAT " row table %s", row,
04911             cpl_table_get_nrow(frames[tid].data.table.table),
04912             frames[tid].filename);
04913 
04914     cpl_table_set_int(frames[tid].data.table.table, "Select", row - 1, *value);
04915 
04916 
04917     if (row > frames[tid].data.table.maxrow) {
04918         frames[tid].data.table.maxrow = row;
04919     }
04920   cleanup:
04921     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04922 }
04923 

Generated on 3 Mar 2013 for UVES Pipeline Reference Manual by  doxygen 1.6.1