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

Generated on 28 Feb 2012 for UVES Pipeline Reference Manual by  doxygen 1.6.1