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

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