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

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

correction 2 petits bugs ds nouveau fits - Reza 18/11/2005

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