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: 2012/03/02 16:23:15 $
00024  * $Revision: 1.5 $
00025  * $Name: uves-5_0_0 $
00026  * $Log: flames_midas_def.c,v $
00027  * Revision 1.5  2012/03/02 16:23:15  amodigli
00028  * fixed compiler warnings related to CPL6 upgrade
00029  *
00030  * Revision 1.4  2011/12/08 13:58:29  amodigli
00031  * Fox warnings with CPL6
00032  *
00033  * Revision 1.3  2010/09/24 09:32:02  amodigli
00034  * put back QFITS dependency to fix problem spot by NRI on FIBER mode (with MIDAS calibs) data
00035  *
00036  * Revision 1.1  2009/04/14 07:01:07  amodigli
00037  * added to CVS (moded from flames tree)
00038  *
00039  * Revision 1.73  2008/09/29 06:50:32  amodigli
00040  * add #include <string.h>
00041  *
00042  * Revision 1.72  2008/08/29 09:54:04  amodigli
00043  * fixed compiler warning
00044  *
00045  * Revision 1.71  2008/06/26 08:21:58  amodigli
00046  * more silend init/end of MIDAS interface
00047  *
00048  * Revision 1.70  2007/12/10 07:33:52  amodigli
00049  * added support of D_R8_FORMAT
00050  *
00051  * Revision 1.69  2007/10/23 06:44:19  amodigli
00052  * fixed compilation warnings
00053  *
00054  * Revision 1.68  2007/10/01 17:19:34  amodigli
00055  * added scdprs
00056  *
00057  * Revision 1.67  2007/08/30 08:44:16  amodigli
00058  * fixed problem with null strings in convert_to_history and problems with a lengh of a cards in get_descr_info
00059  *
00060  * Revision 1.66  2007/08/21 13:08:25  jmlarsen
00061  * Removed irplib_access module, largely deprecated by CPL-4
00062  *
00063  * Revision 1.65  2007/08/20 08:56:49  amodigli
00064  * fixed bug on termination null char in flames_midas_sckgetc
00065  *
00066  * Revision 1.64  2007/08/16 06:58:09  amodigli
00067  * commented out assure check in flames_convert_to_history to prevent problem with slitff_l_sigma01 and CPL4: was that assure really needed?
00068  *
00069  * Revision 1.63  2007/08/08 08:00:29  amodigli
00070  * update frame_new_table to support input in '.tfits'
00071  *
00072  * Revision 1.62  2007/07/27 06:44:48  amodigli
00073  * Moved several function declarations from flames_uves.h to other new .h files
00074  *
00075  * Revision 1.61  2007/07/26 16:08:28  jmlarsen
00076  * Manually set table column unit to empty string when no unit is given. CPL-3 did that. CPL-4 not
00077  *
00078  * Revision 1.60  2007/07/25 15:55:12  amodigli
00079  * fixed a problem writing char descriptors not null ternimated evidenced with CPL4
00080  *
00081  * Revision 1.59  2007/07/18 15:27:17  jmlarsen
00082  * Added check for NULL pointer
00083  *
00084  * Revision 1.58  2007/07/03 14:04:48  jmlarsen
00085  * Fixed fixmes
00086  *
00087  * Revision 1.57  2007/06/28 09:34:43  jmlarsen
00088  * More useful error message
00089  *
00090  * Revision 1.56  2007/06/26 13:58:07  jmlarsen
00091  * Expand list of special MIDAS keywords
00092  *
00093  * Revision 1.55  2007/06/25 15:45:33  jmlarsen
00094  * Do not write FIBRESON to HISTORY keyword
00095  *
00096  * Revision 1.54  2007/06/22 15:27:49  jmlarsen
00097  * Support read/write of D_I2_FORMAT
00098  *
00099  * Revision 1.53  2007/06/22 14:52:20  jmlarsen
00100  * Exported dtype_to_cpltype function
00101  *
00102  * Revision 1.52  2007/06/22 09:45:59  jmlarsen
00103  * Changed interface of uves_save_image
00104  *
00105  * Revision 1.51  2007/06/20 13:45:02  jmlarsen
00106  * Make sure not to convert some hardcoded FITS keywords to HISTORY format
00107  *
00108  * Revision 1.50  2007/06/20 11:10:46  jmlarsen
00109  * Use CFITSIO, also for 2d images
00110  *
00111  * Revision 1.49  2007/06/19 12:00:05  jmlarsen
00112  * Changed comment
00113  *
00114  * Revision 1.48  2007/06/12 15:19:07  jmlarsen
00115  * Added support for writing CUNIT
00116  *
00117  * Revision 1.47  2007/06/08 15:37:53  jmlarsen
00118  * Bugfix in SCDWR when creating new descriptor
00119  *
00120  * Revision 1.46  2007/06/08 06:41:23  amodigli
00121  * cleaned output
00122  *
00123  * Revision 1.45  2007/06/06 15:28:38  jmlarsen
00124  * And made it compile
00125  *
00126  * Revision 1.44  2007/06/06 15:14:52  jmlarsen
00127  * Fixed memory error
00128  *
00129  * Revision 1.43  2007/06/06 14:05:13  jmlarsen
00130  * SCCADD return value of OBJECT if existing
00131  *
00132  * Revision 1.42  2007/06/06 08:17:33  amodigli
00133  * replace tab with 4 spaces
00134  *
00135  * Revision 1.41  2007/06/06 07:23:59  jmlarsen
00136  * Use property comments to control conversion to/from HISTORY keywords
00137  *
00138  * Revision 1.40  2007/06/05 06:53:54  jmlarsen
00139  * Fixed buffer overrun in SCDRDC
00140  *
00141  * Revision 1.39  2007/06/04 17:08:20  amodigli
00142  * removed compilation warnings
00143  *
00144  * Revision 1.38  2007/06/04 11:26:42  jmlarsen
00145  * Added SCKGETC_fsp for cpl_frameset pointers
00146  *
00147  * Revision 1.37  2007/06/04 06:34:22  amodigli
00148  * added CPL_TYPE_FLOAT support in convert_to_history
00149  *
00150  * Revision 1.36  2007/05/30 16:07:53  jmlarsen
00151  * Support reading 3d, 4d FITS images
00152  *
00153  * Revision 1.35  2007/05/30 14:49:02  jmlarsen
00154  * Support for 3d, 4d FITS images
00155  *
00156  * Revision 1.34  2007/05/29 14:39:48  jmlarsen
00157  * Readded 3d table functions but map them to simple (2d) table functions
00158  *
00159  * Revision 1.33  2007/05/29 13:46:21  jmlarsen
00160  * Removed 3d table column stubs which were not needed for FLAMES
00161  *
00162  * Revision 1.32  2007/05/18 15:41:24  amodigli
00163  * added some info
00164  *
00165  * Revision 1.31  2007/05/16 15:43:39  jmlarsen
00166  * Initial support for 3d images
00167  *
00168  * Revision 1.30  2007/05/16 14:21:52  amodigli
00169  * added debug statements
00170  *
00171  * Revision 1.29  2007/05/16 10:08:38  jmlarsen
00172  * Added .fits to provided filenames if not given
00173  *
00174  * Revision 1.28  2007/05/14 16:13:57  jmlarsen
00175  * Fixed memory leak
00176  *
00177  * Revision 1.27  2007/05/14 16:04:52  jmlarsen
00178  * Bugfix in SCKRD functions
00179  *
00180  * Revision 1.26  2007/05/14 13:25:31  jmlarsen
00181  * Added support for 'allocated' table rows
00182  *
00183  * Revision 1.25  2007/05/11 13:52:48  jmlarsen
00184  * Implemented image buffer read/write functions
00185  *
00186  * Revision 1.24  2007/05/11 09:41:38  jmlarsen
00187  * Support type double in convert_to_history
00188  *
00189  * Revision 1.23  2007/05/10 14:03:15  jmlarsen
00190  * Added workaround for CPL's TNULL handling
00191  *
00192  * Revision 1.22  2007/05/08 14:26:17  jmlarsen
00193  * Implemented table selection flags
00194  *
00195  * Revision 1.21  2007/05/04 14:45:32  amodigli
00196  * added support for D_I1_FORMAT
00197  *
00198  * Revision 1.20  2007/05/04 10:21:13  jmlarsen
00199  * Set image size properly in SCDCOP
00200  *
00201  * Revision 1.19  2007/04/24 12:49:34  jmlarsen
00202  * Replaced cpl_propertylist -> uves_propertylist which is much faster
00203  *
00204  * Revision 1.18  2007/04/24 09:43:10  jmlarsen
00205  * Renamed uves_propertylist_append -> uves_propertylist_append_property
00206  *
00207  * Revision 1.17  2007/04/23 07:01:10  amodigli
00208  * uncommented BKG_XY_WIN_SZ_X BKG_XY_WIN_SZ_Y BKG_MAX_IO_WIN
00209  *
00210  * Revision 1.16  2007/04/20 14:53:29  jmlarsen
00211  * Allow type conversion in table read/write functions
00212  *
00213  * Revision 1.15  2007/04/16 06:50:37  jmlarsen
00214  * Fixed memory leaks
00215  *
00216  * Revision 1.14  2007/04/10 07:31:35  jmlarsen
00217  * Fixed buffer overrun due to use of strcpy
00218  *
00219  * Revision 1.13  2007/04/03 11:05:31  jmlarsen
00220  * Implemented table module
00221  *
00222  * Revision 1.12  2007/03/23 14:11:49  jmlarsen
00223  * Replaced exit system calls with appropriate error handling
00224  *
00225  * Revision 1.11  2007/03/23 13:44:37  jmlarsen
00226  * Implemented SCKWR- functions
00227  *
00228  * Revision 1.10  2007/03/23 10:25:32  amodigli
00229  * implemented sccadd
00230  *
00231  * Revision 1.9  2007/03/23 10:10:14  jmlarsen
00232  * Implemented catalog interface
00233  *
00234  * Revision 1.8  2007/03/23 08:04:55  jmlarsen
00235  * Work on conversion
00236  *
00237  * Revision 1.7  2007/03/15 15:05:33  jmlarsen
00238  * More implementation
00239  *
00240  * Revision 1.6  2007/03/05 09:40:53  jmlarsen
00241  * Work on SCDCOP
00242  *
00243  * Revision 1.5  2007/02/27 14:09:31  jmlarsen
00244  * Extended interface of uves_find_property
00245  *
00246  * Revision 1.4  2007/01/31 13:14:54  jmlarsen
00247  * Initial implementation of SCFGET
00248  *
00249  * Revision 1.3  2007/01/29 13:09:55  jmlarsen
00250  * Work on conversion to CPL
00251  *
00252  * Revision 1.2  2007/01/15 14:00:23  jmlarsen
00253  * Imported FLAMES sources from MIDAS pipeline
00254  *
00255  * Revision 1.1  2007/01/10 08:06:10  jmlarsen
00256  * Added source files
00257  *
00258  * Revision 1.2  2006/12/01 12:52:31  jmlarsen
00259  * Added flames_pfits module
00260  *
00261  * Revision 1.1  2006/10/20 06:42:09  jmlarsen
00262  * Moved FLAMES source to flames directory
00263  *
00264  * Revision 1.114  2006/10/09 13:03:09  jmlarsen
00265  * Removed explicit uves_msg_softer/louder calls
00266  *
00267  */
00268 
00269 #ifdef HAVE_CONFIG_H
00270 #  include <config.h>
00271 #endif
00272 
00273 /*----------------------------------------------------------------------------*/
00293 /*----------------------------------------------------------------------------*/
00294 
00295 /*-----------------------------------------------------------------------------
00296                             Includes
00297  -----------------------------------------------------------------------------*/
00298 #include <flames_midas_def.h>
00299 
00300 #include <uves_utils_cpl.h>
00301 #include <uves_dfs.h>
00302 #include <uves_dump.h>
00303 #include <uves_utils_wrappers.h>
00304 #include <uves_error.h>
00305 
00306 #include <uves_msg.h>
00307 #include <uves_pfits.h>
00308 
00309 #include <fitsio.h>
00310 #include <string.h>
00311 #include <errno.h>
00312 /*-----------------------------------------------------------------------------
00313                             Defines
00314  -----------------------------------------------------------------------------*/
00315 
00316 #define MAX_OPEN 1024 /* Maximum number of open images/tables files */
00317 
00319 /*-----------------------------------------------------------------------------
00320                             Functions prototypes
00321  -----------------------------------------------------------------------------*/
00322 /*-----------------------------------------------------------------------------
00323                             Variables
00324  -----------------------------------------------------------------------------*/
00325 
00326 struct frame
00327 {
00328     const char *filename;      /* NULL: slot not used */
00329 
00330     bool is_image;             /* Image or table? */
00331     union {
00332         struct {
00333             cpl_image *image;  
00334             cpl_type type;   /* CPL type of image (cannot store this in
00335                                 the CPL image structure, because the image may
00336                                 be logically open before it is actually loaded
00337                                 into memory) */
00338             int dtype;       /* MIDAS image type */
00339         } image;
00340         struct {
00341             cpl_table *table;  /* The actual table columns *and* an
00342                                   'internal' column "Select" to record
00343                                   selections */
00344             cpl_table *colnames;
00345             int maxrow;        /* Number of rows actually used
00346                                   (maybe be less than rows allocated) */
00347         } table;
00348     } data;
00349 
00350     uves_propertylist *header;  /* Primary header, also for tables.
00351                                   NULL: not loaded (yet) */
00352     bool need_to_save;         /* Need to save to disk when closing? */
00353 
00354     /* Invariants:
00355        if need_to_save, then image/table is != NULL
00356        For images:
00357           if image != NULL, then cpl_image_get_type(image) = type 
00358        For tables:
00359           (table == NULL) == (colnames == NULL)
00360           if table != NULL, then table.ncol-1 == colnames.nrow
00361           if table != NULL, table has column "Select"
00362     */
00363 
00364 };
00365 
00366 #define COLNAME "ColName"
00367 
00368 /* There are 3(!) different representations of FITS headers
00369 
00370    1. As seen by the FLAMES code, e.g.
00371 
00372    LHCUTS[3]...
00373    LHCUTS[4]...
00374    ORDERLIM[1]...
00375    ORDERLIM[2]...
00376    ESO OBS ID...
00377 
00378    2. CPL propertylist
00379    
00380    DATAMIN...
00381    DATAMAX...
00382    ORDERLIM = x
00383    ORDERLIM = y
00384    ESO OBS ID...
00385 
00386    3. The actual FITS file
00387    
00388    DATAMIN...
00389    DATAMAX...
00390    HISTORY ORDERLIM 
00391    HISTORY x y
00392    HISTORY
00393    HIERARCH ESO OBS ID...
00394 
00395 */
00396 
00397 struct frame frames[MAX_OPEN];
00398 const char *current_caller = NULL;
00399 
00400 /*-----------------------------------------------------------------------------
00401                             Implementation
00402  -----------------------------------------------------------------------------*/
00403 /*----------------------------------------------------------------------------*/
00416 /*----------------------------------------------------------------------------*/
00417 
00418 static bool invariant(int id)
00419 {
00420     struct frame *frm = &frames[id];
00421 
00422     if (frm->is_image)
00423         {
00424             return
00425                 (!frm->need_to_save || frm->data.image.image != NULL) &&
00426                 (frm->data.image.image == NULL
00427                  || cpl_image_get_type(frm->data.image.image) == frm->data.image.type);
00428         }
00429     else
00430         {
00431             return (!frm->need_to_save || frm->data.table.table != NULL)
00432                 &&
00433                 ((frm->data.table.table == NULL) == (frm->data.table.colnames == NULL))
00434                 &&
00435                 (frm->data.table.table == NULL || 
00436                  cpl_table_get_ncol(frm->data.table.table) - 1 ==
00437                  cpl_table_get_nrow(frm->data.table.colnames)) 
00438                 &&
00439                 (frm->data.table.table == NULL || 
00440                  cpl_table_has_column(frm->data.table.table, "Select"));
00441 
00442         }
00443 }
00444 /*----------------------------------------------------------------------------*/
00449 /*----------------------------------------------------------------------------*/
00450 static bool
00451 frame_is_open(int id)
00452 {
00453     return frames[id].filename != NULL;
00454 }
00455 
00456 /*----------------------------------------------------------------------------*/
00462 /*----------------------------------------------------------------------------*/
00463 static void 
00464 frame_new_image(int id, const char *filename, 
00465                 uves_propertylist *header,
00466                 bool need_to_save,
00467                 cpl_image *image,
00468                 cpl_type type,
00469                 int dtype)
00470 {
00471     if (strstr(filename, ".fits") == filename + strlen(filename) - 5) {
00472         frames[id].filename = uves_sprintf("%s", filename);
00473     } 
00474     else if (strstr(filename, ".bdf") == filename + strlen(filename) - 4) {
00475         /* Replace .bdf -> .fits */
00476         frames[id].filename = uves_sprintf("%sX", filename);
00477         ((char *)frames[id].filename)[strlen(filename) - 3] = 'f';
00478         ((char *)frames[id].filename)[strlen(filename) - 2] = 'i';
00479         ((char *)frames[id].filename)[strlen(filename) - 1] = 't';
00480         ((char *)frames[id].filename)[strlen(filename) - 0] = 's';
00481     }
00482     else {
00483         frames[id].filename = uves_sprintf("%s.fits", filename);
00484     }
00485     frames[id].is_image = true;
00486     frames[id].data.image.image = image;
00487     frames[id].data.image.type  = type;
00488     frames[id].data.image.dtype = dtype;
00489     frames[id].header = header;
00490     frames[id].need_to_save = need_to_save;
00491 
00492     return;
00493 }
00494 /*----------------------------------------------------------------------------*/
00500 /*----------------------------------------------------------------------------*/
00501 static void 
00502 frame_new_table(int id, const char *filename, 
00503                 uves_propertylist *header,
00504                 bool need_to_save,
00505                 cpl_table *table,
00506                 int maxrow,
00507                 cpl_table *colnames)
00508 {
00509     if (strstr(filename, ".fits") == filename + strlen(filename) - 5) {
00510         frames[id].filename = uves_sprintf("%s", filename);
00511     } 
00512     else if (strstr(filename, ".tfits") == filename + strlen(filename) - 6) {
00513         frames[id].filename = uves_sprintf("%s", filename);
00514     } 
00515     else if (strstr(filename, ".tbl") == filename + strlen(filename) - 4) {
00516         /* Replace .tbl -> .fits */
00517         frames[id].filename = uves_sprintf("%sX", filename);
00518         ((char *)frames[id].filename)[strlen(filename) - 3] = 'f';
00519         ((char *)frames[id].filename)[strlen(filename) - 2] = 'i';
00520         ((char *)frames[id].filename)[strlen(filename) - 1] = 't';
00521         ((char *)frames[id].filename)[strlen(filename) - 0] = 's';
00522     } else {
00523         frames[id].filename = uves_sprintf("%s.fits", filename);
00524     }
00525     frames[id].is_image = false;
00526     frames[id].data.table.table = table;
00527     if (table != NULL) {
00528         cpl_table_new_column(table, "Select", CPL_TYPE_INT);
00529         cpl_table_fill_column_window_int(table, "Select",
00530                                          0, cpl_table_get_nrow(table),
00531                                          1); /* initialize to all selected */
00532     }
00533     else {
00534         /* Select column will be created when table is loaded from disk */
00535     }
00536     frames[id].data.table.maxrow = maxrow;
00537     frames[id].data.table.colnames = colnames;
00538     frames[id].header = header;
00539     frames[id].need_to_save = need_to_save;
00540     return;
00541 }
00542 
00543 /*----------------------------------------------------------------------------*/
00549 /*----------------------------------------------------------------------------*/
00550 static void 
00551 frame_free(int id)
00552 {
00553     if (frame_is_open(id))
00554         {
00555             uves_free_string_const(&frames[id].filename);
00556             if (frames[id].is_image)
00557                 {
00558                     uves_free_image(&frames[id].data.image.image);
00559                 }
00560             else
00561                 {
00562                     uves_free_table(&frames[id].data.table.table);
00563                     uves_free_table(&frames[id].data.table.colnames);
00564                 }
00565             uves_free_propertylist(&frames[id].header);
00566         }
00567 }
00568 
00569 /*----------------------------------------------------------------------------*/
00575 /*----------------------------------------------------------------------------*/
00576 static bool
00577 is_special_midas_descr(const char *descr)
00578 {
00579     return 
00580         strcmp(descr, "NPIX") == 0 ||
00581         strcmp(descr, "REFPIX") == 0 ||
00582         strcmp(descr, "START") == 0 ||
00583         strcmp(descr, "STEP") == 0 ||
00584         strcmp(descr, "ROTA") == 0 ||
00585         strcmp(descr, "CUNIT") == 0 ||
00586         strcmp(descr, "IDENT") == 0 ||
00587         strcmp(descr, "O_TIME") == 0 ||
00588         strcmp(descr, "LHCUTS") == 0 ||
00589         strcmp(descr, "O_POS") == 0;
00590 }
00591 
00592 /*----------------------------------------------------------------------------*/
00600 /*----------------------------------------------------------------------------*/
00601 static const char *
00602 convert_to_fits(const char *descr, int indx)
00603 {
00604     /* Special MIDAS keywords are:
00605        (MIDAS manual volume A p. 7-5)    
00606        NAXISn -> NPIXn
00607        CRPIXn -> REFPIXn
00608        CRVALn -> STARTn
00609        CDELTn -> STEPn
00610        CROTAn -> ROTAn
00611        BUNIT  -> CUNIT(1)
00612        CTYPEn -> CUNIT(n+1)
00613        OBJECT -> IDENT
00614        DATE_OBS -> O_TIME(1)
00615 
00616                   LHCUTS(1), LHCUTS(2)
00617           internal in MIDAS,
00618           not converted
00619        DATAMIN -> LHCUTS(3)       (and convert double -> float)
00620        DATAMAX -> LHCUTS(4)
00621        EPOCH   -> O_POS(3)
00622        EQUINOX -> O_POS(3)
00623     */
00624 
00625     const char *fits_descr = NULL;
00626     if      (strcmp(descr, "NPIX"  ) == 0) fits_descr = uves_sprintf("NAXIS%d", indx);
00627     else if (strcmp(descr, "REFPIX") == 0) assure( false, CPL_ERROR_UNSUPPORTED_MODE, "%s", descr);
00628     else if (strcmp(descr, "START" ) == 0) fits_descr = uves_sprintf("CRVAL%d", indx);
00629     else if (strcmp(descr, "STEP"  ) == 0) fits_descr = uves_sprintf("CDELT%d", indx);
00630     else if (strcmp(descr, "ROTA"  ) == 0) assure( false, CPL_ERROR_UNSUPPORTED_MODE, "%s", descr);
00631     else if (strcmp(descr, "CUNIT" ) == 0) 
00632         fits_descr = (indx == 1) ? uves_sprintf("BUNIT") : uves_sprintf("CTYPE%d", indx);
00633     else if (strcmp(descr, "IDENT" ) == 0) fits_descr = uves_sprintf("OBJECT");
00634     else if (strcmp(descr, "O_TIME") == 0) assure( false, CPL_ERROR_UNSUPPORTED_MODE, "%s", descr);
00635     else if (strcmp(descr, "LHCUTS") == 0) 
00636     {
00637         fits_descr = 
00638         (indx == 1) ? uves_sprintf("LHCUTS1") :    /* For now, write these keywords for indx 1,2 */
00639         (indx == 2) ? uves_sprintf("LHCUTS2") :
00640         (indx == 3) ? uves_sprintf("DATAMIN") : uves_sprintf("DATAMAX");
00641     }
00642     else if (strcmp(descr, "O_POS" ) == 0) assure( false, CPL_ERROR_UNSUPPORTED_MODE, "%s", descr);
00643         
00644     if (fits_descr == NULL)
00645     {
00646         fits_descr = uves_sprintf("%s", descr);
00647     }
00648 
00649   cleanup:
00650     return fits_descr;
00651 }
00652 
00653 /*----------------------------------------------------------------------------*/
00678 /*----------------------------------------------------------------------------*/
00679 static void
00680 convert_to_history(uves_propertylist **header)
00681 {
00682     int plist_size, i;
00683     const char *new_name  = NULL;
00684     char *v = NULL;
00685     cpl_table *new_values = NULL;
00686     cpl_property *new_prop = NULL;
00687     uves_propertylist *result = NULL;  /* Cannot change type of one property,
00688                                          need to copy to new list */
00689     result = uves_propertylist_new();
00690 
00691     plist_size = uves_propertylist_get_size(*header);
00692     for (i = 0; i < plist_size; i++) {
00693         cpl_property *p = uves_propertylist_get(*header, i);
00694         const char *name = cpl_property_get_name(p);
00695         int j;
00696 
00697         if (cpl_property_get_comment(p) != NULL &&
00698             strcmp(cpl_property_get_comment(p), "PROCESSED") == 0) {
00699             /* already processed, ignore */
00700         }
00701         else if ((strlen(name) > 8 && strncmp(name, "ESO ", 4) != 0) 
00702                  ||
00703                  (cpl_property_get_comment(p) != NULL &&
00704                   strcmp(cpl_property_get_comment(p), "MIDAS_DESC") == 0)) {
00705 
00706             int n_prop;
00707             
00708             uves_free_string_const(&new_name);
00709             switch (cpl_property_get_type(p)) {
00710             case CPL_TYPE_STRING:
00711                 new_name = uves_sprintf("'%s','C'", name);
00712                 break;
00713             case CPL_TYPE_INT:
00714                 new_name = uves_sprintf("'%s','I'", name);
00715                 break;
00716             case CPL_TYPE_FLOAT:
00717                 new_name = uves_sprintf("'%s','R*4'", name);
00718                 break;
00719             case CPL_TYPE_DOUBLE:
00720                 new_name = uves_sprintf("'%s','R*8'", name);
00721                 break;
00722             default:
00723                 assure(false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me %s %s", name,
00724                        uves_tostring_cpl_type(cpl_property_get_type(p)));
00725                 break;
00726             }
00727 
00728             uves_free_table(&new_values);
00729             new_values = cpl_table_new(2);
00730             cpl_table_new_column(new_values, "Val", CPL_TYPE_STRING);
00731             n_prop = 0;
00732             
00733             /* And collect this and any subsequent properties with same name */
00734             for (j = i; j < plist_size; j++) {
00735           cpl_property *p2;
00736 
00737           check_nomsg( p2 = uves_propertylist_get(*header, j) );
00738                 if (strcmp(cpl_property_get_name(p2), name) == 0) {
00739                     uves_msg_debug("Found %s", name);
00740 
00741                     /* Here, we would like to remove p2 from the list
00742                        in order not to process it again, but uves_propertylists
00743                        don't support that */
00744                     cpl_property_set_comment(p2, "PROCESSED");
00745             
00746                     assure( cpl_property_get_type(p2) == cpl_property_get_type(p),
00747                             CPL_ERROR_TYPE_MISMATCH,
00748                             "Found property %s with type %s and with type %s",
00749                             name, 
00750                             uves_tostring_cpl_type(cpl_property_get_type(p)),
00751                             uves_tostring_cpl_type(cpl_property_get_type(p2)));
00752             
00753                     uves_free_string(&v);
00754                     switch (cpl_property_get_type(p2)) {
00755                     case CPL_TYPE_STRING:
00756                       if(strlen(cpl_property_get_string(p2)) > 0) {
00757                         v = uves_sprintf("%s", cpl_property_get_string(p2));
00758               } else {
00759             uves_msg_debug("Empty string descriptor");
00760             v=cpl_malloc(1);
00761                         *v='\0';
00762               }
00763               break;
00764                     case CPL_TYPE_INT:
00765               v = uves_sprintf("%d", cpl_property_get_int(p2));
00766               break;
00767                     case CPL_TYPE_FLOAT:
00768                       v = uves_sprintf("%g", cpl_property_get_float(p2));
00769                       break;
00770                     case CPL_TYPE_DOUBLE:
00771                       v = uves_sprintf("%g", cpl_property_get_double(p2));
00772                       break;
00773                     default:
00774                       assure(false, CPL_ERROR_UNSUPPORTED_MODE, 
00775                              "Implement me %s %s", name,
00776                              uves_tostring_cpl_type(cpl_property_get_type(p2)));
00777                       break;
00778                     }
00779 
00780 
00781             assure(v != NULL, CPL_ERROR_UNSPECIFIED,"Allocation failure");
00782                     assure( strlen(v) <= 80 - strlen("HISTORY "),
00783                             CPL_ERROR_UNSUPPORTED_MODE,
00784                             "Value (%s) too long string",
00785                             v);
00786           
00787                  
00788 
00789                     /* Increase table size as necessary */
00790                     if (n_prop >= cpl_table_get_nrow(new_values))
00791                         {
00792                             cpl_table_set_size(new_values, 
00793                                                2*cpl_table_get_nrow(new_values));
00794                         }
00795                         
00796                     check_nomsg( cpl_table_set_string(new_values, "Val", n_prop, v) );
00797                     n_prop += 1;
00798                 }
00799             }
00800             cpl_table_set_size(new_values, n_prop);
00801 
00802             /* if (strcmp(name, "SIGMAFRAME") == 0) {
00803                cpl_table_dump(new_values, 0, cpl_table_get_nrow(new_values), stderr);
00804                uves_print_uves_propertylist(*header, 0, uves_propertylist_get_size(*header));
00805                } */
00806                         
00807             /* Convert to 1+n+1 HISTORY entries */
00808             uves_propertylist_append_string(result, "HISTORY", new_name);
00809             for (j = 0; j < cpl_table_get_nrow(new_values); j++)
00810                 {
00811                     uves_propertylist_append_string(result, "HISTORY",
00812                                                     cpl_table_get_string(new_values, "Val", j));
00813                 }
00814             uves_propertylist_append_string(result, "HISTORY", "");
00815 
00816 
00817         }
00818         else {
00819             uves_free_property(&new_prop);
00820             new_prop = cpl_property_duplicate(p);
00821             uves_propertylist_append_property(result, new_prop);
00822         }
00823 
00824     }
00825 
00826     uves_free_propertylist(header);
00827     *header = uves_propertylist_duplicate(result);
00828     
00829   cleanup:
00830     uves_free_string_const(&new_name);
00831     uves_free_string(&v);
00832     uves_free_table(&new_values);
00833     uves_free_property(&new_prop);
00834     uves_free_propertylist(&result);
00835     return;    
00836 }
00837 
00838 /*----------------------------------------------------------------------------*/
00858 /*----------------------------------------------------------------------------*/
00859 static uves_propertylist *
00860 load_header(const char *filename,
00861         int extension)
00862 {
00863     uves_propertylist *fitsheader = NULL;
00864     uves_propertylist *result = NULL;
00865     int plist_size, i;
00866     const char *new_name = NULL;
00867     const char *new_value = NULL;
00868 
00869     const char *desc_name = NULL;
00870     const void *values = NULL;
00871     
00872     check( fitsheader = uves_propertylist_load(filename, extension),
00873        "Could not load extension %d header from file %s", extension, filename);
00874 
00875     result = uves_propertylist_new();
00876     plist_size = uves_propertylist_get_size(fitsheader);
00877     for (i = 0; i < plist_size; i++) {
00878         cpl_property *p = uves_propertylist_get(fitsheader, i);
00879         const char *name = cpl_property_get_name(p);
00880         bool convert_from_midas = false;
00881         
00882         if (strcmp(name, "HISTORY") == 0)
00883             {
00884                 const char *value;
00885                 
00886                 if (cpl_property_get_type(p) == CPL_TYPE_STRING)
00887                     {
00888                         value = cpl_property_get_string(p);
00889                         
00890                         /* If a MIDAS descriptor is encoded here.
00891                            Must match "'.+'"
00892                         */
00893                         if ((int)strlen(value) >= 3 && 
00894                             value[0] == '\'' &&
00895                             strstr(value+2, "'") != NULL)
00896                             {
00897                                 /* Get descriptor name. */
00898                                 uves_free_string_const(&desc_name);
00899                                 desc_name = cpl_strdup(value+1);
00900                                 *(strstr(desc_name, "'")) = '\0';
00901                                 
00902                                 convert_from_midas = !is_special_midas_descr(desc_name);
00903                                 
00904                                 /* i.e. don't convert e.g
00905                                    HISTORY 'LHCUTS'
00906                                 */
00907                             }
00908                     }
00909                 else
00910                     {
00911                         uves_msg_warning("%s has HISTORY property of non-string type (%s)",
00912                                          filename, 
00913                                          uves_tostring_cpl_type(cpl_property_get_type(p)));
00914                     }
00915             }
00916         
00917         if (convert_from_midas) {
00918             int length, j;
00919             int ncards;
00920             cpl_type type;
00921             
00922             uves_free(values); values = NULL;
00923             check( values = 
00924                    uves_read_midas_array(fitsheader, desc_name, &length, &type,
00925                                          &ncards),
00926                    "Could not get values of HISTORY descriptor '%s'", desc_name);
00927             
00928             i += ncards-1;
00929             
00930             /* Create new properties */
00931             for (j = 0; j < ((type == CPL_TYPE_STRING) ? 1 : length); j++) {
00932 
00933                 uves_free_string_const(&new_name);
00934                 new_name = uves_sprintf("%s", desc_name);
00935                 
00936                 switch(type) {
00937                 case CPL_TYPE_INT:
00938                     uves_propertylist_append_c_int(result, new_name, ((int*)values)[j], "MIDAS_DESC");
00939                     break;
00940                 case CPL_TYPE_FLOAT:
00941                     uves_propertylist_append_c_float(result, new_name, ((float*)values)[j], "MIDAS_DESC");
00942                     break;
00943                 case CPL_TYPE_DOUBLE:
00944                     uves_propertylist_append_c_double(result, new_name, ((double*)values)[j], "MIDAS_DESC");
00945                     break;
00946                 case CPL_TYPE_STRING:
00947                     uves_propertylist_append_c_string(result, new_name, (char *)values, "MIDAS_DESC");
00948                     break;
00949                 default:
00950                     assure( false, CPL_ERROR_UNSUPPORTED_MODE,
00951                             "Type is %s", uves_tostring_cpl_type(type));
00952                 }
00953             }
00954         }
00955         else {
00956             uves_propertylist_append_property(result, p);
00957         }
00958     }
00959     
00960   cleanup:
00961     uves_free_string_const(&new_name);
00962     uves_free_string_const(&new_value);
00963     uves_free_string_const(&desc_name);
00964     uves_free_propertylist(&fitsheader);
00965     uves_free(values); values = NULL;
00966     if (cpl_error_get_code() != CPL_ERROR_NONE)
00967     {
00968         uves_free_propertylist(&result);
00969     }
00970     return result;
00971 
00972 }
00973 /*----------------------------------------------------------------------------*/
00978 /*----------------------------------------------------------------------------*/
00979 cpl_type
00980 flames_midas_image_dtype_to_cpltype(int dtype)
00981 {
00982     cpl_type type = CPL_TYPE_INVALID;
00983 
00984     switch(dtype) {
00985     case D_OLD_FORMAT: type = CPL_TYPE_FLOAT; break;
00986     case D_R4_FORMAT: type = CPL_TYPE_FLOAT; break;
00987     case D_R8_FORMAT: type = CPL_TYPE_DOUBLE; break;
00988     case D_I1_FORMAT: type = CPL_TYPE_INT; break;
00989     case D_I2_FORMAT: type = CPL_TYPE_INT; break;
00990     case D_I4_FORMAT: type = CPL_TYPE_INT; break;
00991     default:
00992         assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me %d",
00993                 dtype);
00994         break;
00995     }
00996 
00997   cleanup:
00998     return type;
00999 }
01000 /*----------------------------------------------------------------------------*/
01008 /*----------------------------------------------------------------------------*/
01009 
01010 static void
01011 load_frame_header(int id)
01012 {
01013     int extension = 0; /* For tables and images */
01014 
01015     passure( invariant(id), " ");
01016 
01017     passure( frame_is_open(id), " ");
01018 
01019     if (frames[id].header == NULL)
01020     {
01021             /* Convert MIDAS HISTORY descriptors to internal format */
01022             check( frames[id].header = load_header(frames[id].filename,
01023                                              extension),
01024                    "Error loading header from %s", frames[id].filename);
01025 
01026             uves_msg_debug("Loaded %s header (%ld FITS cards)",
01027                            frames[id].filename,
01028                            uves_propertylist_get_size(frames[id].header));
01029     }
01030     
01031     passure( invariant(id), " ");
01032 
01033   cleanup:
01034     return;
01035 }
01036 
01037 /*----------------------------------------------------------------------------*/
01045 /*----------------------------------------------------------------------------*/
01046 static void
01047 set_column_format_unit_tnull(cpl_table *t, const uves_propertylist *theader)
01048 {
01049     const char *colname;
01050 
01051     int tfield; /* number of columns */
01052     char *key_type = NULL;
01053     char *key_form = NULL;
01054     char *key_unit = NULL;
01055     char *key_null = NULL;
01056     char *val_type = NULL;
01057     char *val_form = NULL;
01058     char *val_unit = NULL;
01059     int val_null;
01060 
01061     check_nomsg( tfield = uves_propertylist_get_int(theader, "TFIELDS"));
01062 
01063     for(colname = cpl_table_get_column_name(t);
01064         colname != NULL;
01065         colname = cpl_table_get_column_name(NULL)) {
01066         bool found = false;
01067         int i;
01068         for (i = 1; i <= tfield && !found; i++) {
01069             uves_free_string(&key_type);
01070             uves_free_string(&key_form);
01071             uves_free_string(&key_unit);
01072             uves_free_string(&key_null);
01073             uves_free_string(&val_type);
01074             uves_free_string(&val_form);
01075             uves_free_string(&val_unit);
01076             key_type = uves_sprintf("TTYPE%d", i); /* column name */
01077             key_form = uves_sprintf("TFORM%d", i);
01078             key_unit = uves_sprintf("TUNIT%d", i);
01079             key_null = uves_sprintf("TNULL%d", i);
01080             
01081             /* remove trailing blanks */
01082             val_type = cpl_strdup(uves_propertylist_get_string(theader, key_type));
01083             if (strlen(val_type) > 0) {
01084                 while (val_type[strlen(val_type)-1] == ' ') {
01085                     val_type[strlen(val_type)-1] = '\0';
01086                 }
01087             }
01088             
01089             if (strcmp(val_type, colname) == 0)  {
01090                 found = true;
01091                 if (uves_propertylist_contains(theader, key_form))  {
01092                     val_form = cpl_strdup(uves_propertylist_get_string(theader, key_form));
01093                     if (strlen(val_form) > 0) {
01094                         while (val_form[strlen(val_form)-1] == ' ') {
01095                             val_form[strlen(val_form)-1] = '\0';
01096                         }
01097                     }
01098                     
01099                     cpl_table_set_column_format(t, colname, val_form);
01100                 }
01101                 if (uves_propertylist_contains(theader, key_unit))  {
01102                     val_unit = cpl_strdup(uves_propertylist_get_string(theader, key_unit));
01103                     if (strlen(val_unit) > 0) {
01104                         while (val_unit[strlen(val_unit)-1] == ' ') {
01105                             val_unit[strlen(val_unit)-1] = '\0';
01106                         }
01107                     }
01108                     
01109                     cpl_table_set_column_unit(t, colname, val_unit);
01110                 }
01111                 else {
01112                     /* FLAMES C code expects the unit to be always non-NULL,
01113                        therefore set it to an empty string. 
01114 
01115                        This was guaranteed by CPL-3.x which always wrote 
01116                        the TUNIT keyword when saving.
01117 
01118                        But with CPL-4, the TUNIT keyword is not always present.
01119                     */
01120                     cpl_table_set_column_unit(t, colname, "        ");
01121                 }
01122 
01123                 if (cpl_table_get_column_type(t, colname) == CPL_TYPE_INT &&
01124                     uves_propertylist_contains(theader, key_null))  {
01125                     val_null = uves_propertylist_get_int(theader, key_null);
01126 
01127                     cpl_table_fill_invalid_int(t, colname, val_null);
01128                 }
01129             }
01130         }
01131     }
01132     
01133   cleanup:
01134     uves_free_string(&key_type);
01135     uves_free_string(&key_form);
01136     uves_free_string(&key_unit);
01137     uves_free_string(&key_null);
01138     uves_free_string(&val_type);
01139     uves_free_string(&val_form);
01140     uves_free_string(&val_unit);
01141     return;
01142 }
01143 
01144 /*----------------------------------------------------------------------------*/
01150 /*----------------------------------------------------------------------------*/
01151 static void
01152 load_frame(int id)
01153 {
01154     uves_propertylist *theader = NULL;
01155     cpl_imagelist *ilist = NULL;
01156     fitsfile *fptr = NULL;
01157 
01158     /* doesn't have to hold here: passure( invariant(id), " "); */
01159     passure( frame_is_open(id), " ");
01160 
01161     if (frames[id].is_image) {
01162         if (frames[id].data.image.image == NULL) {
01163             long naxes[4];
01164             long firstpixel[4] = {1, 1, 1, 1};
01165             int naxis;
01166             int fio_status = 0;            
01167             
01168             uves_msg_debug("Loading image %s (type %s) to memory", 
01169                            frames[id].filename, 
01170                            uves_tostring_cpl_type(frames[id].data.image.type));
01171             
01172             /* Use CFITSIO. CPL doesn't handle 4d images */
01173 
01174             fits_open_file(&fptr, frames[id].filename, READONLY, &fio_status);
01175             
01176             assure( fio_status == 0, CPL_ERROR_FILE_IO,
01177                     "Failed to open %s for reading", frames[id].filename );
01178     
01179             /* Get the image dimension */
01180             fits_get_img_dim(fptr, &naxis, &fio_status);
01181             assure( naxis == 1 || naxis == 2 || naxis == 3 || naxis == 4,
01182                     CPL_ERROR_ILLEGAL_INPUT, "Illegal dimension: %d", naxis);
01183             
01184             /* Get the file size */
01185             naxes[0] = 1;
01186             naxes[1] = 1;
01187             naxes[2] = 1;
01188             naxes[3] = 1;
01189             fits_get_img_size(fptr, naxis, naxes, &fio_status);
01190             assure( fio_status == 0, CPL_ERROR_FILE_IO,
01191                     "Failed to get %s image size", frames[id].filename);
01192 
01193 
01194             frames[id].data.image.image = cpl_image_new(naxes[0] * naxes[1] * naxes[2] * naxes[3], 1,
01195                                                         frames[id].data.image.type);
01196 
01197             switch(frames[id].data.image.type) {
01198             case CPL_TYPE_DOUBLE:
01199                 fits_read_pix(fptr, TDOUBLE, firstpixel, naxes[0] * naxes[1] * naxes[2] * naxes[3],
01200                               NULL, cpl_image_get_data_double(frames[id].data.image.image),
01201                               NULL, &fio_status);
01202                 break;
01203             case CPL_TYPE_FLOAT:
01204                 fits_read_pix(fptr, TFLOAT, firstpixel, naxes[0] * naxes[1] * naxes[2] * naxes[3],
01205                               NULL, cpl_image_get_data_float(frames[id].data.image.image),
01206                               NULL, &fio_status);
01207                 break;
01208             case CPL_TYPE_INT:
01209                 fits_read_pix(fptr, TINT, firstpixel, naxes[0] * naxes[1] * naxes[2] * naxes[3],
01210                               NULL, cpl_image_get_data_int(frames[id].data.image.image),
01211                               NULL, &fio_status);
01212                 break;
01213             default:
01214                 assure( false, CPL_ERROR_INVALID_TYPE,
01215                         "Illegal type %s", uves_tostring_cpl_type(frames[id].data.image.type));
01216 
01217             }
01218             
01219             fits_close_file(fptr, &fio_status) ;
01220             assure( fio_status == 0, CPL_ERROR_FILE_IO,
01221                     "Failed to load image %s", frames[id].filename);
01222  
01223         }
01224     }
01225     else
01226         {
01227             if (frames[id].data.table.table == NULL)
01228                 {
01229                     int extension = 1;
01230                     int mark_invalid_values = 1; /* 1=yes */
01231                     const char *name;
01232                     int row;
01233 
01234                     uves_msg_debug("Loading table %s to memory", frames[id].filename);
01235 
01236                     check( frames[id].data.table.table = 
01237                            cpl_table_load(frames[id].filename,
01238                                           extension,
01239                                           mark_invalid_values),
01240                            "Error loading table from %s", frames[id].filename);
01241                     
01242                     if (!cpl_table_has_column(frames[id].data.table.table, "Select")) {
01243                         cpl_table_new_column(frames[id].data.table.table, "Select", 
01244                                              CPL_TYPE_INT);
01245                         cpl_table_fill_column_window_int(
01246                             frames[id].data.table.table, "Select",
01247                             0, cpl_table_get_nrow(frames[id].data.table.table),
01248                             1);
01249                     }
01250                     
01251                     frames[id].data.table.maxrow = cpl_table_get_nrow(frames[id].data.table.table);
01252 
01253                     check( theader = uves_propertylist_load(frames[id].filename, extension),
01254                            "Error loading table header from %s", frames[id].filename);
01255                     
01256                     /* Assign numbers to columns */
01257                     frames[id].data.table.colnames = 
01258                         cpl_table_new(cpl_table_get_ncol(frames[id].data.table.table) - 1);
01259                     cpl_table_new_column(frames[id].data.table.colnames, COLNAME, CPL_TYPE_STRING);
01260                     
01261                     for(name = cpl_table_get_column_name(frames[id].data.table.table), row = 0;
01262                         name != NULL;
01263                         name = cpl_table_get_column_name(NULL)) {
01264                         if (strcmp(name, "Select") != 0) {
01265                             cpl_table_set_string(frames[id].data.table.colnames, COLNAME, row, name);
01266                             row++;
01267                         }
01268                     }
01269                     
01270                     /* Workaround here: cpl_table_load ignores the table column
01271                        units/formats and TNULL, so read + set those manually */
01272                     check( set_column_format_unit_tnull(frames[id].data.table.table, theader),
01273                            "Error loading table %s format/units", frames[id].filename);
01274                 }
01275         }
01276     
01277     passure( invariant(id), " ");
01278            
01279   cleanup:
01280     uves_free_imagelist(&ilist);
01281     uves_free_propertylist(&theader);
01282     return;
01283 }
01284 
01285 /*----------------------------------------------------------------------------*/
01296 /*----------------------------------------------------------------------------*/
01297 static cpl_property **
01298 create_descr(uves_propertylist *header,
01299          const char *descr,
01300          char type, int length,
01301          int nexist)
01302 {
01303     const char *fits_descr = NULL;
01304     const char *previous_descr = NULL;
01305     cpl_property **cards = NULL;
01306     int i;
01307     cpl_property *new_prop = NULL;
01308 
01309     passure( header != NULL, " ");
01310     assure( length >= 1, CPL_ERROR_ILLEGAL_INPUT, "Length = %d", length);
01311 
01312     cards = cpl_malloc((length+1) * sizeof(cpl_property *));
01313 
01314     if (nexist > 0)
01315     {
01316         i = 0;
01317         check( previous_descr = convert_to_fits(descr, i + nexist),
01318            "Could not convert %s to FITS", descr);
01319     }
01320     else
01321     {
01322         previous_descr = uves_sprintf("----");
01323     }
01324 
01325     for (i = 1; i <= length; i++)
01326     {
01327             const char *comment;
01328 
01329             uves_free_string_const(&fits_descr);
01330             check( fits_descr = convert_to_fits(descr, i + nexist),
01331                    "Could not convert %s to FITS", descr);
01332 
01333             uves_msg_debug("Creating property %s (%d of %d, type = '%c')", fits_descr,
01334                            nexist + i, nexist + length, type);
01335 
01336             if (strcmp(descr, fits_descr) == 0 &&
01337                 strncmp(descr, "CTYPE", 5) != 0 &&
01338                 strncmp(descr, "CDELT", 5) != 0 &&
01339                 strncmp(descr, "CRVAL", 5) != 0 &&
01340                 strncmp(descr, "CRPIX", 5) != 0 &&
01341                 strncmp(descr, "ESO QC", 6) != 0 &&
01342                 strcmp(descr, "BUNIT") != 0 &&
01343                 strcmp(descr, "COLS") != 0 &&
01344                 strcmp(descr, "ROWS") != 0 &&
01345                 strcmp(descr, "PIXMAX") != 0 &&
01346                 strcmp(descr, "STARTX") != 0 &&
01347                 strcmp(descr, "STARTY") != 0 &&
01348                 strcmp(descr, "STEPX") != 0 &&
01349                 strcmp(descr, "STEPY") != 0 &&
01350                 strcmp(descr, "YSHIFT") != 0 &&
01351                 strcmp(descr, "DATAMIN") != 0 &&
01352                 strcmp(descr, "DATAMAX") != 0 &&
01353                 strcmp(descr, "NFLATS") != 0 &&
01354                 strcmp(descr, "RON") != 0 &&
01355                 strcmp(descr, "GAIN") != 0 &&
01356                 strcmp(descr, "FIBRESON") != 0)
01357                 {
01358                 /* Then it is a MIDAS descriptor which must be
01359                    stored in HISTORY keywords */
01360                 comment = "MIDAS_DESC";
01361             }
01362             else {
01363                 /* It is a descriptor recognized by the FITS format
01364                    (such as NAXIS1), which should not be converted
01365                    into HISTORY format */
01366                 comment = NULL;
01367             }
01368                 
01369 
01370             switch(type)
01371                 {
01372                 case 'I': uves_propertylist_append_c_int   (header, fits_descr, 0, comment)  ; break;
01373                 case 'R': uves_propertylist_append_c_float (header, fits_descr, 0.0, comment); break;
01374                 case 'C': uves_propertylist_append_c_string(header, fits_descr, "0", comment); break;
01375                 case 'D': uves_propertylist_append_c_double(header, fits_descr, 0.0, comment); break;
01376                 default: assure( false, CPL_ERROR_UNSUPPORTED_MODE, "%c", type); break;
01377                 }
01378 
01379             /* If name changes with index, get the first occurence */
01380 
01381         cards[i-1] = uves_find_property(header,
01382                         fits_descr, 
01383                         strcmp(fits_descr, previous_descr) != 0 ?
01384                         0 :  i-1 + nexist);
01385         
01386         passure( cards[i-1] != NULL, "%s %d %d", fits_descr, i-1, nexist);
01387 
01388         uves_free_string_const(&previous_descr);
01389         previous_descr = uves_sprintf("%s", fits_descr);
01390     }
01391 
01392     cards[length] = NULL;
01393 
01394   cleanup:
01395     uves_free_property(&new_prop);
01396     uves_free_string_const(&fits_descr);
01397     uves_free_string_const(&previous_descr);
01398     return cards;
01399 }
01400 
01401 /*----------------------------------------------------------------------------*/
01420 /*----------------------------------------------------------------------------*/
01421 static cpl_property **
01422 get_descr_info(int id, const char *descr, 
01423                char *type, int *length, int *bytelem)
01424 {
01425 
01426 
01427   *bytelem=*bytelem; //to remove compilation warning: this is not used
01428 
01429     cpl_property **cards = NULL;
01430     cpl_type t;
01431     const char *fits_descr = NULL;
01432     const char *previous_fits_descr = NULL;
01433     *type = ' ';
01434 
01435     passure( invariant(id), " ");
01436 
01437     assure( frame_is_open(id), CPL_ERROR_ILLEGAL_INPUT,
01438         "Frame no. %d is not open", id);
01439     
01440     check( load_frame_header(id),
01441        "Could not load header of file %s", frames[id].filename);
01442 
01443     cards = cpl_calloc(1, sizeof(cpl_property *));
01444     assure_mem( cards );
01445     
01446     *length = 0;
01447     do {
01448         *length += 1;
01449         cards = cpl_realloc(cards, (*length)*sizeof(cpl_property *));
01450         
01451         uves_free_string_const(&previous_fits_descr);
01452         previous_fits_descr = uves_sprintf("%s", fits_descr != NULL ? fits_descr : "----");
01453         
01454         uves_free_string_const(&fits_descr);
01455         fits_descr = convert_to_fits(descr, *length);
01456         
01457         uves_msg_debug("Searching for %d. occurence of %s", 
01458                        strcmp(fits_descr, previous_fits_descr) == 0 ?
01459                        *length : 1,
01460                        fits_descr);
01461         //uves_msg_debug("prev=%s curr=%s",previous_fits_descr,fits_descr);
01462         cards[*length-1] =
01463             uves_find_property(frames[id].header,
01464                                fits_descr, 
01465                                strcmp(fits_descr, previous_fits_descr) == 0 ?
01466                                *length - 1 : 0);
01467     }
01468     while (cards[*length-1] != NULL);
01469     
01470     *length -= 1;
01471 
01472     if (cards[0] != NULL)
01473     {
01474         t = cpl_property_get_type(cards[0]);
01475        
01476         switch(t)
01477         {
01478         case CPL_TYPE_INT   : *type = 'I'; break;
01479         case CPL_TYPE_FLOAT : *type = 'R'; break;
01480         case CPL_TYPE_STRING: *type = 'C'; break;
01481         case CPL_TYPE_DOUBLE: *type = 'D'; break;
01482         default: *type = ' '; break;
01483         }
01484 
01485         uves_msg_debug("Type is %c", *type);
01486     //AMO: Here the check on the length was *length == 1
01487         assure( *type != 'C' || *length <= 3, CPL_ERROR_UNSUPPORTED_MODE,
01488             "Cannot handle string array descriptor %s %s of length %d",
01489         descr, cpl_property_get_string(cards[0]),*length );
01490     
01491         if (*type == 'C')
01492         {
01493     //AMO: Here the check on the length was *length == 1
01494             passure( *length <= 3, "%d", *length );
01495             /* ... but we must return the string length,
01496                not the number of cards */
01497             *length = strlen(cpl_property_get_string(cards[0]));
01498         }
01499     }
01500     else
01501     {
01502         uves_msg_debug("%s not found", fits_descr);
01503         cpl_free(cards); cards = NULL;
01504         *length = 0;
01505     }
01506 
01507     passure( invariant(id), " ");
01508     
01509   cleanup:
01510     uves_free_string_const(&fits_descr);
01511     uves_free_string_const(&previous_fits_descr);
01512     if (cpl_error_get_code() != CPL_ERROR_NONE)
01513     {
01514         cpl_free(cards); cards = NULL;
01515     }
01516 
01517     return cards;
01518 }
01519 
01520 /*----------------------------------------------------------------------------*/
01530 /*----------------------------------------------------------------------------*/
01531 int flames_midas_scspro(const char *name)
01532 {
01533     int i;
01534 
01535     assure( current_caller == NULL, CPL_ERROR_ILLEGAL_INPUT,
01536         "MIDAS mode already running");
01537 
01538     uves_msg_debug("Initializing %s", name);
01539     current_caller = uves_sprintf("%s", name);
01540 
01541     assure( strcmp(name, "-1") != 0, CPL_ERROR_UNSUPPORTED_MODE,
01542         "Running outside MIDAS mode not supported");
01543 
01544     /* Reset all file handles */
01545     for (i = 0; i < MAX_OPEN; i++)
01546     {
01547         frames[i].filename = NULL;
01548     }
01549 
01550   cleanup:
01551     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01552 }
01553 
01554 /*----------------------------------------------------------------------------*/
01559 /*----------------------------------------------------------------------------*/
01560 
01561 int flames_midas_scsepi(void)
01562 {
01563     if (current_caller == NULL)
01564     {
01565         uves_msg_warning("MIDAS mode not running, "
01566                  "nothing to stop");
01567     }
01568     else
01569     {
01570             /* Check for unallocated resources */
01571             int i;
01572             for (i = 0; i < MAX_OPEN; i++)
01573                 {
01574                     if (frame_is_open(i))
01575                         {
01576                             uves_msg_warning("%s: %s no. %d: %s not deallocated",
01577                                              current_caller,
01578                                              frames[i].is_image ? "Image" : "Table",
01579                                              i, frames[i].filename);
01580 
01581                             frame_free(i);
01582                         }
01583                 }
01584 
01585         uves_msg_debug("Ending %s", current_caller);
01586         uves_free_string_const(&current_caller);
01587     }
01588 
01589     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01590 }
01591 
01592 /*----------------------------------------------------------------------------*/
01608 /*----------------------------------------------------------------------------*/
01609 int flames_midas_error_macro(const char *file, const char *function, int line,
01610                  int status)
01611 {
01612     uves_msg_debug("%s:%s() execution failed at %s:%s():%d", 
01613            current_caller != NULL ? current_caller : "???",
01614            function, file, function, line);
01615     
01616     return status;
01617 }
01618 
01619 /*----------------------------------------------------------------------------*/
01626 /*----------------------------------------------------------------------------*/
01627 
01628 int flames_midas_fail_macro(const char *file, const char *function, int line)
01629 { 
01630     const char *f = cpl_strdup(current_caller != NULL ? current_caller : "???");
01631     uves_msg_error("%s execution failed. Exit from MIDAS mode", f);
01632 
01633     uves_msg_debug("  at %s:%s():%d", file, function, line);
01634 
01635     flames_midas_scsepi();
01636 
01637     assure( false, CPL_ERROR_UNSPECIFIED, "%s failed", f);
01638 
01639   cleanup:
01640     uves_free_string_const(&f);
01641     return 1;
01642 }
01643 
01644 /*----------------------------------------------------------------------------*/
01654 /*----------------------------------------------------------------------------*/
01655 int flames_midas_sckwri(int *key, const int *values, 
01656             int felem, int maxvals, int *unit)
01657 {
01658     int i;
01659     *unit=*unit; //to remove compilation warning: this is not used
01660 
01661     assure_nomsg( key != NULL, CPL_ERROR_NULL_INPUT );
01662 
01663     uves_msg_debug("Writing %d elements to integer keyword", maxvals);
01664 
01665     for (i = 0; i < maxvals; i++) {
01666         key[(felem-1) + i] = values[i];
01667     }
01668 
01669   cleanup:
01670     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01671 }
01672 
01673 /*----------------------------------------------------------------------------*/
01683 /*----------------------------------------------------------------------------*/
01684 int flames_midas_sckwrd(double *key, const double *values, 
01685             int felem, int maxvals, int *unit)
01686 {
01687     int i;
01688     *unit=*unit; //to remove compilation warning: this is not used
01689     
01690     assure_nomsg( key != NULL, CPL_ERROR_NULL_INPUT );
01691 
01692     uves_msg_debug("Writing %d elements to double keyword", maxvals);
01693 
01694     for (i = 0; i < maxvals; i++) {
01695         key[(felem-1) + i] = values[i];
01696     }
01697 
01698     //fixme: is unit used? MIDAS doc. says it's unsupported
01699 
01700   cleanup:
01701     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01702 }
01703 
01704 
01705 /*----------------------------------------------------------------------------*/
01716 /*----------------------------------------------------------------------------*/
01717 int flames_midas_sckwrc(char *key, int noelem,
01718             const char *values, int felem, int maxvals, int *unit)
01719 {
01720     *unit=*unit; //to remove compilation warning: this is not used
01721     assure_nomsg( noelem == 1, CPL_ERROR_UNSUPPORTED_MODE); 
01722     //fixme: remove from interface if this is always the case
01723 
01724     uves_msg_debug("Writing %d elements to character keyword", maxvals);
01725 
01726     strncpy(key+(felem-1), values, maxvals);
01727 
01728     //fixme: is unit used?
01729   cleanup:
01730     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01731 }
01732 
01733 /*----------------------------------------------------------------------------*/
01744 /*----------------------------------------------------------------------------*/
01745 int flames_midas_sckgetc(const char *key, 
01746              int felem, int maxvals, 
01747              int *actvals, char *values)
01748 {
01749 
01750     assure_nomsg( key    != NULL, CPL_ERROR_NULL_INPUT );
01751     assure_nomsg( values != NULL, CPL_ERROR_NULL_INPUT );
01752     assure_nomsg( actvals!= NULL, CPL_ERROR_NULL_INPUT );
01753 
01754     strncpy(values, key + (felem - 1), maxvals);
01755     values[strlen(key)+1] = '\0';
01756     *actvals = strlen(values);
01757 
01758     /*
01759       uves_msg_warning("Copy %s to %s",
01760                    key, values);
01761     
01762     */
01763 
01764   cleanup:
01765     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01766 }
01767 
01768 /*----------------------------------------------------------------------------*/
01778 /*----------------------------------------------------------------------------*/
01779 int flames_midas_sckgetc_fs(const cpl_frameset *key, 
01780                             int felem, int maxvals, 
01781                             int *actvals, const cpl_frameset **values)
01782 {
01783     maxvals=maxvals; //to remove compilation warning: this is not used
01784     assure_nomsg( key != NULL, CPL_ERROR_NULL_INPUT );
01785     assure( felem == 1, CPL_ERROR_ILLEGAL_INPUT,
01786             "felem = %d", felem );
01787     assure_nomsg( actvals != NULL, CPL_ERROR_NULL_INPUT );
01788     assure_nomsg( values  != NULL, CPL_ERROR_NULL_INPUT );
01789 
01790     *values = key;
01791 
01792   cleanup:
01793     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01794 }
01795 
01796 /*----------------------------------------------------------------------------*/
01806 /*----------------------------------------------------------------------------*/
01807 int flames_midas_sckgetc_fsp(cpl_frameset **key, 
01808                             int felem, int maxvals, 
01809                             int *actvals, cpl_frameset ***values)
01810 {
01811     maxvals=maxvals; //to remove compilation warning: this is not used
01812     assure_nomsg( key != NULL, CPL_ERROR_NULL_INPUT );
01813     assure( felem == 1, CPL_ERROR_ILLEGAL_INPUT,
01814             "felem = %d", felem );
01815     assure_nomsg( actvals != NULL, CPL_ERROR_NULL_INPUT );
01816     assure_nomsg( values  != NULL, CPL_ERROR_NULL_INPUT );
01817 
01818     *values = key;
01819 
01820   cleanup:
01821     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01822 }
01823 
01824 /*----------------------------------------------------------------------------*/
01836 /*----------------------------------------------------------------------------*/
01837 int flames_midas_sckrdd(const double *key, int felem, int maxvals, 
01838             int *actvals, double *values, int *unit, int *null)
01839 {
01840     int i;
01841     *unit=*unit; //to remove compilation warning: this is not used
01842     *null=*null; //to remove compilation warning: this is not used
01843 
01844     assure_nomsg( key != NULL, CPL_ERROR_NULL_INPUT );
01845 
01846     *actvals = 0;
01847     for (i = 0; i < maxvals; i++)
01848     {
01849         values[i] = key[(felem-1)+i];
01850         (*actvals)++;
01851     }
01852 
01853     /* unit, null not implemented in MIDAS */
01854 
01855   cleanup:
01856     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01857 }
01858 
01859 /*----------------------------------------------------------------------------*/
01871 /*----------------------------------------------------------------------------*/
01872 int flames_midas_sckrdr(const float *key, int felem, int maxvals, 
01873             int *actvals, float *values, int *unit, int *null)
01874 {
01875     int i;
01876     *unit=*unit; //to remove compilation warning: this is not used
01877     *null=*null; //to remove compilation warning: this is not used
01878 
01879     assure_nomsg( key != NULL, CPL_ERROR_NULL_INPUT );
01880 
01881     *actvals = 0;
01882     for (i = 0; i < maxvals; i++)
01883     {
01884         values[i] = key[(felem-1)+i];
01885         (*actvals)++;
01886     }
01887 
01888     /* unit, null not implemented in MIDAS */
01889 
01890   cleanup:
01891     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01892 }
01893 
01894 /*----------------------------------------------------------------------------*/
01906 /*----------------------------------------------------------------------------*/
01907 int flames_midas_sckrdi(const int *key, int felem, int maxvals, 
01908             int *actvals, int *values, int *unit, int *null)
01909 {
01910     int i;
01911     *unit=*unit; //to remove compilation warning: this is not used
01912     *null=*null; //to remove compilation warning: this is not used
01913 
01914     *actvals = 0;
01915     for (i = 0; i < maxvals; i++)
01916     {
01917         values[i] = key[(felem-1)+i];
01918         (*actvals)++;
01919     }
01920 
01921     /* unit, null not implemented in MIDAS */
01922 
01923 /*  cleanup: */
01924     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01925 }
01926 
01927 /*----------------------------------------------------------------------------*/
01940 /*----------------------------------------------------------------------------*/
01941 int flames_midas_sckrdc(const char *key, int noelm, int felem, int maxvals, 
01942             int *actvals, char *values, int *unit, int *null)
01943 {
01944     /* This function is only used in calls, like this
01945        
01946          SCKRDC("H_RON_L",16,1,1,&actvals, h_ron_l, &unit, &null)
01947 
01948      where  noelm is the string length and felem = maxvals = 1   */
01949     *unit=*unit; //to remove compilation warning: this is not used
01950     *null=*null; //to remove compilation warning: this is not used
01951 
01952     assure( felem == 1, CPL_ERROR_UNSUPPORTED_MODE, "Implement me" );
01953     assure( maxvals == 1, CPL_ERROR_UNSUPPORTED_MODE, "Implement me" );
01954 
01955     strncpy(values, key + (felem - 1), noelm);
01956     values[noelm] = '\0';
01957     *actvals = strlen(values);
01958 
01959     /* unit, null not implemented in MIDAS */
01960 
01961   cleanup:
01962     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01963 }
01964 
01965 /*----------------------------------------------------------------------------*/
01976 /*----------------------------------------------------------------------------*/
01977 static int
01978 sckfnd(const char the_type, const void *key, char *type, int *noelem, int *bytelem)
01979 {
01980     *noelem=*noelem; //to remove compilation warning: this is not used
01981     *bytelem=*bytelem; //to remove compilation warning: this is not used
01982     if (key == NULL)
01983     {
01984         uves_msg_debug("Keyword is NULL");   
01985         *type = ' ';
01986     }
01987     else
01988     {
01989         *type = the_type;
01990     }
01991     /* Fixme: what about noelem  (needs to be passed from the caller) */
01992     
01993 //  cleanup:
01994     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
01995 }
01996 
01997 /*----------------------------------------------------------------------------*/
02001 /*----------------------------------------------------------------------------*/
02002 int flames_midas_sckfnd_double(const double *key, char *type, int *noelem, int *bytelem)
02003 {
02004     return sckfnd('D', key, type, noelem, bytelem);
02005 }
02006 /*----------------------------------------------------------------------------*/
02010 /*----------------------------------------------------------------------------*/
02011 int flames_midas_sckfnd_float(const float *key, char *type, int *noelem, int *bytelem)
02012 {
02013     return sckfnd('R', key, type, noelem, bytelem);
02014 }
02015 
02016 /*----------------------------------------------------------------------------*/
02020 /*----------------------------------------------------------------------------*/
02021 int flames_midas_sckfnd_int(const int *key, char *type, int *noelem, int *bytelem)
02022 {
02023     return sckfnd('I', key, type, noelem, bytelem);
02024 }
02025 
02026 /*----------------------------------------------------------------------------*/
02030 /*----------------------------------------------------------------------------*/
02031 int flames_midas_sckfnd_string(const char *key, char *type, int *noelem, int *bytelem)
02032 {
02033     return sckfnd('C', key, type, noelem, bytelem);
02034 }
02035 
02036 /*----------------------------------------------------------------------------*/
02042 /*----------------------------------------------------------------------------*/
02043 
02044 int flames_midas_sctput(const char *msg, 
02045             const char *function, const char *file, int line)
02046 {
02047     if (strncmp(msg, "Error", 5) == 0)
02048     {
02049         uves_msg_error("%s:%d: %s", file, line, msg);
02050     }
02051     else if (strncmp(msg, "Warning", 7) == 0)
02052     {
02053         uves_msg_warning("%s: %s", function, msg);
02054     }
02055     else
02056     {
02057             /* indented */
02058         uves_msg_low("%s: %s", function, msg);
02059     }
02060 
02061 //  cleanup:
02062     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02063 }
02064 
02065 /*----------------------------------------------------------------------------*/
02093 /*----------------------------------------------------------------------------*/
02094 int flames_midas_scfinf(const char *name, int fno, int *ibuf)
02095 {
02096     FILE *file;
02097     uves_propertylist *header = NULL;
02098 
02099     uves_msg_debug("fno = %d", fno);
02100 
02101     if (name == NULL) return 1;
02102     
02103     /* Test for existence */
02104     file = fopen(name, "r");
02105     if (file == NULL)
02106         {
02107             uves_msg_debug("File %s could not be opened", name);
02108             return 1;
02109         }
02110     uves_msg_debug("File %s could be opened", name);
02111     fclose(file);
02112     
02113     if (fno == 3) {
02114         /* The FLAMES code needs only the information about the
02115            file type which is written to ibuf[0] */
02116         if (uves_get_nextensions(name) > 0) {
02117             ibuf[0] = F_TBL_TYPE;
02118         }
02119         else {
02120             ibuf[0] = F_IMA_TYPE;
02121         }
02122     }
02123     else if (fno == 4)
02124     {
02125             /* The FLAMES code needs only the data type
02126                which is written to ibuf[1] */
02127             int bitpix;
02128 
02129             check( header = uves_propertylist_load(name, 0),
02130                    "Could not load %s primary header", name);
02131 
02132             check( bitpix = uves_pfits_get_bitpix(header),
02133                    "Could not get BITPIX from %s", name);
02134 
02135             uves_msg_debug("BITPIX is %d", bitpix);
02136 
02137             switch (bitpix) {
02138             case  16: ibuf[1] = D_I2_FORMAT; break; /* 16 bit signed integer */
02139             case  32: ibuf[1] = D_I4_FORMAT; break; /* 32 bit signed integer */
02140             case -32: ibuf[1] = D_R4_FORMAT; break; /* 32 bit floating point */
02141             case -64: ibuf[1] = D_R8_FORMAT; break; /* 64 bit floating point */
02142             default:
02143                 assure( false, CPL_ERROR_UNSUPPORTED_MODE,
02144                         "Cannot convert BITPIX = %d to DATTYPE",
02145                         bitpix);
02146                 break;
02147             }
02148     }
02149     else if (fno == 99)
02150     {
02151             /* Just test for file existence */
02152     }
02153     else
02154     {
02155         assure( false, CPL_ERROR_UNSUPPORTED_MODE,
02156                     "fno = %d is not needed by FLAMES code", fno);
02157     }
02158     
02159   cleanup:
02160     uves_free_propertylist(&header);
02161     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02162 }
02163 
02164 /*----------------------------------------------------------------------------*/
02174 /*----------------------------------------------------------------------------*/
02175 int flames_midas_scfopn(const char *name, int dattype, int newopn, int filtype,
02176             int *imno)
02177 {
02178     uves_msg_debug("Trying to open %s", name);
02179 
02180     if (filtype == F_IMA_TYPE) {
02181 
02182         if (newopn == 0) {
02183             
02184             /* Find first open slot */
02185             int i;
02186             bool found = false;
02187             for (i = 0; !found && i < MAX_OPEN; i++)
02188                 {
02189                     if (!frame_is_open(i))
02190                         {
02191                             cpl_type type;
02192                             
02193                             found = true;
02194                             *imno = i;
02195                             
02196                             type = flames_midas_image_dtype_to_cpltype(dattype);
02197                             
02198                             frame_new_image(*imno, name, NULL, false,
02199                                             NULL, type, dattype);
02200                             
02201                             uves_msg_debug("Opened image no. %d: %s as type %s",
02202                                            i, name, 
02203                                            uves_tostring_cpl_type(type));
02204                         }
02205                 }
02206             
02207             assure( found, CPL_ERROR_UNSUPPORTED_MODE,
02208                     "Cannot open more than %d image files",
02209                     MAX_OPEN);
02210         }
02211         else
02212             {
02213                 
02214                 assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me");
02215             }
02216     }
02217     else
02218     {
02219             assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me");
02220     }
02221 
02222   cleanup:
02223     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02224 }
02225 
02226 /*----------------------------------------------------------------------------*/
02240 /*----------------------------------------------------------------------------*/
02241 int flames_midas_scfcre(const char *name, int dattype, int iomode, int filtype, 
02242                         int size, int *imno)
02243 {
02244     if (filtype == F_IMA_TYPE)
02245     {
02246         if (iomode == F_O_MODE) /* output: create empty header */
02247         {
02248 
02249             /* Find first open slot */
02250             int i;
02251             bool found = false;
02252                     cpl_type type;
02253 
02254             for (i = 0; !found && i < MAX_OPEN; i++)
02255             {
02256 
02257                 if (!frame_is_open(i))
02258                 {
02259                     found = true;
02260                     *imno = i;
02261                     
02262                     uves_msg_debug("Opened image no. %d: %s",
02263                            i, name);
02264                 }
02265             }
02266             
02267             assure( found, CPL_ERROR_UNSUPPORTED_MODE,
02268                 "Cannot open more than %d image files",
02269                 MAX_OPEN);
02270             
02271                     type = flames_midas_image_dtype_to_cpltype(dattype);
02272                    
02273                     /* Create Nx1 image, set proper size later */
02274                     frame_new_image(*imno, name, uves_propertylist_new(), true,
02275                                     cpl_image_new(size, 1, type), type, dattype);
02276 
02277                 }
02278 
02279         else
02280         {
02281             assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me");
02282         }
02283     }
02284     else
02285     {
02286         assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me");
02287     }
02288 
02289 
02290     passure( invariant(*imno), " ");
02291 
02292   cleanup:
02293     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02294 }
02295 
02296 /*----------------------------------------------------------------------------*/
02302 /*----------------------------------------------------------------------------*/
02303 static int
02304 frame_close(int id)
02305 {
02306     cpl_property **cards = NULL;
02307     fitsfile *fptr = NULL;
02308     int fio_status = 0;
02309 
02310     passure( invariant(id), " ");
02311     if (!frame_is_open(id))  {
02312 
02313 
02314         uves_msg_warning("%s number %d is not open, cannot close", 
02315                          frames[id].is_image ? "Image" : "Table",
02316                          id);
02317 
02318     }
02319     else {
02320         if (frames[id].need_to_save) {
02321             char type;
02322             int bytelem;
02323             int naxis;
02324             
02325             uves_msg_debug("Saving frame %s to disk", frames[id].filename);
02326             
02327             check( load_frame(id),
02328                    "Could not load frame %s", frames[id].filename);
02329                     
02330             check( load_frame_header(id),
02331                    "Could not load %s header", frames[id].filename);
02332                     
02333             check( cards = get_descr_info(id, "NPIX",
02334                                           &type, &naxis, &bytelem),
02335                    "Could not get info on descriptor NPIX");
02336                     
02337             check( convert_to_history(&frames[id].header),
02338                    "Could not convert header");
02339 
02340             /* Note header is free'd below, so changing it is ok */
02341              if (frames[id].is_image)
02342                 {
02343 
02344 
02345                     bool save_as_bitpix16 =
02346                         (frames[id].data.image.dtype == D_I1_FORMAT ||
02347                          frames[id].data.image.dtype == D_I2_FORMAT);
02348                     /* Save D_I1_FORMAT / D_I2_FORMAT  (masks) as 16 bit unsigned, 
02349                        otherwise 32 bit signed */
02350 
02351                     bool save_as_1d = (naxis == 1);
02352                     /* Don't save 2d images as 1d, we will loose START/STEP descriptors */
02353 
02354                     assure( naxis == 1 || naxis == 2 || naxis == 3 || naxis == 4,
02355                             CPL_ERROR_UNSUPPORTED_MODE,
02356                             "Cannot save image with NAXIS = %d", naxis);
02357 
02358                     uves_msg_debug("Saving %dd image", naxis);
02359                     
02360                     check( uves_save_image(frames[id].data.image.image,
02361                                            frames[id].filename,
02362                                            frames[id].header,
02363                                            save_as_bitpix16,
02364                                            save_as_1d),
02365                            "Error saving image %s", frames[id].filename);
02366 
02367                     if (naxis == 2 || naxis == 3 || naxis == 4) {
02368                         int NAXIS[4];
02369                         int unit, null;
02370                         int actvals;
02371                         char dummy[100]; /* More than length of FITS key record */
02372                         char err_message[81];  /* long enough according to CFITSIO doc. */
02373                         int current_naxis;   /* As written by the previous uves_save_image()
02374                                                 call */
02375                         
02376                         assure( 0 == flames_midas_scdrdi(id, "NPIX",
02377                                                          1, naxis,
02378                                                          &actvals, NAXIS,
02379                                                          &unit, &null), 
02380                                 CPL_ERROR_ILLEGAL_INPUT,
02381                                 "Failed to read NPIX");
02382                         
02383                         assure( actvals == naxis, CPL_ERROR_ILLEGAL_INPUT,
02384                                 "naxis = %d but actvals = %d", naxis, actvals);
02385                                 
02386                         /* CPL and QFITS cannot change a FITS header without 
02387                            load/saving the data buffer
02388                            so use CFITSIO for this basic task */
02389 
02390                         fits_open_file(&fptr, frames[id].filename, READWRITE, &fio_status);
02391                         
02392                         assure( fio_status == 0, CPL_ERROR_ILLEGAL_OUTPUT,
02393                                 "Failed to open file %s", frames[id].filename);
02394 
02395                         /* Move to beginning of header, then to location of NAXIS (which should already exist) */
02396                         fits_read_record(fptr, 0, dummy, &fio_status);
02397                         /* fits_read_card(fptr, (char*)"NAXIS", dummy, &fio_status); */
02398                         fits_read_key(fptr, TINT, (char*)"NAXIS", &current_naxis, NULL, &fio_status);
02399 
02400                         fits_update_key(fptr, TINT, (char*)"NAXIS", &naxis, (char*)"Empty unit", &fio_status);
02401                         fits_update_key(fptr, TINT, (char*)"NAXIS1", &NAXIS[0], (char*)"Empty unit", &fio_status);
02402 
02403                         if (current_naxis < 2) {
02404                             fits_insert_card(fptr, (char*)"NAXIS2", &fio_status);
02405                         }
02406                         fits_update_key(fptr, TINT, (char*)"NAXIS2", &NAXIS[1], (char*)"Empty unit", &fio_status);
02407                         
02408                         if (naxis >= 3) {
02409                             fits_insert_card(fptr, (char*)"NAXIS3", &fio_status);
02410                             fits_update_key(fptr, TINT, (char*)"NAXIS3", &NAXIS[2], (char*)"Empty unit", &fio_status);
02411                         }
02412                         
02413                         if (naxis >= 4) {
02414                             fits_insert_card(fptr, (char*)"NAXIS4", &fio_status);
02415                             fits_update_key(fptr, TINT, (char*)"NAXIS4", &NAXIS[3], (char*)"Empty unit", &fio_status);
02416                         }
02417                         
02418                         fits_close_file(fptr, &fio_status);
02419                         
02420                         if (fio_status != 0) fits_read_errmsg(err_message);
02421                         assure( fio_status == 0, CPL_ERROR_ILLEGAL_OUTPUT,
02422                                 "Error '%s' code %d while updating %s FITS header", 
02423                                 err_message, fio_status, frames[id].filename);
02424                     }
02425 
02426                 }
02427             else
02428                 {
02429                     cpl_table_set_size(frames[id].data.table.table,
02430                                        frames[id].data.table.maxrow);
02431                   
02432                     check( uves_table_save(frames[id].data.table.table,
02433                                            frames[id].header, /* Primary header */
02434                                            NULL,                /* Ext. header */
02435                                            frames[id].filename,
02436                                            CPL_IO_DEFAULT),
02437                            "Error saving table %s", frames[id].filename);
02438                 }
02439                     
02440             frames[id].need_to_save = false;
02441 
02442         }
02443         else
02444             {
02445                 uves_msg_debug("Closing %s %s (don't save to disk)", 
02446                                frames[id].is_image ? "image" : "table",
02447                                frames[id].filename);
02448             }
02449             
02450         frame_free(id);
02451 
02452     }
02453     
02454     passure( !frame_is_open(id), " ");
02455     passure( invariant(id), " ");
02456 
02457   cleanup:
02458     cpl_free(cards); cards = NULL;
02459     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02460 }
02461     
02462 /*----------------------------------------------------------------------------*/
02469 /*----------------------------------------------------------------------------*/
02470 int flames_midas_scfclo(int imno)
02471 {
02472     return frame_close(imno);
02473 }
02474 
02475 /*----------------------------------------------------------------------------*/
02487 /*----------------------------------------------------------------------------*/
02488 int flames_midas_scfget(int imno, int felem, int size, int *actsize, char *bufadr)
02489 {
02490   //cpl_type type;
02491 
02492     passure( invariant(imno), " ");
02493 
02494     assure( frame_is_open(imno) && frames[imno].is_image, CPL_ERROR_ILLEGAL_INPUT,
02495             "Image no. %d is not open", imno);
02496 
02497     check( load_frame(imno),
02498        "Could not load image %s", frames[imno].filename);
02499 
02500     assure( (felem-1) + size <=
02501         cpl_image_get_size_x(frames[imno].data.image.image)*
02502         cpl_image_get_size_y(frames[imno].data.image.image),
02503         CPL_ERROR_ACCESS_OUT_OF_RANGE,
02504         "Cannot read %d bytes of CPL image of size %" CPL_SIZE_FORMAT "x%" CPL_SIZE_FORMAT " position %d",
02505         size, 
02506         cpl_image_get_size_x(frames[imno].data.image.image),
02507         cpl_image_get_size_y(frames[imno].data.image.image),
02508         felem-1);
02509 
02510     switch(frames[imno].data.image.type) {
02511     case CPL_TYPE_INT:
02512     {
02513         int *buffer;
02514         int i;
02515         buffer = cpl_image_get_data_int(frames[imno].data.image.image);
02516         buffer += (felem-1);
02517         
02518         switch(frames[imno].data.image.dtype) {
02519         case D_I1_FORMAT:
02520             for (i = 0; i < size; i++)
02521                 {
02522                     ((char *)bufadr)[i] = buffer[i];
02523                 }
02524             break;
02525         case D_I2_FORMAT:
02526         case D_I4_FORMAT:
02527             for (i = 0; i < size; i++)
02528                 {
02529                     ((int *)bufadr)[i] = buffer[i];
02530                 }
02531             break;
02532         default:
02533             assure_nomsg( false, CPL_ERROR_UNSUPPORTED_MODE );
02534             break;
02535         }
02536         *actsize = size;
02537     }
02538     break;
02539     case CPL_TYPE_FLOAT:
02540     {
02541         float *buffer;
02542         int i;
02543         buffer = cpl_image_get_data_float(frames[imno].data.image.image);
02544         buffer += (felem-1);
02545         
02546         for (i = 0; i < size; i++)
02547             {
02548                 ((float *)bufadr)[i] = buffer[i];
02549             }
02550         *actsize = size;
02551     }
02552     break;
02553     default:
02554         assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Type is %s",
02555                 uves_tostring_cpl_type(frames[imno].data.image.type));
02556         break;
02557     }
02558     
02559     passure( invariant(imno), " ");
02560 
02561   cleanup: 
02562     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02563 }
02564 
02565 
02566 /*----------------------------------------------------------------------------*/
02576 /*----------------------------------------------------------------------------*/
02577 int flames_midas_scfput(int imno, int felem, int size, const char *bufadr)
02578 {
02579     int i;
02580 
02581     passure( invariant(imno), " ");
02582 
02583     assure( frame_is_open(imno) && frames[imno].is_image, CPL_ERROR_ILLEGAL_INPUT,
02584         "Image no. %d is not open", imno);
02585 
02586     /* Load image if necessary, then overwrite part, or all of data buffer */
02587     check( load_frame(imno),
02588            "Could not load image %s", frames[imno].filename);
02589 
02590     assure( (felem-1) + size <=
02591         cpl_image_get_size_x(frames[imno].data.image.image)*
02592         cpl_image_get_size_y(frames[imno].data.image.image),
02593         CPL_ERROR_ACCESS_OUT_OF_RANGE,
02594         "Cannot write %d pixels to CPL image of size %" CPL_SIZE_FORMAT "x%" CPL_SIZE_FORMAT " position %d",
02595         size, 
02596         cpl_image_get_size_x(frames[imno].data.image.image),
02597         cpl_image_get_size_y(frames[imno].data.image.image),
02598         felem-1);
02599 
02600     uves_msg_debug("Writing %d pixels to image %s",
02601                    size, frames[imno].filename);
02602 
02603     switch(frames[imno].data.image.type) {
02604     case CPL_TYPE_INT:
02605     {
02606         int *buffer;
02607         buffer = cpl_image_get_data_int(frames[imno].data.image.image);
02608         buffer += (felem-1);
02609 
02610         switch(frames[imno].data.image.dtype) {
02611         case D_I1_FORMAT:
02612             for (i = 0; i < size; i++)
02613                 {
02614                     buffer[i] = ((char *)bufadr)[i];
02615                 }
02616             break;
02617         case D_I2_FORMAT:
02618         case D_I4_FORMAT:
02619             for (i = 0; i < size; i++)
02620                 {
02621                     buffer[i] = ((int *)bufadr)[i];
02622                 }
02623             break;
02624         default:
02625             assure_nomsg( false, CPL_ERROR_UNSUPPORTED_MODE );
02626             break;
02627         }
02628     }
02629     break;
02630     case CPL_TYPE_FLOAT:
02631     {
02632         float *buffer;
02633         buffer = cpl_image_get_data_float(frames[imno].data.image.image);
02634         buffer += (felem-1);
02635         
02636         for (i = 0; i < size; i++)
02637             {
02638                 buffer[i] = ((float *)bufadr)[i];
02639             }
02640     }
02641     break;
02642     case CPL_TYPE_DOUBLE:
02643     {
02644         double *buffer;
02645         buffer = cpl_image_get_data_double(frames[imno].data.image.image);
02646         buffer += (felem-1);
02647         
02648         for (i = 0; i < size; i++)
02649             {
02650                 buffer[i] = ((double *)bufadr)[i];
02651             }
02652     }
02653     break;
02654     default:
02655         assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Type is %s", 
02656                 uves_tostring_cpl_type(frames[imno].data.image.type));
02657         break;
02658     }
02659     
02660     frames[imno].need_to_save = true;  /* Memory buffer has changed */
02661 
02662     passure( invariant(imno), " ");
02663 
02664   cleanup:
02665     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02666 }
02667 
02668 /*----------------------------------------------------------------------------*/
02682 /*----------------------------------------------------------------------------*/
02683 int flames_midas_scdfnd(int id, const char *descr, 
02684             char *type, int *noelem, int *bytelem)
02685 {
02686   cpl_property **cards = NULL;
02687 
02688   passure( invariant(id), " ");
02689   assure_nomsg( descr != NULL, CPL_ERROR_NULL_INPUT );
02690 
02691   if (strcmp(descr, "LHCUTS") == 0)
02692     {
02693       int datamin_noelem, datamax_noelem;
02694       char datamin_type, datamax_type;
02695                 
02696       *noelem = 2; /* LHCUTS1 and LHCUTS2 always exist */
02697       *type ='R';
02698             
02699       flames_midas_scdfnd(id, "DATAMIN", &datamin_type, &datamin_noelem, bytelem);
02700       flames_midas_scdfnd(id, "DATAMAX", &datamax_type, &datamax_noelem, bytelem);
02701             
02702       assure( datamin_noelem <= 1, CPL_ERROR_ILLEGAL_INPUT,
02703           "Multiple (%d) DATAMIN keywords found", datamin_noelem);
02704 
02705       assure( datamax_noelem <= 1, CPL_ERROR_ILLEGAL_INPUT,
02706           "Multiple (%d) DATAMIN keywords found", datamax_noelem);
02707 
02708       if (datamin_noelem > 0)
02709     {
02710       *noelem = 3;
02711       assure( datamin_type == 'D', CPL_ERROR_TYPE_MISMATCH,
02712           "DATAMIN has type %c, %c expected", datamin_type, 'D');
02713 
02714       if (datamax_noelem > 0)
02715         {
02716           *noelem = 4;
02717           assure( datamax_type == 'D', CPL_ERROR_TYPE_MISMATCH,
02718               "DATAMAX has type %c, %c expected", datamax_type, 'D');
02719         }
02720     }
02721 
02722     }
02723   else
02724     {
02725       check( cards = get_descr_info(id, descr,
02726                     type, noelem, bytelem),
02727          "Could not get info on descriptor %s", descr);
02728             
02729       if (cards == NULL)
02730     {
02731       *type = ' ';
02732       uves_msg_debug("Descriptor %s not found",descr);
02733     }
02734       else
02735     {
02736       uves_msg_debug("Found descriptor %s, type = %c, length = %d",
02737                descr, *type, *noelem);
02738     }
02739     }
02740 
02741   passure( invariant(id), " ");
02742 
02743  cleanup:
02744   cpl_free(cards); cards = NULL;
02745 
02746   return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02747 }
02748 
02749 
02750 
02751 /*----------------------------------------------------------------------------*/
02765 /*----------------------------------------------------------------------------*/
02766 int flames_midas_scdprs(int id, const char *descr, 
02767             char *type, int *noelem, int *bytelem)
02768 {
02769   cpl_property **cards = NULL;
02770 
02771   passure( invariant(id), " ");
02772   assure_nomsg( descr != NULL, CPL_ERROR_NULL_INPUT );
02773 
02774   if (strcmp(descr, "LHCUTS") == 0)
02775     {
02776       int datamin_noelem, datamax_noelem;
02777       char datamin_type, datamax_type;
02778                 
02779       *noelem = 2; /* LHCUTS1 and LHCUTS2 always exist */
02780       *type ='R';
02781             
02782       flames_midas_scdfnd(id, "DATAMIN", &datamin_type, &datamin_noelem, bytelem);
02783       flames_midas_scdfnd(id, "DATAMAX", &datamax_type, &datamax_noelem, bytelem);
02784             
02785       assure( datamin_noelem <= 1, CPL_ERROR_ILLEGAL_INPUT,
02786           "Multiple (%d) DATAMIN keywords found", datamin_noelem);
02787 
02788       assure( datamax_noelem <= 1, CPL_ERROR_ILLEGAL_INPUT,
02789           "Multiple (%d) DATAMIN keywords found", datamax_noelem);
02790 
02791       if (datamin_noelem > 0)
02792     {
02793       *noelem = 3;
02794       assure( datamin_type == 'D', CPL_ERROR_TYPE_MISMATCH,
02795           "DATAMIN has type %c, %c expected", datamin_type, 'D');
02796 
02797       if (datamax_noelem > 0)
02798         {
02799           *noelem = 4;
02800           assure( datamax_type == 'D', CPL_ERROR_TYPE_MISMATCH,
02801               "DATAMAX has type %c, %c expected", datamax_type, 'D');
02802         }
02803     }
02804 
02805     }
02806   else
02807     {
02808       check( cards = get_descr_info(id, descr,
02809                     type, noelem, bytelem),
02810          "Could not get info on descriptor %s", descr);
02811             
02812       if (cards == NULL)
02813     {
02814       *type = ' ';
02815       uves_msg_debug("Descriptor %s not found",descr);
02816           cpl_free(cards); cards = NULL;
02817       return 1;
02818     }
02819       else
02820     {
02821       uves_msg_debug("Found descriptor %s, type = %c, length = %d",
02822                descr, *type, *noelem);
02823     }
02824     }
02825 
02826   passure( invariant(id), " ");
02827 
02828  cleanup:
02829   cpl_free(cards); cards = NULL;
02830 
02831   return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02832 }
02833 
02834 /*----------------------------------------------------------------------------*/
02849 /*----------------------------------------------------------------------------*/
02850 static int
02851 scdrd(char expected_type, int id, const char *descr, 
02852       int felem, int maxvals,
02853       int *actvals, void *values,
02854       int *unit, int *null)
02855 {
02856     char type;
02857     int length;
02858     int bytelem;
02859     cpl_property **cards = NULL;
02860     int i;
02861     *unit=*unit; //to remove compilation warning: this is not used
02862     *null=*null; //to remove compilation warning: this is not used
02863 
02864     passure( invariant(id), " ");
02865 
02866     check( cards = get_descr_info(id, descr, &type,
02867                                   &length, &bytelem),
02868        "Could not get info on descriptor %s", descr);
02869 
02870     assure( cards != NULL, CPL_ERROR_DATA_NOT_FOUND,
02871         "Descriptor %s not found in file %s", descr, frames[id].filename);
02872 
02873     /* Allow conversion R -> D */
02874     assure( (expected_type == 'D' && type == 'R') 
02875             ||
02876             type == expected_type, CPL_ERROR_TYPE_MISMATCH,
02877         "Descriptor %s has type %c, %c expected",
02878         descr, type, expected_type);
02879 
02880     passure( type != 'C' || felem == 1, "'%c' %d", type, felem);
02881 
02882     *actvals = 0;
02883     //uves_msg_warning("length=%d",length);
02884     for (i = felem-1; i < length; i++)
02885     {
02886         if (*actvals < maxvals)
02887         {
02888             uves_msg_debug("Getting %d of %d (max %d) values of descriptor %s",
02889                    *actvals + 1, length - (felem-1), maxvals, descr);
02890 
02891             switch(type) {
02892             case 'I': 
02893                 ((int *)values)[i-(felem-1)]    = cpl_property_get_int(cards[i]); 
02894                 uves_msg_debug("Value = %d", ((int *)values)[i-(felem-1)]);
02895                 break;
02896             case 'D': 
02897                 ((double *)values)[i-(felem-1)] = cpl_property_get_double(cards[i]);
02898                 uves_msg_debug("Value = %g", ((double *)values)[i-(felem-1)]);
02899                 break;
02900             case 'R': 
02901                 switch(expected_type) {
02902                 case 'R':
02903                     ((float *)values)[i-(felem-1)]  = cpl_property_get_float(cards[i]); 
02904                     uves_msg_debug("Value = %g", ((float *)values)[i-(felem-1)]);
02905                     break;
02906                 case 'D':
02907                     ((double *)values)[i-(felem-1)]  = cpl_property_get_float(cards[i]); 
02908                     uves_msg_debug("Value = %g", ((double *)values)[i-(felem-1)]);
02909                     break;
02910                 default:
02911                     passure( false, " ");
02912                     break;
02913                 }
02914                 break;
02915             case 'C':
02916                 ((char *)values)[i-(felem-1)]   = cpl_property_get_string(cards[0])[i]; 
02917                 uves_msg_debug("Value = %c", ((char *)values)[i-(felem-1)]);
02918                 break;
02919             default: 
02920                 assure( false, CPL_ERROR_INVALID_TYPE, "Type is %c", type); 
02921                 break;
02922             }
02923             *actvals += 1;
02924         }
02925     }
02926 
02927     if (type == 'C' && *actvals < maxvals)
02928     {
02929         /* length is the string length,
02930            terminate with 0
02931            This character does not count in actvals
02932                but is include in maxvals
02933         */
02934         ((char *)values)[length-(felem-1)] = '\0';
02935     }
02936     
02937     /* unit, null not implemented by MIDAS */
02938 
02939     passure( invariant(id), " ");
02940 
02941   cleanup:
02942     cpl_free(cards); cards = NULL;
02943 
02944     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02945 }
02946 /*----------------------------------------------------------------------------*/
02953 /*----------------------------------------------------------------------------*/
02954 int flames_midas_scdrdi(int id, const char *descr, 
02955             int felem, int maxvals,
02956             int *actvals, int *values,
02957             int *unit, int *null)
02958 {
02959     char *char_values = NULL;
02960 
02961 #if 0
02962     if (strcmp(descr, "MAXFIBRES") == 0)
02963     {
02964         char_values = cpl_malloc(maxvals + 1);
02965         assure_mem( char_values );
02966         char_values[0] = '\0';
02967 
02968         assure( felem == 1, CPL_ERROR_UNSUPPORTED_MODE,
02969             "first element no. (%d) is not 1", felem);
02970 
02971         check( scdrd('C', imno, descr, felem, maxvals, actvals, char_values, unit, null),
02972            "Reading %s as string failed", descr);
02973 
02974         assure( strlen(char_values) == 1, CPL_ERROR_ILLEGAL_INPUT,
02975             "MAXFIBRES value (%s) has length different from 1",
02976             char_values);
02977 
02978         /* We have a string of length 1, convert to integer */
02979         errno = 0;
02980         values[0] = atoi(char_values);
02981         assure( errno == 0, CPL_ERROR_ILLEGAL_OUTPUT,
02982             "Conversion of %s to integer failed", char_values);
02983 
02984         cpl_msg_debug("Got value %s (%d)", char_values, values[0]);
02985     }
02986     else
02987 #endif
02988     {
02989         /* Ok to return here, nothing alloc'ed */
02990         return scdrd('I', id, descr, felem, maxvals, actvals, values, unit, null);
02991     }
02992 
02993 /*  cleanup: */
02994     uves_free_string(&char_values);
02995     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
02996 }
02997 
02998 /*----------------------------------------------------------------------------*/
03004 /*----------------------------------------------------------------------------*/
03005 int flames_midas_scdrdd(int id, const char *descr, 
03006             int felem, int maxvals,
03007             int *actvals, double *values,
03008             int *unit, int *null)
03009 {
03010     return scdrd('D', id, descr, felem, maxvals, actvals, values, unit, null);
03011 }
03012 
03013 /*----------------------------------------------------------------------------*/
03019 /*----------------------------------------------------------------------------*/
03020 int flames_midas_scdrdr(int id, const char *descr, 
03021             int felem, int maxvals,
03022             int *actvals, float *values,
03023             int *unit, int *null)
03024 {
03025     if (strcmp("LHCUTS", descr) == 0 && felem < 3)
03026     {
03027             int i;
03028             bool success = true;
03029             
03030             for (i = felem; i < felem+maxvals; i++)
03031                 {
03032                     double val;
03033                     if (1 <= i && i <= 2)
03034                         {
03035                             uves_msg_debug("Do not read LHCUTS%d", i);
03036                         }
03037                     else if (i == 3)
03038                         {
03039                             success = success &&
03040                                 (flames_midas_scdrdd(id, "DATAMIN", i, 1,
03041                                                      actvals,
03042                                                      &val,
03043                                                      unit, null)) == 0;
03044 
03045                             values[i-felem] = (float) val;
03046                         }
03047                     else if (i == 4)
03048                         {
03049                             success = success &&
03050                                 (flames_midas_scdrdd(id, "DATAMAX", i, 1,
03051                                                      actvals,
03052                                                      &val,
03053                                                      unit, null)) == 0;
03054                             values[i-felem] = (float) val;
03055                         }
03056                     else
03057                         {
03058                             success = false;
03059                         }
03060                 }
03061             return success ? 0 : 1;
03062     }
03063     else
03064     {
03065             return scdrd('R', id, descr, felem, maxvals, actvals, values, unit, null);
03066     }
03067 }
03068 
03069 /*----------------------------------------------------------------------------*/
03079 /*----------------------------------------------------------------------------*/
03080 int flames_midas_scdrdc(int id, const char *descr, 
03081             int noelem,
03082             int felem, int maxvals,
03083             int *actvals, char *values,
03084             int *unit, int *null)
03085 {
03086     int returnvalue = 1;
03087     
03088     assure( noelem == sizeof(char), CPL_ERROR_UNSUPPORTED_MODE, "Implement me" );
03089     assure( felem  == 1, CPL_ERROR_UNSUPPORTED_MODE, "Implement me" );
03090    
03091     returnvalue = scdrd('C', id, descr, felem, maxvals, actvals, values, unit, null);
03092     
03093   cleanup:
03094     return returnvalue;    
03095 }
03096 
03097 
03098 
03099 /*----------------------------------------------------------------------------*/
03117 /*----------------------------------------------------------------------------*/
03118 static int
03119 scdwr(char type_to_write, int id, const char *descr, const void *values, 
03120       int felem, int nval, const int *unit)
03121 {
03122     char type = '-';
03123     int length, bytelem, i;
03124     cpl_property **cards = NULL;
03125     cpl_property **cards_extra = NULL;
03126 
03127 
03128     passure( invariant(id), " ");
03129 
03130     assure( frame_is_open(id), CPL_ERROR_ILLEGAL_INPUT,
03131         "Frame no. %d is not open", id);
03132 
03133     check( cards = get_descr_info(id, descr, 
03134                                   &type, &length, &bytelem),
03135        "Could not get info on descriptor %s", descr);
03136     
03137     if (cards == NULL) {
03138         int number_of_cards = (type_to_write == 'C') ? 1 : (felem-1)+nval;
03139         int nexisting = 0;
03140         
03141         type = type_to_write;
03142         check( cards = create_descr(frames[id].header, descr, type,
03143                                     number_of_cards, nexisting),
03144                "Could not create %d %s descriptors",
03145                number_of_cards, descr);
03146     }
03147     else {
03148         assure( type == type_to_write ||
03149                 (type == 'D' && type_to_write == 'R'),
03150                 CPL_ERROR_TYPE_MISMATCH,
03151                 "Cannot write type %c data to type %c descriptor %s",
03152                 type_to_write, type, descr);
03153         
03154         if (type_to_write != 'C' &&
03155             (felem-1) + nval > length)
03156             /* Create additional descriptors */
03157             {
03158                 int number_of_extra = (felem-1) + nval - length;
03159                 int ncards;
03160                 
03161                 /* Count existing descriptors */
03162                 ncards = 0;
03163                 while(cards[ncards] != NULL) ncards++;
03164                 
03165                 uves_msg_debug("Only %d existing %s descriptor(s), add another %d",
03166                                ncards, descr, number_of_extra);
03167                 
03168                 check( cards_extra
03169                        = create_descr(frames[id].header, descr, type,
03170                                       number_of_extra, ncards),
03171                        "Could not create %d %s descriptors",
03172                        number_of_extra, descr);
03173                 
03174                 /* Append to existing */
03175                 cards = cpl_realloc(cards, (ncards + number_of_extra + 1)*sizeof(cpl_property *));
03176                 
03177                 for (i = ncards; i < ncards + number_of_extra; i++)
03178                     {
03179                         cards[i] = cards_extra[i-ncards];
03180                     }
03181                 
03182                 cards[ncards+number_of_extra] = NULL;
03183             }
03184         else {
03185             uves_msg_debug("Do not add new cards for descriptor %s", descr);
03186         }
03187     }
03188 
03189     /* Properties now exist in correct number, with correct type */
03190     for (i = 0; i < ((type_to_write == 'C') ? 1 : nval); i++) {
03191         if (type_to_write == 'I') {
03192             uves_msg_debug("Writing %d. of %d values (%d) to cards[%d]",
03193                            i+1,
03194                            ((type_to_write == 'C') ? 1 : nval),
03195                            ((const int *)values)[i],
03196                            (felem-1) + i);
03197         }
03198         else {
03199             uves_msg_debug("Writing %d. of %d values to cards[%d]", 
03200                            i+1,
03201                            ((type_to_write == 'C') ? 1 : nval),
03202                            (felem-1) + i);
03203         }
03204         
03205         /* Allow conversion float -> double */
03206         switch(type_to_write) {
03207         case 'I': cpl_property_set_int (cards[(felem-1) + i], ((const int *)values)[i]); break;
03208         case 'R': 
03209             switch(type) {
03210             case 'R':
03211                 cpl_property_set_float (cards[(felem-1) + i], ((const float *)values)[i]); break;
03212             case 'D':
03213                 cpl_property_set_double(cards[(felem-1) + i], ((const float *)values)[i]); break;
03214             default:
03215                 assure( false, CPL_ERROR_UNSUPPORTED_MODE,
03216                         "Cannot write type '%c' values to type '%c' descriptor",
03217                         type_to_write, type);
03218                 break;
03219             }
03220             break;
03221         case 'C': cpl_property_set_string(cards[(felem-1) + i], (const char *)values); break;
03222         case 'D': cpl_property_set_double(cards[(felem-1) + i], ((const double *)values)[i]); break;
03223         default: 
03224             assure( false,CPL_ERROR_UNSUPPORTED_MODE, "Implement me"); break;
03225         }
03226 
03227     }
03228     
03229     /* unit not implemented by MIDAS */
03230     
03231     frames[id].need_to_save = true;
03232     /* and in order to be able to save the header with CPL,
03233        we need to also have the image in memory (if not already) */
03234     check( load_frame(id),
03235            "Could not load frame %s", frames[id].filename );
03236 
03237     passure( invariant(id), " ");
03238 
03239   cleanup:
03240     cpl_free(cards); cards = NULL;
03241     cpl_free(cards_extra); cards_extra = NULL;
03242     
03243     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03244 }
03245 
03246 /*----------------------------------------------------------------------------*/
03252 /*----------------------------------------------------------------------------*/
03253 int flames_midas_scdwri(int id, const char *descr, const int *values, 
03254             int felem, int nval, const int *unit)
03255 {
03256     if (strcmp(descr, "NPIX") == 0)
03257     /* MIDAS  NPIXi maps to FITS NAXISi */
03258     {
03259         cpl_type type;
03260         int *buffer_int=NULL;
03261         float *buffer_float=NULL;
03262         double *buffer_double=NULL;
03263         int size=0;
03264         
03265         assure( nval == 1 || nval == 2 || nval == 3 || nval == 4, 
03266                 CPL_ERROR_UNSUPPORTED_MODE,
03267                 "Only 2d, 3d and 4d (not %dd) images supported", 
03268                 nval);
03269         
03270         assure( frames[id].is_image, CPL_ERROR_ILLEGAL_INPUT,
03271                 "Cannot write NPIX to table %s", frames[id].filename);
03272         
03273         switch(nval) {
03274         case 1: size = values[0]; break;
03275         case 2: size = values[0] * values[1]; break;
03276         case 3: size = values[0] * values[1] * values[2]; break;
03277             case 4: size = values[0] * values[1] * values[2] * values[3]; break;
03278         default:
03279             passure( false, "Impossible");
03280             break;
03281         }
03282 
03283         if (frames[id].data.image.image == NULL) {
03284             frames[id].data.image.image = 
03285                 cpl_image_new(size, 1, 
03286                               frames[id].data.image.type);
03287         }
03288         
03289         assure( size == 
03290                 cpl_image_get_size_x(frames[id].data.image.image) *
03291                 cpl_image_get_size_y(frames[id].data.image.image), 
03292                 CPL_ERROR_INCOMPATIBLE_INPUT,
03293                 "Cannot set image %s NAXIS to %d because the "
03294                 "image memory buffer size is %" CPL_SIZE_FORMAT "",
03295                 frames[id].filename, 
03296                 size,
03297                 cpl_image_get_size_x(frames[id].data.image.image) *
03298                 cpl_image_get_size_y(frames[id].data.image.image));
03299         
03300         /* Now unwrap + wrap the image structure, but keep
03301            the buffer unchanged */
03302         type = cpl_image_get_type(frames[id].data.image.image);
03303         if (nval == 2) {
03304             /* This is redundant now that NAXIS is overwritten when closing */
03305             uves_msg_debug("Setting image %s (type %s) size to %dx%d",
03306                            frames[id].filename,
03307                            uves_tostring_cpl_type(type),
03308                            values[0], values[1]);
03309             switch(type) {
03310             case CPL_TYPE_INT   : buffer_int    = cpl_image_get_data_int(frames[id].data.image.image); break;
03311             case CPL_TYPE_FLOAT : buffer_float  = cpl_image_get_data_float(frames[id].data.image.image); break;
03312             case CPL_TYPE_DOUBLE: buffer_double = cpl_image_get_data_double(frames[id].data.image.image); break;
03313             default:
03314                 assure( false, CPL_ERROR_INVALID_TYPE, "Type is %s",
03315                         uves_tostring_cpl_type(type));
03316                 break;
03317             }
03318 
03319                 
03320             /* Deallocate, except buffer */
03321             cpl_image_unwrap(frames[id].data.image.image);
03322                 
03323             switch(type) {
03324             case CPL_TYPE_INT   : frames[id].data.image.image = cpl_image_wrap_int   (values[0], values[1], buffer_int); break;
03325             case CPL_TYPE_FLOAT : frames[id].data.image.image = cpl_image_wrap_float (values[0], values[1], buffer_float); break;
03326             case CPL_TYPE_DOUBLE: frames[id].data.image.image = cpl_image_wrap_double(values[0], values[1], buffer_double); break;
03327             default:
03328                 assure( false, CPL_ERROR_INVALID_TYPE, "Type is %s",
03329                         uves_tostring_cpl_type(type));
03330                 break;
03331             }
03332 
03333         }
03334         else {
03335             /* for 3d, 4d images don't change the CPL
03336                image axes. NAXISi will be overwritten when saving */
03337         }
03338     }
03339     
03340     scdwr('I', id, descr, values, felem, nval, unit);
03341     
03342   cleanup:
03343     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03344 }
03345 
03346 /*----------------------------------------------------------------------------*/
03352 /*----------------------------------------------------------------------------*/
03353 int flames_midas_scdwrd(int id, const char *descr, const double *values, 
03354                         int felem, int nval, const int *unit)
03355 {
03356     if (strcmp("CRPIX", descr) == 0 ||
03357         strcmp("CRVAL", descr) == 0 ||
03358         strcmp("CDELT", descr) == 0) {
03359         int i;
03360         bool success = true;
03361         
03362         for (i = felem; i < felem+nval; i++) {
03363             char descr_i[10];
03364             
03365             sprintf(descr_i, "%s%i", descr, i);
03366             success = success &&
03367                 (flames_midas_scdwrd(id, descr_i, &values[i-felem], 
03368                                      felem, 1, unit) == 0);
03369         }
03370 
03371         return success ? 0 : 1;
03372     }
03373     
03374     return scdwr('D', id, descr, values, felem, nval, unit);
03375 }
03376 
03377 /*----------------------------------------------------------------------------*/
03383 /*----------------------------------------------------------------------------*/
03384 int flames_midas_scdwrr(int id, const char *descr, const float *values, 
03385                         int felem, int nval, const int *unit)
03386 {
03387     if (strcmp("LHCUTS", descr) == 0 && felem < 3) {
03388         int i;
03389         bool success = true;
03390             
03391         for (i = felem; i < felem+nval; i++)
03392             {
03393                 if (1 <= i && i <= 2)
03394                     {
03395                         uves_msg_debug("Do not write LHCUTS%d", i);
03396                     }
03397                 else if (i == 3)
03398                     {
03399                         double val = (double) values[i-felem-1];
03400                         success = success &&
03401                             (flames_midas_scdwrd(id, "DATAMIN", &val, 
03402                                                  1, 1, unit) == 0);
03403                     }
03404                 else if (i == 4)
03405                     {
03406                         double val = (double) values[i-felem-1];
03407                         success = success &&
03408                             (flames_midas_scdwrd(id, "DATAMAX", &val,
03409                                                  1, 1, unit) == 0);
03410                     }
03411                 else
03412                     {
03413                         success = false;
03414                     }
03415             }
03416         return success ? 0 : 1;
03417     }
03418     else
03419     {
03420         return scdwr('R', id, descr, values, felem, nval, unit);
03421     }
03422 }
03423 
03424 /*----------------------------------------------------------------------------*/
03434 /*----------------------------------------------------------------------------*/
03435 int flames_midas_scdwrc(int id, const char *descr, int noelm, const char *values, 
03436                         int felem, int nval, const int *unit)
03437 {
03438     int returnvalue = 1;
03439     char* tmp_string=NULL;
03440 
03441     if (strcmp(descr, "CUNIT") == 0) {
03442         if (noelm == 1) {
03443             char val[17];
03444             int i;
03445 
03446             assure( nval % 16 == 0, CPL_ERROR_UNSUPPORTED_MODE,
03447                     "nval = %d", nval );
03448             /* nval used in FLAMES code are 32, 48, 64 and 80 */
03449 
03450 
03451             strncpy(val, values, 16);
03452             val[16] = '\0';
03453             returnvalue = flames_midas_scdwrc(id, "BUNIT", 1, val, felem, 16, unit);
03454             
03455             for (i = 1; i < nval/16; i++) {
03456                 const char *ctype_i;
03457                 
03458                 switch(i) {
03459                 case 1: ctype_i = "CTYPE1"; break;
03460                 case 2: ctype_i = "CTYPE2"; break;
03461                 case 3: ctype_i = "CTYPE3"; break;
03462                 case 4: ctype_i = "CTYPE4"; break;
03463                 default:
03464                     return 1;
03465                     break;
03466                 }
03467                 
03468                 strncpy(val, values+i*16, 16);
03469                 val[16] = '\0';
03470                 
03471                 if (returnvalue == 0) {
03472                     returnvalue = flames_midas_scdwrc(id, ctype_i, 1, val, felem, 16, unit);
03473                 }
03474             }
03475         }
03476         else {
03477             /* The FLAMES C code has only one call like this.
03478                Implement it by 3 manual calls.
03479             */
03480             assure( nval == 3, CPL_ERROR_UNSUPPORTED_MODE,
03481                     "noelm = %d, nval = %d", noelm, nval);
03482             
03483             /* Yes, here noelm and nval are swapped */
03484             returnvalue = flames_midas_scdwrc(id, "BUNIT",  1, values+0, felem, noelm, unit);
03485             if (returnvalue == 0) {
03486                 returnvalue = flames_midas_scdwrc(id, "CTYPE1", 1, values+1, felem, noelm, unit);
03487             }
03488             if (returnvalue == 0) {
03489                 returnvalue = flames_midas_scdwrc(id, "CTYPE2", 1, values+2, felem, noelm, unit);
03490             }
03491         }
03492     }
03493     else {
03494         assure( noelm == sizeof(char), CPL_ERROR_UNSUPPORTED_MODE, "Implement me" );
03495         assure( felem == 1, CPL_ERROR_UNSUPPORTED_MODE, "Implement me" );
03496         
03497         /* nval is the string length */
03498         tmp_string=cpl_calloc((nval+1),sizeof(char));
03499         strncpy(tmp_string,values,nval);    
03500         returnvalue = scdwr('C', id, descr, tmp_string, felem, nval, unit);
03501         
03502     }
03503     
03504   cleanup:
03505     cpl_free(tmp_string);
03506     return returnvalue;    
03507 }
03508 
03509 /*----------------------------------------------------------------------------*/
03516 /*----------------------------------------------------------------------------*/
03517 int flames_midas_scddel(int id, const char *descr)
03518 {
03519     cpl_property **cards = NULL;
03520     char type;
03521     int length, bytelem;
03522     const char *fits_descr = NULL;
03523     const char *name_regexp = NULL;
03524 
03525     passure( invariant(id), " ");
03526 
03527     assure( frame_is_open(id), CPL_ERROR_ILLEGAL_INPUT,
03528         "Frame no. %d is not open", id );
03529 
03530     /* Need to convert from MIDAS names to CPL propertylist names */
03531     check( cards = get_descr_info(id, descr, &type,
03532                                   &length, &bytelem),
03533        "Could not get info on descriptor %s", descr);
03534 
03535     if (cards != NULL)
03536         {
03537             int i;
03538             
03539             frames[id].need_to_save = true;
03540 
03541             for (i = 1; i <= length; i++)
03542                 {
03543                     int invert = 0;
03544                     uves_free_string_const(&fits_descr);        
03545                     check( fits_descr = convert_to_fits(descr, i),
03546                            "Could not convert %s to FITS", descr);
03547 
03548                     /* uves_propertylist_erase() will  erase only the first
03549                        property with the given name. We want to erase all matches
03550                     */
03551 
03552                     uves_free_string_const(&fits_descr);        
03553                     name_regexp = uves_sprintf("^%s$", fits_descr);
03554                     uves_propertylist_erase_regexp(frames[id].header, name_regexp, invert);
03555                 }
03556     }
03557 
03558     passure( invariant(id), " ");
03559 
03560   cleanup:
03561     uves_free_string_const(&fits_descr);        
03562     uves_free_string_const(&name_regexp);
03563     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03564 }
03565 
03566 /*----------------------------------------------------------------------------*/
03587 /*----------------------------------------------------------------------------*/
03588 
03589 static int scdcop(int from, int to, int mask, bool copy_naxis)
03590 {
03591     const char *key = NULL;
03592     passure( invariant(from), " ");
03593     passure( invariant(to  ), " ");
03594 
03595     assure( frame_is_open(from), CPL_ERROR_ILLEGAL_INPUT,
03596             "Image no. %d is not open", from);
03597     
03598     assure( frame_is_open(to), CPL_ERROR_ILLEGAL_INPUT,
03599             "Image no. %d is not open", to);
03600     
03601     check( load_frame_header(from),
03602        "Could not load header of file %s", frames[from].filename);
03603 
03604     check( load_frame_header(to),
03605        "Could not load header of file %s", frames[to].filename);
03606 
03607     switch (mask) {
03608     case 1:
03609         /* copy all */
03610         if (0)
03611             {
03612                 /* This would just append */
03613                 uves_propertylist_append(frames[to].header, frames[from].header);
03614             }
03615         else
03616             {
03617                 /* overwrites existing descriptors */
03618                 if (copy_naxis) {
03619                     uves_propertylist_copy_property_regexp(frames[to].header, 
03620                                                            frames[from].header,
03621                                                            ".*", 0);
03622                 }
03623                 else {
03624                     uves_propertylist_copy_property_regexp(frames[to].header, 
03625                                                            frames[from].header,
03626                                                            "^NAXIS", 1);
03627                 }
03628             }
03629         uves_msg_debug("%s header now contains %ld descriptors",
03630                        frames[to].filename, uves_propertylist_get_size(frames[to].header));
03631         
03632         break;
03633     case 3:
03634         assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me");     
03635         break;
03636     default:
03637         /* Not needed for FLAMES code */
03638         assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me");
03639     }
03640 
03641     /* Need to change size of image */
03642     if (frames[from].is_image && copy_naxis) {
03643         int naxis = uves_propertylist_get_int(frames[from].header, "NAXIS");
03644         int axis;
03645         int unit;
03646         int n[2];
03647 
03648         uves_msg_debug("Manually propagating NPIX");
03649 
03650         assure( naxis == 2, CPL_ERROR_UNSUPPORTED_MODE,
03651                 "NAXIS = %d", naxis );
03652 
03653         for (axis = 1; axis <= naxis; axis++) {
03654             uves_free_string_const(&key);
03655             key = uves_sprintf("NAXIS%d", axis);
03656             n[axis-1] = uves_propertylist_get_int(frames[from].header, key);
03657         }
03658 
03659         check_nomsg( flames_midas_scdwri(to, "NPIX", n,
03660                                          1, 2, &unit));
03661     }
03662     
03663     frames[to].need_to_save = true;
03664     check( load_frame(to),
03665        "Could not load image %s", frames[to].filename);
03666 
03667     passure( invariant(from), " ");
03668     passure( invariant(to  ), " ");
03669 
03670   cleanup:
03671     uves_free_string_const(&key);
03672     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03673 }
03674 
03675 /*----------------------------------------------------------------------------*/
03682 /*----------------------------------------------------------------------------*/
03683 int flames_midas_scdcop(int from, int to, int mask)
03684 {
03685     return scdcop(from, to, mask, true);
03686 }
03687 
03688 /*----------------------------------------------------------------------------*/
03695 /*----------------------------------------------------------------------------*/
03696 int flames_midas_scdcop_nonaxis(int from, int to, int mask)
03697 {
03698     return scdcop(from, to, mask, false);
03699 }
03700 
03701 /*----------------------------------------------------------------------------*/
03712 /*----------------------------------------------------------------------------*/
03713 int flames_midas_sccsho(const cpl_frameset *catfile,
03714                         int *noent, 
03715                         int *last)
03716 {
03717     *last=*last; //to remove compilation warning: this is not used
03718     assure_nomsg( catfile != NULL, CPL_ERROR_NULL_INPUT );
03719     assure_nomsg( noent != NULL, CPL_ERROR_NULL_INPUT );
03720 
03721     *noent = cpl_frameset_get_size(catfile);
03722 
03723     //fixme: is 'last' used by any caller? If so, how is it different from 'noent'?
03724     
03725   cleanup:
03726     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03727 }
03728 
03729 
03730 /*----------------------------------------------------------------------------*/
03738 /*----------------------------------------------------------------------------*/
03739 int flames_midas_sccfnd(const cpl_frameset *catfile, 
03740                         int frmno, 
03741                         char *frame)
03742 {
03743     const cpl_frame *f;
03744     
03745     assure_nomsg( catfile != NULL, CPL_ERROR_NULL_INPUT );
03746     assure_nomsg( frame != NULL, CPL_ERROR_NULL_INPUT );
03747     frame[0] = '\0';
03748 
03749     check( f = cpl_frameset_get_frame_const(catfile, frmno-1), /* CPL counts from zero */
03750            "Could not get frame no. %d from catalog", frmno);
03751 
03752     strcpy(frame, cpl_frame_get_filename(f));
03753 
03754     uves_msg_debug("Returning frame %s", cpl_frame_get_filename(f));
03755 
03756   cleanup:
03757     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03758 }
03759 /*----------------------------------------------------------------------------*/
03776 /*----------------------------------------------------------------------------*/
03777 int flames_midas_sccget(const cpl_frameset *catfile,
03778                         int flag,
03779                         char *name, char *ident, 
03780                         int *no)
03781 {
03782     const char *fits_descr = NULL;
03783     uves_propertylist *header = NULL;
03784     
03785     assure_nomsg( catfile != NULL, CPL_ERROR_NULL_INPUT );
03786     assure_nomsg( no      != NULL, CPL_ERROR_NULL_INPUT );
03787     assure_nomsg( name    != NULL, CPL_ERROR_NULL_INPUT );
03788     assure_nomsg( flag == 0 || ident != NULL, CPL_ERROR_NULL_INPUT );
03789 
03790     if (*no == cpl_frameset_get_size(catfile))
03791         {
03792             *name = ' ';
03793             *no += 1;
03794 
03795             uves_msg_debug("Returning frame ' '");
03796         }
03797     else
03798         {
03799             const cpl_frame *f;
03800             check( f = cpl_frameset_get_frame_const(catfile, *no),
03801                    "Could not get frame no. %d from catalog", *no);
03802             
03803             *no += 1;
03804             strcpy(name, cpl_frame_get_filename(f));
03805 
03806             if (flag != 0) {
03807                 const char *ident_value;
03808                 
03809                 check( header = uves_propertylist_load(name, 0),
03810                        "Failed to load %s header", name);
03811 
03812                 if (false) {
03813                     check_nomsg( fits_descr = convert_to_fits(ident, 1) );
03814                 }
03815                 else {
03816                     fits_descr = uves_sprintf("%s", "OBJECT");
03817                 }
03818 
03819                 if (uves_propertylist_contains(header, fits_descr)) {
03820                     check_nomsg( ident_value = 
03821                                  uves_propertylist_get_string(header, fits_descr));
03822                 }
03823                 else {
03824                     ident_value = " ";
03825                 }
03826                 
03827 
03828                 /* Unsafe by design of this function */
03829                 strcpy(ident, ident_value);
03830 
03831                 /* Pad with blanks until strlen = 40 */
03832                 {
03833                     int i;
03834                     i = strlen(ident);
03835                     while (i <= 39) {
03836                         ident[i] = ' ';
03837                         i++;
03838                     }
03839                     ident[i] = '\0';
03840                 }
03841                 
03842                 uves_msg_debug("Returning ident '%s'", ident);
03843 
03844                 /* previously 
03845                    strcpy(ident, cpl_frame_get_tag(f));
03846                 */
03847                }
03848 
03849             uves_msg_debug("Returning frame %s", name);
03850         }
03851     
03852 
03853   cleanup: 
03854     uves_free_propertylist(&header);
03855     uves_free_string_const(&fits_descr);
03856 
03857     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03858 }
03859 
03860 /*----------------------------------------------------------------------------*/
03873 /*----------------------------------------------------------------------------*/
03874 int flames_midas_scccre(cpl_frameset **catfile, 
03875                         int type,
03876                         int flag)
03877 {
03878     assure_nomsg( catfile != NULL, CPL_ERROR_NULL_INPUT );
03879 
03880     /* These parameters always have these values in the FLAMES code */
03881     assure( type == F_IMA_TYPE, CPL_ERROR_UNSUPPORTED_MODE,
03882             "Implement me");
03883     assure(flag == 0, CPL_ERROR_UNSUPPORTED_MODE,
03884            "Implement me");
03885 
03886     *catfile = cpl_frameset_new();
03887 
03888   cleanup: 
03889     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03890 }
03891 
03892 /*----------------------------------------------------------------------------*/
03905 /*----------------------------------------------------------------------------*/
03906 int flames_midas_sccadd(cpl_frameset *catfile,
03907             const char *name,
03908             const char *ident)
03909 {
03910   //const char *fits_descr = NULL;
03911     cpl_frame* frame = NULL;
03912     //uves_propertylist *header = NULL;
03913 
03914     assure_nomsg( catfile != NULL, CPL_ERROR_NULL_INPUT );
03915     assure_nomsg( name    != NULL, CPL_ERROR_NULL_INPUT );
03916     assure_nomsg( ident   != NULL, CPL_ERROR_NULL_INPUT );
03917 
03918     frame = cpl_frame_new();
03919     cpl_frame_set_filename(frame, name);
03920     cpl_frame_set_tag(frame, "dummy"); /* need for cpl_frameset_insert() */
03921     cpl_frameset_insert(catfile, frame);
03922 
03923     /* In principle, we should here update the 
03924        OBJECT fits card with the provided ident string.
03925        However this ident string is always a blank. 
03926        Therefore do not update OBJECT which is very difficult to do with CPL */
03927 
03928     {
03929         int i = 0;
03930         while(ident[i] != '\0') {
03931             assure( ident[i] == ' ', CPL_ERROR_UNSUPPORTED_MODE,
03932                     "Blank ident string expected. Received '%s'",
03933                     ident);
03934             i++;
03935         }
03936     }
03937 
03938     /* previously
03939        cpl_frame_set_tag(frame, ident);
03940     */
03941 
03942   cleanup: 
03943     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
03944 }
03945 
03946 /*----------------------------------------------------------------------------*/
03952 /*----------------------------------------------------------------------------*/
03953 static cpl_type
03954 table_dtype_to_cpltype(int dtype, int alen)
03955 {
03956     cpl_type type = CPL_TYPE_INVALID;
03957 
03958     /* Only these combinations are used in FLAMES code */
03959     assure( dtype == D_I4_FORMAT ||
03960             dtype == D_R8_FORMAT ||
03961             dtype == D_R4_FORMAT ||
03962             dtype == D_C_FORMAT, CPL_ERROR_UNSUPPORTED_MODE,
03963             "dtype = %d", dtype);
03964     
03965     assure( dtype == D_C_FORMAT || alen == 1, CPL_ERROR_UNSUPPORTED_MODE,
03966             "dtype = %d, alen = %d", dtype, alen);
03967     
03968     switch(dtype) {
03969     case D_I4_FORMAT: type = CPL_TYPE_INT; break;
03970     case D_R4_FORMAT: type = CPL_TYPE_FLOAT; break;
03971     case D_R8_FORMAT: type = CPL_TYPE_DOUBLE; break;
03972     case D_C_FORMAT: type = CPL_TYPE_STRING; break;
03973     default:
03974         /* impossible */
03975         passure( false, " ");
03976         break;
03977     }    
03978 
03979   cleanup:
03980     return type;
03981 }
03982 
03983 /*----------------------------------------------------------------------------*/
03989 /*----------------------------------------------------------------------------*/
03990 static int
03991 sizeof_cpltype(cpl_type type)
03992 {
03993     switch(type) {
03994         /* These correspondences are documented in CPL */
03995     case CPL_TYPE_INT:    return sizeof(int); break;
03996     case CPL_TYPE_FLOAT:  return sizeof(float); break;
03997     case CPL_TYPE_DOUBLE: return sizeof(double); break;
03998     case CPL_TYPE_STRING: return sizeof(char); break;
03999     default:
04000         assure( false, CPL_ERROR_UNSUPPORTED_MODE,
04001                 "Cannot convert CPL type %s", uves_tostring_cpl_type(type));
04002         break;
04003     }
04004 
04005   cleanup:
04006     return 0;
04007 }
04008 
04009 /*----------------------------------------------------------------------------*/
04015 /*----------------------------------------------------------------------------*/
04016 static int
04017 table_cpltype_to_dtype(cpl_type type)
04018 {
04019     int dtype = -1;
04020     
04021     switch(type) {
04022     case CPL_TYPE_INT:    dtype = D_I4_FORMAT; break;
04023     case CPL_TYPE_FLOAT:  dtype = D_R4_FORMAT; break;
04024     case CPL_TYPE_DOUBLE: dtype = D_R8_FORMAT; break;
04025     case CPL_TYPE_STRING: dtype = D_C_FORMAT; break;
04026     default:
04027         assure( false, CPL_ERROR_UNSUPPORTED_MODE,
04028                 "Cannot convert CPL type %s", uves_tostring_cpl_type(type));
04029         break;
04030     }
04031 
04032   cleanup:
04033     return dtype;
04034 }
04035 
04036 /*----------------------------------------------------------------------------*/
04043 /*----------------------------------------------------------------------------*/
04044 static const char *
04045 table_colname_from_number(int tid, int column)
04046 {
04047     const char *name = NULL;
04048 
04049     passure( invariant(tid), " ");
04050     
04051     assure( frame_is_open(tid) && !frames[tid].is_image, CPL_ERROR_ILLEGAL_INPUT,
04052         "Table %d is not open", tid);
04053     
04054     check( load_frame(tid), "Could not load table %s", frames[tid].filename);
04055 
04056     assure( 1 <= column && column <= cpl_table_get_nrow(frames[tid].data.table.colnames),
04057             CPL_ERROR_ACCESS_OUT_OF_RANGE,
04058             "Illegal column number %d. Table has %" CPL_SIZE_FORMAT " row(s)",
04059             column, cpl_table_get_nrow(frames[tid].data.table.colnames));
04060 
04061     name = cpl_table_get_string(frames[tid].data.table.colnames, COLNAME,
04062                                 column - 1);
04063 
04064   cleanup:
04065     return name;
04066 }
04067 
04068 /*----------------------------------------------------------------------------*/
04082 /*----------------------------------------------------------------------------*/
04083 int flames_midas_tctopn(const char *name, int mode, int allrow, int *tid)
04084 {
04085     assure( allrow == -1 || mode == F_O_MODE, CPL_ERROR_INCOMPATIBLE_INPUT,
04086             "allrow = %d, mode = %d", allrow, mode);
04087 
04088     if (mode == F_I_MODE || mode == F_IO_MODE || mode == F_O_MODE)
04089     {
04090         /* Find first open slot */
04091         int i;
04092         bool found = false;
04093         for (i = 0; !found && i < MAX_OPEN; i++)
04094         {
04095             if (! frame_is_open(i))
04096             {
04097                 found = true;
04098                 *tid = i;
04099 
04100                 if (mode == F_I_MODE || mode == F_IO_MODE)   /* Input */
04101                     {
04102                         frame_new_table(i, name, NULL, false,
04103                                         NULL, 0, NULL);
04104                     }
04105                 else if (mode == F_O_MODE)   /* Output */
04106                     {
04107                         cpl_table *colnames = cpl_table_new(0);
04108                         cpl_table_new_column(colnames,
04109                                              COLNAME, CPL_TYPE_STRING);
04110                         
04111                         frame_new_table(i, name, uves_propertylist_new(), true,
04112                                         cpl_table_new(allrow), 0, colnames);
04113                         
04114                     }
04115                 
04116                 uves_msg_debug("Opened table no. %d: %s",
04117                        i, name);
04118             }
04119         }
04120         
04121         assure( found, CPL_ERROR_UNSUPPORTED_MODE,
04122             "Cannot open more than %d table files",
04123             MAX_OPEN);
04124     }
04125     else
04126     {
04127         assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me");
04128     }
04129 
04130     passure( invariant(*tid), " ");
04131 
04132   cleanup:
04133     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04134 }
04135 
04136 /*----------------------------------------------------------------------------*/
04143 /*----------------------------------------------------------------------------*/
04144 int flames_midas_tctclo(int tid)
04145 {
04146     return frame_close(tid);
04147 }
04148 
04149 /*----------------------------------------------------------------------------*/
04163 /*----------------------------------------------------------------------------*/
04164 int flames_midas_tccser(int tid, const char *colref, int *column)
04165 {
04166     bool found;
04167     int i;
04168 
04169     passure( invariant(tid), " ");
04170 
04171     /* The MIDAS interface supports the following, but there is no reason
04172        to do that for the FLAMES code */
04173     assure( colref[0] != ':' &&
04174             colref[0] != '#', CPL_ERROR_UNSUPPORTED_MODE, "Illegal column name: %s",
04175             colref);
04176 
04177     assure( frame_is_open(tid) && !frames[tid].is_image, CPL_ERROR_ILLEGAL_INPUT,
04178         "Table %d is not open", tid);
04179 
04180     check( load_frame(tid), "Could not load table %s", frames[tid].filename);
04181 
04182     *column = -1;
04183     found = false;
04184     for (i = 0; i < cpl_table_get_nrow(frames[tid].data.table.colnames) && !found; i++)
04185         {
04186             const char *name = cpl_table_get_string(frames[tid].data.table.colnames, COLNAME, i);
04187             if (strcmp(name, colref) == 0)
04188                 {
04189                     *column = i + 1; /* counting from 1 */
04190                     found = true;
04191                 }
04192     }
04193 
04194     if (!found) 
04195         {
04196             uves_msg_warning("Table %s has no column %s",
04197                              frames[tid].filename, colref);
04198         }
04199 
04200     passure( invariant(tid), " ");
04201 
04202   cleanup:
04203     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04204 }
04205 
04206 /*----------------------------------------------------------------------------*/
04215 /*----------------------------------------------------------------------------*/
04216 int flames_midas_tciget(int tid, int *column, int *row)
04217 {
04218   //const char *name;
04219 
04220     passure( invariant(tid), " ");
04221 
04222     assure( frame_is_open(tid) && !frames[tid].is_image, CPL_ERROR_ILLEGAL_INPUT,
04223         "Table %d is not open", tid);
04224 
04225     check( load_frame(tid), "Could not load table %s", frames[tid].filename);
04226 
04227     *column = cpl_table_get_ncol(frames[tid].data.table.table) - 1;
04228     /* Return actual number of rows, not allocated */
04229     //*row    = cpl_table_get_nrow(frames[tid].data.table.table);
04230     *row    = frames[tid].data.table.maxrow;
04231 
04232     passure( invariant(tid), " ");
04233 
04234   cleanup:
04235     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04236 }
04237 
04238 /*----------------------------------------------------------------------------*/
04251 /*----------------------------------------------------------------------------*/
04252 int flames_midas_tcbget(int tid, int column, int *dtype, int *items, int *bytes)
04253 {
04254     const char *colname;
04255 
04256     check_nomsg( colname = table_colname_from_number(tid, column) );
04257 
04258     check_nomsg( *dtype = table_cpltype_to_dtype(
04259                      cpl_table_get_column_type(frames[tid].data.table.table, 
04260                                                colname)) );
04261 
04262     /* Note! 
04263        This function is only used in flames_create_full_ordertable.c,
04264        so it only has to work in that case.
04265     */
04266 
04267     *items = 1;
04268 
04269     if (*dtype == D_C_FORMAT) 
04270         {
04271             *bytes = 80 * sizeof_cpltype(
04272                 table_dtype_to_cpltype(*dtype, *items) );
04273         }
04274     else 
04275         {
04276             *bytes = (*items) * sizeof_cpltype(
04277                 table_dtype_to_cpltype(*dtype, *items) );
04278         }
04279 
04280   cleanup:
04281     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04282 }
04283 
04284 /*----------------------------------------------------------------------------*/
04291 /*----------------------------------------------------------------------------*/
04292 int flames_midas_tcdget(int tid, int *store)
04293 {
04294     tid=tid; //to remove compilation warning: this is not used
04295     *store=*store; //to remove compilation warning: this is not used
04296     assure( false, CPL_ERROR_UNSUPPORTED_MODE, "Implement me");
04297   cleanup: return 1;
04298 }
04299 
04300 /*----------------------------------------------------------------------------*/
04309 /*----------------------------------------------------------------------------*/
04310 int flames_midas_tcfget(int tid, int column, char *form, int *dtype)
04311 {
04312     const char *colname;
04313     const char *format;
04314 
04315     check_nomsg( colname = table_colname_from_number(tid, column));
04316     
04317     check_nomsg( *dtype = table_cpltype_to_dtype(
04318                      cpl_table_get_column_type(frames[tid].data.table.table, colname)));
04319 
04320     check_nomsg( format = cpl_table_get_column_format(frames[tid].data.table.table, colname));
04321 
04322     strcpy(form, format);
04323     
04324   cleanup: 
04325     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04326 }
04327 
04328 /*----------------------------------------------------------------------------*/
04336 /*----------------------------------------------------------------------------*/
04337 int flames_midas_tclget(int tid, int column, char *label)
04338 {
04339     const char *colname;
04340 
04341     label[0] = '\0';
04342     check_nomsg( colname = table_colname_from_number(tid, column));
04343 
04344     /* It's up to the caller to allocate enough space */
04345     strcpy(label, colname);
04346     
04347   cleanup:
04348     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04349 }
04350 
04351 /*----------------------------------------------------------------------------*/
04359 /*----------------------------------------------------------------------------*/
04360 int flames_midas_tcuget(int tid, int column, char *unit)
04361 {
04362     const char *colname;
04363     const char *u;
04364 
04365     unit[0] = '\0';
04366     //uves_msg("column=%s \n",column);
04367     check_nomsg( colname = table_colname_from_number(tid, column));
04368     check_nomsg( u = cpl_table_get_column_unit(frames[tid].data.table.table, colname));
04369     assure( u != NULL, CPL_ERROR_ILLEGAL_INPUT, "Column %s unit not set", colname);
04370     
04371     strcpy(unit, u);
04372     
04373   cleanup: 
04374     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04375 }
04376 /*----------------------------------------------------------------------------*/
04385 /*----------------------------------------------------------------------------*/
04386 int flames_midas_tclser(int tid, const char *label, int *column)
04387 {
04388     /* This function seems to be the same as flames_midas_tccser(),
04389        except that
04390        flames_midas_tccser() is case sensitive and allows prefixing
04391        the column name with : or #
04392 
04393        But these subtle differences are not used by the FLAMES code, so
04394        just call that other function */
04395     return flames_midas_tccser(tid, label, column);
04396 }
04397 
04398 /*----------------------------------------------------------------------------*/
04416 /*----------------------------------------------------------------------------*/
04417 int flames_midas_tccini(int tid, int dtype, int alen, 
04418                         const char *form, const char *unit, const char *label, 
04419                         int *column)
04420 {
04421     cpl_type type;
04422 
04423     passure( invariant(tid), " ");
04424     
04425     assure( frame_is_open(tid) && !frames[tid].is_image, CPL_ERROR_ILLEGAL_INPUT,
04426         "Table %d is not open", tid);
04427     
04428     check( load_frame(tid), "Could not load table %s", frames[tid].filename);
04429     
04430     check_nomsg( type = table_dtype_to_cpltype(dtype, alen) );
04431 
04432     uves_msg_debug("Creating column %s (unit = %s, format = %s)",
04433                    label, unit, form);
04434 
04435     /* Create the column */
04436     assure( !cpl_table_has_column(frames[tid].data.table.table, label),
04437             CPL_ERROR_ILLEGAL_OUTPUT,
04438             "Column %s already exists", label);
04439     cpl_table_new_column       (frames[tid].data.table.table, label, type);
04440     cpl_table_set_column_format(frames[tid].data.table.table, label, form);
04441     cpl_table_set_column_unit  (frames[tid].data.table.table, label, unit);
04442 
04443     /* Initialize column to avoid garbage (CPL doesn't initialize NULL elements) */
04444     switch(type) {
04445     case CPL_TYPE_INT   : cpl_table_fill_invalid_int   (frames[tid].data.table.table, label, -1); break;
04446     case CPL_TYPE_FLOAT : cpl_table_fill_invalid_float (frames[tid].data.table.table, label, -1); break;
04447     case CPL_TYPE_DOUBLE: cpl_table_fill_invalid_double(frames[tid].data.table.table, label, -1); break;
04448     case CPL_TYPE_STRING: /* Do nothing, already NULL */ break;
04449     default:
04450         passure( false, " " );
04451         break;
04452     }
04453 
04454     /* Update description of columns */
04455     *column = cpl_table_get_ncol(frames[tid].data.table.table) - 1;
04456     cpl_table_set_size  (frames[tid].data.table.colnames, *column);  /* This is O(n^2) in the number of 
04457                                                              columns (i.e. slow if there are
04458                                                              many columns, but the CPL table 
04459                                                              handling is like that anyway. */
04460     cpl_table_set_string(frames[tid].data.table.colnames, COLNAME, *column-1, label);
04461 
04462     passure( invariant(tid), " ");
04463 
04464   cleanup:
04465     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04466 }
04467 
04468 /*----------------------------------------------------------------------------*/
04483 /*----------------------------------------------------------------------------*/
04484 static int
04485 tcerd(cpl_type type, int tid, int row, int column,
04486       void *value, int *null)
04487 {
04488     const char *colname;
04489     const char *val_str;
04490 
04491     check_nomsg( colname = table_colname_from_number(tid, column));
04492 
04493     /* Check disabled, allow type conversion 
04494     assure( cpl_table_get_column_type(frames[tid].data.table.table, colname)
04495             == type, CPL_ERROR_TYPE_MISMATCH, "Column %s type is %s, type %s expected",
04496             colname, uves_tostring_cpl_type(cpl_table_get_column_type(frames[tid].data.table.table, colname)),
04497             uves_tostring_cpl_type(type) );
04498     */
04499 
04500     assure( 1 <= row && row <= cpl_table_get_nrow(frames[tid].data.table.table),
04501             CPL_ERROR_ACCESS_OUT_OF_RANGE,
04502             "Cannot read row %d of %" CPL_SIZE_FORMAT " row table",
04503             row, cpl_table_get_nrow(frames[tid].data.table.table));
04504 
04505     switch(type) {
04506     case CPL_TYPE_INT:
04507         ((int *)value)[0] = cpl_table_get(frames[tid].data.table.table,
04508                                           colname, row - 1,
04509                                           null);
04510         break;
04511     case CPL_TYPE_FLOAT:
04512         ((float *)value)[0] = cpl_table_get(frames[tid].data.table.table,
04513                                             colname, row - 1,
04514                                             null);
04515         break;
04516     case CPL_TYPE_DOUBLE:
04517         ((double *)value)[0] = cpl_table_get(frames[tid].data.table.table,
04518                                              colname, row - 1,
04519                                              null);
04520         break;
04521     case CPL_TYPE_STRING:
04522         val_str = cpl_table_get_string(frames[tid].data.table.table,
04523                                        colname, row - 1);
04524         if (val_str == NULL)
04525             {
04526                 if (null != NULL) *null = 1;
04527                 ((char *)value)[0] = '\0';
04528             }
04529         else
04530             {
04531                 if (null != NULL) *null = 0;
04532                 strcpy((char *)value, val_str);
04533             }
04534         break;
04535     default:
04536         assure( false, CPL_ERROR_INVALID_TYPE, "Type is %s", uves_tostring_cpl_type(type));
04537         break;
04538     }
04539 
04540   cleanup:
04541     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04542 }
04543 
04544 /*----------------------------------------------------------------------------*/
04551 /*----------------------------------------------------------------------------*/
04552 int flames_midas_tcerdc(int tid, int row, int column, char *values, int *null)
04553 {
04554     return tcerd(CPL_TYPE_STRING, tid, row, column, values, null);
04555 }
04556 
04557 /*----------------------------------------------------------------------------*/
04561 /*----------------------------------------------------------------------------*/
04562 int flames_midas_tcerdi(int tid, int row, int column, int *value, int *null)
04563 {
04564     return tcerd(CPL_TYPE_INT, tid, row, column, value, null);
04565 }
04566 
04567 /*----------------------------------------------------------------------------*/
04571 /*----------------------------------------------------------------------------*/
04572 int flames_midas_tcerdr(int tid, int row, int column, float *value, int *null)
04573 {
04574     return tcerd(CPL_TYPE_FLOAT, tid, row, column, value, null);
04575 }
04576 
04577 /*----------------------------------------------------------------------------*/
04581 /*----------------------------------------------------------------------------*/
04582 int flames_midas_tcerdd(int tid, int row, int column,
04583             double *value, int *null)
04584 {
04585     return tcerd(CPL_TYPE_DOUBLE, tid, row, column, value, null);
04586 }
04587 
04588 /*----------------------------------------------------------------------------*/
04600 /*----------------------------------------------------------------------------*/
04601 static int tcewr(cpl_type type, int tid, int row, int column, const void *value)
04602 {
04603     const char *colname;
04604     
04605     check_nomsg( colname = table_colname_from_number(tid, column));
04606     
04607     /* Check disabled, allow type mismatch and conversion (as in MIDAS)
04608     assure( cpl_table_get_column_type(frames[tid].data.table.table, colname)
04609             == type, CPL_ERROR_TYPE_MISMATCH, "Column %s has type %s; %s expected",
04610             colname, uves_tostring_cpl_type(cpl_table_get_column_type(frames[tid].data.table.table, colname)),
04611             uves_tostring_cpl_type(type) );
04612     */
04613 
04614     assure( row <= cpl_table_get_nrow(frames[tid].data.table.table),
04615             CPL_ERROR_ACCESS_OUT_OF_RANGE,
04616             "Cannot write row %d from %" CPL_SIZE_FORMAT " row table",
04617             row, cpl_table_get_nrow(frames[tid].data.table.table));
04618 
04619     if (row > frames[tid].data.table.maxrow) {
04620         frames[tid].data.table.maxrow = row;
04621     }
04622 
04623     switch(type) {
04624     case CPL_TYPE_INT:    
04625         cpl_table_set(frames[tid].data.table.table, colname, row - 1, ((const int *)value)[0]); 
04626         break;
04627     case CPL_TYPE_FLOAT:
04628         cpl_table_set(frames[tid].data.table.table, colname, row - 1, ((const float *)value)[0]); 
04629         break;
04630     case CPL_TYPE_DOUBLE: 
04631         cpl_table_set(frames[tid].data.table.table, colname, row - 1, ((const double *)value)[0]); 
04632         break;
04633     case CPL_TYPE_STRING:
04634         cpl_table_set_string(frames[tid].data.table.table, colname, row - 1, (const char *)value); 
04635         break;
04636     default:
04637         assure( false, CPL_ERROR_INVALID_TYPE, "Type is %s", uves_tostring_cpl_type(type));
04638         break;
04639     }
04640 
04641   cleanup:
04642     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04643 }
04644 
04645 /*----------------------------------------------------------------------------*/
04652 /*----------------------------------------------------------------------------*/
04653 int flames_midas_tcewrc(int tid, int row, int column, const char *value)
04654 {
04655     /* Write full string, including commas */
04656     return tcewr(CPL_TYPE_STRING, tid, row, column, value);
04657 }
04658 
04659 /*----------------------------------------------------------------------------*/
04663 /*----------------------------------------------------------------------------*/
04664 int flames_midas_tcewrd(int tid, int row, int column, const double *value)
04665 {
04666     return tcewr(CPL_TYPE_DOUBLE, tid, row, column, value);
04667 }
04668 
04669 /*----------------------------------------------------------------------------*/
04673 /*----------------------------------------------------------------------------*/
04674 int flames_midas_tcewri(int tid, int row, int column, const int *value)
04675 {
04676     return tcewr(CPL_TYPE_INT, tid, row, column, value);
04677 }
04678 /*----------------------------------------------------------------------------*/
04682 /*----------------------------------------------------------------------------*/
04683 int flames_midas_tcewrr(int tid, int row, int column, const float *value)
04684 {
04685     return tcewr(CPL_TYPE_FLOAT, tid, row, column, value);
04686 }
04687 
04688 /*----------------------------------------------------------------------------*/
04692 /*----------------------------------------------------------------------------*/
04693 static int
04694 tcard(cpl_type type, int tid, int row, int column,
04695       int index, int items, void *value)
04696 {
04697     assure( index == 1 && (
04698                 type == CPL_TYPE_STRING ||
04699                 items == 1),
04700             CPL_ERROR_UNSUPPORTED_MODE,
04701             "index, items = %d, %d", index, items);
04702 
04703     return tcerd(type, tid, row, column, value, NULL);
04704 
04705   cleanup:
04706     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04707 }
04708 
04709 /*----------------------------------------------------------------------------*/
04721 /*----------------------------------------------------------------------------*/
04722 int flames_midas_tcardc(int tid, int row, int col, int index, int items, char *value)
04723 {
04724     return tcard(CPL_TYPE_STRING, tid, row, col, index, items, value);
04725 }
04726 
04727 /*----------------------------------------------------------------------------*/
04738 /*----------------------------------------------------------------------------*/
04739 int flames_midas_tcardd(int tid, int row, int col, int index, int items, double *value)
04740 {
04741     return tcard(CPL_TYPE_DOUBLE, tid, row, col, index, items, value);
04742 }
04743 
04744 /*----------------------------------------------------------------------------*/
04748 /*----------------------------------------------------------------------------*/
04749 int flames_midas_tcardi(int tid, int row, int col, int index, int items, int *value)
04750 {
04751     return tcard(CPL_TYPE_INT, tid, row, col, index, items, value);
04752 }
04753 
04754 /*----------------------------------------------------------------------------*/
04758 /*----------------------------------------------------------------------------*/
04759 int flames_midas_tcardr(int tid, int row, int col, int index, int items, float *value)
04760 {
04761     return tcard(CPL_TYPE_FLOAT, tid, row, col, index, items, value);
04762 }
04763 
04764 
04765 /*----------------------------------------------------------------------------*/
04769 /*----------------------------------------------------------------------------*/
04770 static int
04771 tcawr(cpl_type type, int tid, int row, int col, int index, int items, const void *value)
04772 {
04773     assure( index == 1 && (
04774                 type == CPL_TYPE_STRING ||
04775                 items == 1),
04776             CPL_ERROR_UNSUPPORTED_MODE,
04777             "index, items = %d, %d", index, items);
04778     
04779     return tcewr(type, tid, row, col, value);
04780     
04781   cleanup:
04782     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04783 }
04784 
04785 /*----------------------------------------------------------------------------*/
04796 /*----------------------------------------------------------------------------*/
04797 int flames_midas_tcawrc(int tid, int row, int col, int index, int items, const char *value)
04798 {
04799     return tcawr(CPL_TYPE_STRING, tid, row, col, index, items, value);
04800 }
04801 /*----------------------------------------------------------------------------*/
04812 /*----------------------------------------------------------------------------*/
04813 int flames_midas_tcawrd(int tid, int row, int col, int index, int items, const double *value)
04814 {
04815     return tcawr(CPL_TYPE_DOUBLE, tid, row, col, index, items, value);
04816 }
04817 /*----------------------------------------------------------------------------*/
04821 /*----------------------------------------------------------------------------*/
04822 int flames_midas_tcawri(int tid, int row, int col, int index, int items, const int *value)
04823 {
04824     return tcawr(CPL_TYPE_INT, tid, row, col, index, items, value);
04825 }
04826 
04827 /*----------------------------------------------------------------------------*/
04831 /*----------------------------------------------------------------------------*/
04832 int flames_midas_tcawrr(int tid, int row, int col, int index, int items, const float *value)
04833 {
04834     return tcawr(CPL_TYPE_FLOAT, tid, row, col, index, items, value);
04835 }
04836 
04837 /*----------------------------------------------------------------------------*/
04845 /*----------------------------------------------------------------------------*/
04846 int flames_midas_tcsget(int tid, int row, int *value)
04847 {
04848     passure( invariant(tid), " ");
04849     
04850     assure( frame_is_open(tid) && !frames[tid].is_image, CPL_ERROR_ILLEGAL_INPUT,
04851         "Table %d is not open", tid);
04852     
04853     check( load_frame(tid), "Could not load table %s", frames[tid].filename);
04854 
04855     assure( 1 <= row && row <= cpl_table_get_nrow(frames[tid].data.table.table),
04856             CPL_ERROR_ACCESS_OUT_OF_RANGE,
04857             "Cannot read row %d  of %" CPL_SIZE_FORMAT " row table %s", row,
04858             cpl_table_get_nrow(frames[tid].data.table.table),
04859             frames[tid].filename);
04860 
04861     *value = cpl_table_get_int(frames[tid].data.table.table,
04862                                "Select",
04863                                row - 1, NULL);
04864 
04865   cleanup:
04866     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04867 }
04868 
04869 /*----------------------------------------------------------------------------*/
04877 /*----------------------------------------------------------------------------*/
04878 int flames_midas_tcsput(int tid, int row, const int *value)
04879 {
04880     passure( invariant(tid), " ");
04881     
04882     assure( frame_is_open(tid) && !frames[tid].is_image, CPL_ERROR_ILLEGAL_INPUT,
04883         "Table %d is not open", tid);
04884     
04885     check( load_frame(tid), "Could not load table %s", frames[tid].filename);
04886 
04887     assure( 1 <= row && row <= cpl_table_get_nrow(frames[tid].data.table.table),
04888             CPL_ERROR_ACCESS_OUT_OF_RANGE,
04889             "Cannot write to row %d of %" CPL_SIZE_FORMAT " row table %s", row,
04890             cpl_table_get_nrow(frames[tid].data.table.table),
04891             frames[tid].filename);
04892 
04893     cpl_table_set_int(frames[tid].data.table.table, "Select", row - 1, *value);
04894 
04895 
04896     if (row > frames[tid].data.table.maxrow) {
04897         frames[tid].data.table.maxrow = row;
04898     }
04899   cleanup:
04900     return (cpl_error_get_code() == CPL_ERROR_NONE) ? 0 : 1;
04901 }
04902 

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