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

Last change on this file since 3359 was 3167, checked in by ansari, 19 years ago

Passage a la version ll (LONGLONG) des routines fits , cmv+Reza 02/02/2007

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