source: Sophya/trunk/SophyaExt/FitsIOServer/fitsinoutfile.cc@ 2834

Last change on this file since 2834 was 2820, checked in by ansari, 20 years ago

1/ Ajout classes FitsInOutFile / FitsTypes / FitsIOException d'enrobage lib cfitsio
2/ Ajout classes FitsBlockRW<T> pour lecture/ecriture sur IMGHDU et Tables
3/ Ajout classes gestionnaire FITS FitsHandler<T> et FitsManager
4/ Ajout classe gestionnaires pour TArray<T> FitsArrayHandler<T>
5/ Ajout classe gestionnaire pour DataTable FitsHandler<BaseDataTable>

Reza 12 octobre 2006

  • Property svn:executable set to *
File size: 14.2 KB
Line 
1#include "sopnamsp.h"
2#include "machdefs.h"
3#include "segdatablock.h"
4#include "fitsinoutfile.h"
5#include <stdio.h>
6#include <string.h>
7#include <iostream>
8
9
10/*!
11 \class SOPHYA::FitsInOutFile
12 \ingroup FitsIOServer
13 \brief Wrapper class for cfitsio library functions
14*/
15
16/*-- Methode --*/
17//! Default constructor - The file should be opened subsequently using Open
18FitsInOutFile::FitsInOutFile()
19{
20 fptr_ = NULL;
21 SetDef_BinTable();
22}
23
24/*-- Methode --*/
25//! Constructor with specification of file name and access mode
26FitsInOutFile::FitsInOutFile(string const & name, FitsIOMode mode)
27{
28 // cout << " DBG - FitsInOutFile(string name= " << name << ")" << endl;
29 fptr_ = NULL;
30 SetDef_BinTable();
31 Open(name.c_str(), mode);
32}
33
34/*-- Methode --*/
35//! Constructor with specification of file name and access mode
36FitsInOutFile::FitsInOutFile(const char * name, FitsIOMode mode)
37{
38 // cout << " DBG - FitsInOutFile(char* name= " << name << ")" << endl;
39 fptr_ = NULL;
40 SetDef_BinTable();
41 Open(name, mode);
42}
43
44/* -- Fonction utilitaire pour verifier fichier ouvert (pointeur non null) -- */
45static inline void CheckFitsPtr(fitsfile* fptr) {
46 if (fptr == NULL) throw FitsIOException("FitsInOutFile/Error - NULL fitsfile pointer ");
47 return;
48}
49/* -- Fonction utilitaire pour verifier le code d'erreur fitsio -- */
50static inline bool FitsCheckStatus(int st, char * emsg = NULL) {
51 if (st) {
52 fits_report_error(stderr, st);
53 if (emsg) {
54 char buff[FLEN_ERRMSG];
55 fits_get_errstatus(st, buff);
56 string msg = emsg;
57 msg += buff;
58 throw FitsIOException(msg);
59 }
60 else return true;
61 }
62 else return false;
63}
64
65/*-- Methode --*/
66//! Destructor - Closes the fits file (if opened)
67FitsInOutFile::~FitsInOutFile()
68{
69 Close();
70}
71
72/*-- Methode --*/
73//! Opens the named fits file (see cfitsio routines fits_open_file and fits_create_file)
74void FitsInOutFile::Open(const char* name, FitsIOMode mode)
75{
76 if (fptr_ != NULL)
77 throw FitsIOException("FitsInOutFile::Open() /Error - file already opened ");
78 int status = 0;
79 fptr_ = NULL;
80 switch ( mode ) {
81 case Fits_RO :
82 fits_open_file(&fptr_, name, READONLY, &status);
83 break;
84 case Fits_RW :
85 fits_open_file(&fptr_, name, READWRITE, &status);
86 break;
87 case Fits_Create :
88 fits_create_file(&fptr_, name, &status);
89 break;
90 }
91 FitsCheckStatus(status, "FitsInOutFile::Open() Error: ");
92 fname_ = name;
93 mode_ = mode;
94 return;
95}
96
97/*-- Methode --*/
98//! Opens the named fits file (see cfitsio routines fits_open_file and fits_create_file)
99void FitsInOutFile::Close()
100{
101 if (fptr_ == NULL) return;
102 int status = 0;
103 if (mode_ == Fits_Create) {
104 status = 0;
105 int hdutyp;
106 fits_movabs_hdu(FitsPtr() , 1, &hdutyp, &status);
107 status = 0;
108 float sfv = 2.0;
109 fits_write_key(FitsPtr(), TFLOAT, "SOPHYAFV", &sfv,
110 "SOPHYA FitsIOServer module version", &status);
111 fits_write_date(FitsPtr(), &status);
112 status = 0;
113 fits_write_comment(FitsPtr(), "------------- SOPHYA (http://www.sophya.org) -------------", &status);
114 fits_write_comment(FitsPtr(), " (C) LAL/IN2P3-CNRS Orsay , (C) DAPNIA/CEA Saclay (FRANCE)", &status);
115 fits_write_comment(FitsPtr(), "-----------------------------------------------------------", &status);
116 }
117 MoveAbsToHDU(1);
118 status = 0;
119 if (fptr_) fits_close_file(fptr_, &status);
120 if (status) {
121 cerr << " FitsInOutFile::Close - Error closing fits file !" << endl;
122 fits_report_error(stderr, status);
123 }
124}
125
126
127/*-- Methode --*/
128float FitsInOutFile::cfitsioVersion()
129{
130 float ver;
131 fits_get_version(&ver);
132 return ver;
133}
134
135/*-- Methode --*/
136int FitsInOutFile::NbHDUs() const
137{
138 int status = 0;
139 int nbhdu = 0;
140 fits_get_num_hdus(FitsPtr() , &nbhdu, &status);
141 FitsCheckStatus(status, "FitsInOutFile::NbHDUs() Error: ");
142 return nbhdu;
143}
144
145/*-- Methode --*/
146int FitsInOutFile::CurrentHDU() const
147{
148 int status = 0;
149 int curhdu = 0;
150 fits_get_hdu_num(FitsPtr() , &curhdu);
151 return curhdu;
152}
153
154/*-- Methode --*/
155int FitsInOutFile::CurrentHDUType() const
156{
157 int status = 0;
158 int hdutyp = 0;
159 fits_get_hdu_type(FitsPtr() , &hdutyp, &status);
160 FitsCheckStatus(status, "FitsInOutFile::CurrentHDUType() Error: ");
161 return hdutyp;
162}
163
164/*-- Methode --*/
165string FitsInOutFile::CurrentHDUTypeStr() const
166{
167 int status = 0;
168 int hdutyp = 0;
169 fits_get_hdu_type(FitsPtr() , &hdutyp, &status);
170 if ( FitsCheckStatus(status, "FitsInOutFile::CurrentHDUTypeStr() Error: ") )
171 return "Unknown";
172 else {
173 if (hdutyp == IMAGE_HDU) return "IMAGE_HDU";
174 else if (hdutyp == BINARY_TBL) return "BINARY_TBL";
175 else if (hdutyp == ASCII_TBL) return "ASCII_TBL";
176 else return "Unknown";
177 }
178}
179
180/*-- Methode --*/
181int FitsInOutFile::MoveAbsToHDU(int hdunum)
182{
183 int status = 0;
184 int hdutyp = 0;
185 fits_movabs_hdu(FitsPtr() , hdunum, &hdutyp, &status);
186 FitsCheckStatus(status, "FitsInOutFile::MoveAbsToHDU Error: ");
187 return hdutyp;
188}
189
190/*-- Methode --*/
191int FitsInOutFile::MoveRelToHDU(int hdunum)
192{
193 int status = 0;
194 int hdutyp = 0;
195 fits_movrel_hdu(FitsPtr() , hdunum, &hdutyp, &status);
196 FitsCheckStatus(status, "FitsInOutFile::MoveRelToHDU Error: ");
197 return hdutyp;
198}
199
200/*-- Methode --*/
201int FitsInOutFile::MoveToNextHDU()
202{
203 if (CurrentHDU() < NbHDUs())
204 return MoveRelToHDU(1);
205 else return -1;
206}
207
208/*-- Methode --*/
209void FitsInOutFile::CreateImageHDU(int bitpix, int naxis, long* naxes)
210{
211 int status = 0;
212 fits_create_img(fptr_, bitpix, naxis, naxes, &status);
213 FitsCheckStatus(status,"FitsInOutFile::CreateImageHDU() Error: ");
214 return;
215}
216
217/*-- Methode --*/
218 /*!
219 See cfitsio function fits_get_img_param() for more information
220 naxis : input=max naxes dimension / out=image dimension
221 Rc : return the image type (bitpix)
222 */
223int FitsInOutFile::GetImageHDUInfo(int& naxis, long* naxes) const
224{
225 int status = 0;
226 int maxdim = naxis;
227 int bitpix = 0;
228 fits_get_img_param(fptr_, maxdim, &bitpix, &naxis, naxes, &status);
229 FitsCheckStatus(status, "FitsInOutFile::GetImageHDUInfo() Error: ");
230 return bitpix;
231}
232
233/*-- Methode --*/
234long FitsInOutFile::GetNbRows() const
235{
236 int status = 0;
237 long nbrow = 0;
238 fits_get_num_rows(FitsPtr() , &nbrow, &status);
239 FitsCheckStatus(status, "FitsInOutFile::GetNbRows() Error: " );
240 return nbrow;
241}
242
243/*-- Methode --*/
244int FitsInOutFile::GetNbCols() const
245{
246 int status = 0;
247 int nbcol = 0;
248 fits_get_num_cols(FitsPtr() , &nbcol, &status);
249 FitsCheckStatus(status, "FitsInOutFile::GetNbCols() Error: ");
250 return nbcol;
251}
252
253/*-- Methode --*/
254/*!
255 Create a binary or ascii table - See cfitsio routine fits_create_tbl for more information.
256 \param extname : extension name. NextExtensionName() will be used if extname == NULL or extname == "".
257 \param ncols : Number of columns
258 \param ttype : Column names
259 \param tform : Column data types J / V / K / E / D ...
260 \param tunit : Column units
261*/
262void FitsInOutFile::CreateTable(int tbltyp, const char * extname, int ncols,
263 char * ttype[], char * tform[],
264 char * tunit[], long ininr)
265{
266 int status = 0;
267
268 char * extn;
269 if ( (extname != NULL) && (extname[0] != '\0') ) extn = const_cast<char *>(extname);
270 else extn = const_cast<char *>(next_extname_.c_str());
271
272 fits_create_tbl(FitsPtr(), tbltyp, ininr, ncols, ttype,
273 tform, tunit, extn, &status);
274 next_extname_ = "";
275 FitsCheckStatus(status, "FitsInOutFile::CreateTable() Error: ");
276 return;
277}
278
279/*-- Methode --*/
280/*!
281 Create a binary or ascii table - See cfitsio routine fits_create_tbl for more information.
282 number of columns specified by colnames.size()
283 \param extname : extension name
284 \param colnames : Column names
285 \param tform : Column data types J / V / K / E / D ...
286 \param tunit : Column units
287*/
288void FitsInOutFile::CreateTable(int tbltyp, const string & extname,
289 const vector<string> & colnames,
290 const vector<string> & tform,
291 const vector<string> & tunit,
292 long ininr)
293{
294 if ( (colnames.size() != tform.size() ) ||
295 (colnames.size() != tunit.size() ) )
296 throw SzMismatchError("FitsInOutFile::CreateTable(): different sizes for colnames,tform,tunit");
297
298 // On utilise les SegDataBlock<T> pour eviter d'avoir a gerer les new/delete
299 // en plus avec les exceptions ...
300 size_t kk;
301 int ncols = colnames.size();
302
303 SegDataBlock<const char *> colnm(colnames.size(), 1);
304 for(kk=0; kk<colnames.size(); kk++) colnm[kk] = colnames[kk].c_str();
305 SegDataBlock<const char *> tfm(tform.size(), 1);
306 for(kk=0; kk<tform.size(); kk++) tfm[kk] = tform[kk].c_str();
307 SegDataBlock<const char *> tun(tunit.size(), 1);
308 for(kk=0; kk<tunit.size(); kk++) tun[kk] = tunit[kk].c_str();
309
310 CreateTable(tbltyp, const_cast<char *>(extname.c_str()), ncols,
311 const_cast<char **>(colnm.GetSegment(0)),
312 const_cast<char **>(tfm.GetSegment(0)),
313 const_cast<char **>(tun.GetSegment(0)),
314 ininr);
315}
316
317/*-- Methode --*/
318/*!
319 Return number of columns in table (See fits_get_colname and fits_get_coltype for more information)
320 \param colnames : Column names
321 \param coltypes : Column data types ( TSTRING / TSHORT / TFLOAT / ... )
322 \param repcnt : Repeat count (for columns with vector data)
323 \param width : The width (in bytes) of a single element in a column
324
325*/
326long FitsInOutFile::GetColInfo(vector<string> & colnames,
327 vector<int> & coltypes,
328 vector<long> & repcnt,
329 vector<long> & width)
330{
331
332 int status = 0;
333
334 colnames.clear();
335 coltypes.clear();
336 width.clear();
337 repcnt.clear();
338
339 int colnum, typecode;
340 long repeat, colw;
341 int ncols = 0;
342 char colname[128]; // longueur max d'un nom de colonne
343
344 while (status != COL_NOT_FOUND) {
345 fits_get_colname(FitsPtr(), CASEINSEN, "*", colname, &colnum, &status);
346 if (status == COL_NOT_FOUND) break;
347 if (status != COL_NOT_UNIQUE) {
348 char buff[32];
349 fits_get_errstatus(status, buff);
350 string msg = "FitsInOutFile::GetColInfo() Error(1): " ;
351 msg += buff;
352 throw FitsIOException(msg);
353 }
354 int sta2 = 0;
355 fits_get_coltype(FitsPtr(), colnum, &typecode, &repeat, &colw, &sta2);
356 FitsCheckStatus(sta2, "FitsInOutFile::GetColInfo() Error(2): ");
357
358 colnames.push_back(colname);
359 coltypes.push_back(typecode);
360 repcnt.push_back(repeat);
361 width.push_back(colw);
362 }
363 return colnames.size();
364}
365
366/*-- Methode --*/
367void FitsInOutFile::InsertColumn(int numcol, const char* colname, const char* fmt)
368{
369 int status = 0;
370 fits_insert_col(FitsPtr(), numcol, const_cast<char *>(colname),
371 const_cast<char *>(fmt), &status);
372 FitsCheckStatus(status, "FitsInOutFile::AddColumn() Error: ");
373
374 return;
375}
376
377/*-- Methode --*/
378string FitsInOutFile::KeyValue(string const & key)
379{
380 int status = 0;
381 char value[FLEN_VALUE], comm[FLEN_COMMENT];
382 fits_read_key(FitsPtr(), TSTRING, const_cast<char *>(key.c_str()), value, comm, &status);
383 FitsCheckStatus(status, "FitsInOutFile::KeyValue() Error: ");
384 return value;
385}
386
387/*-- Methode --*/
388int FitsInOutFile::GetHeaderRecords(DVList& dvl)
389{
390 int status = 0;
391 int nkeys = 0;
392 fits_get_hdrspace(FitsPtr(), &nkeys, NULL, &status);
393 FitsCheckStatus(status, "FitsInOutFile::GetHeaderRecords() Error(1): ");
394
395 char record[FLEN_CARD], value[FLEN_VALUE], comm[FLEN_COMMENT];
396 string comment;
397 int nok = 0;
398 for(int kk=1; kk<=nkeys; kk++) {
399 status = 0;
400 fits_read_record(FitsPtr(), kk, record, &status);
401 FitsCheckStatus(status, "FitsInOutFile::GetHeaderRecords() Error(2): ");
402 int kclas = fits_get_keyclass(record);
403 if ( (kclas == TYP_STRUC_KEY) || (kclas == TYP_NULL_KEY) ) continue;
404 int len = 0;
405 status = 0;
406 fits_get_keyname(record, value, &len, &status);
407 if (status) continue;
408 string keyname = value;
409 status = 0;
410 fits_parse_value(record, value, comm, &status);
411 if (status) continue;
412 if (kclas == TYP_COMM_KEY) {
413 if (comment.length() > 0) comment += '\n';
414 comment += value;
415 continue;
416 }
417 char ktyp;
418 status = 0;
419 fits_get_keytype(value, &ktyp, &status);
420 if (status) continue;
421 switch (ktyp) {
422 case 'C' :
423 case 'L' : // Il faudra traiter le cas des nb complexes
424 case 'X' : // idem pour les valeurs logiques
425 dvl.SetS(keyname, value);
426 break;
427 case 'I' :
428 dvl.SetI(keyname, atoi(value));
429 break;
430 case 'F' :
431 dvl.SetD(keyname, atof(value));
432 break;
433 }
434 if (strlen(comm) > 0) {
435 string scom = comm;
436 dvl.SetComment(keyname, scom);
437 }
438 nok++;
439 }
440 if (comment.length() > 0) dvl.Comment() = comment;
441 return nok;
442}
443
444/*-- Methode --*/
445void FitsInOutFile::WriteKey(const char * kname, MuTyV const & mtv,
446 const char *comment)
447{
448 CheckFitsPtr(FitsPtr());
449 char keyname[FLEN_KEYWORD], comm[FLEN_COMMENT], sval[FLEN_VALUE];
450 long lval;
451 double dval;
452 string s;
453
454 keyname[0] = '\0';
455 strncpy(keyname, kname, FLEN_KEYWORD); keyname[FLEN_KEYWORD-1] = '\0';
456 comm[0] = '\0';
457 if (comm != NULL)
458 strncpy(comm, comment, FLEN_COMMENT); comm[FLEN_COMMENT-1] = '\0';
459 int status = 0;
460 switch (mtv.Type()) {
461 case MuTyV::MTVInteger :
462 lval = mtv.GetIntPart();
463 fits_write_key(FitsPtr(), TLONG, keyname, &lval, comm, &status);
464 break;
465 case MuTyV::MTVFloat :
466 dval = mtv.GetRealPart();
467 fits_write_key(FitsPtr(), TDOUBLE, keyname, &dval, comm, &status);
468 break;
469 case MuTyV::MTVString :
470 strncpy(sval, mtv.GetStringPointer()->c_str(), FLEN_VALUE);
471 keyname[FLEN_VALUE-1] = '\0';
472 fits_write_key(FitsPtr(), TSTRING, keyname, sval, comm, &status);
473 break;
474 default :
475 s = (string)mtv;
476 strncpy(sval, s.c_str(), FLEN_VALUE);
477 keyname[FLEN_VALUE-1] = '\0';
478 fits_write_key(FitsPtr(), TSTRING, keyname, sval, comm, &status);
479 break;
480 }
481 FitsCheckStatus(status, "FitsInOutFile::WriteKey() Error: ");
482 return;
483}
484
485/*-- Methode --*/
486int FitsInOutFile::WriteHeaderRecords(DVList & dvl)
487{
488
489 CheckFitsPtr(FitsPtr());
490 int status = 0;
491 DVList::ValList::const_iterator it;
492 for(it = dvl.Begin(); it != dvl.End(); it++)
493 WriteKey( (*it).first, (*it).second.elval, (*it).second.elcomm);
494 // Ecriture commentaires
495 return 0;
496
497}
498
499/*-- Methode --*/
500void FitsInOutFile::Print(ostream& os, int lev) const
501{
502 string mode;
503 if (mode_ == Fits_Create) mode = "Create";
504 else if (mode_ == Fits_RO) mode = "ReadOnly";
505 else mode = "ReadWrite";
506 os << " FitsInOutFile(FileName= " << fname_ << " Mode="
507 << mode << ") fitsioVers= " << cfitsioVersion() << endl;
508 os << " TotalNumberHDU= " << NbHDUs() << " CurrentHDU: Num= "
509 << CurrentHDU() << " Type= " << CurrentHDUTypeStr() << endl;
510
511 return;
512}
513
514
Note: See TracBrowser for help on using the repository browser.