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

Last change on this file since 3035 was 2937, checked in by ansari, 19 years ago

changement valeur par defaut d'argument ds fitsinoutfile.h .cc , Reza 3/4/2006

  • Property svn:executable set to *
File size: 17.6 KB
RevLine 
[2820]1#include "sopnamsp.h"
2#include "machdefs.h"
3#include "segdatablock.h"
4#include "fitsinoutfile.h"
[2932]5#include "strutil.h"
[2820]6#include <stdio.h>
7#include <string.h>
8#include <iostream>
9
[2843]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}
[2820]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;
[2864]104 mode_ = Fits_RO;
[2820]105 SetDef_BinTable();
[2843]106 SetDef_StrColWidth();
[2820]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;
[2860]115 ownfptr = true;
[2820]116 SetDef_BinTable();
[2843]117 SetDef_StrColWidth();
[2820]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;
[2860]127 ownfptr = true;
[2820]128 SetDef_BinTable();
[2843]129 SetDef_StrColWidth();
[2820]130 Open(name, mode);
131}
132
[2860]133/*! \brief Copy constructor
[2864]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.
[2860]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
[2820]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;
[2860]197 ownfptr = true;
[2820]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{
[2860]205 if (ownfptr == false) return;
[2820]206 if (fptr_ == NULL) return;
207 int status = 0;
208 if (mode_ == Fits_Create) {
209 status = 0;
210 int hdutyp;
211 fits_movabs_hdu(FitsPtr() , 1, &hdutyp, &status);
212 status = 0;
[2843]213 float sfv = Version();
[2820]214 fits_write_key(FitsPtr(), TFLOAT, "SOPHYAFV", &sfv,
215 "SOPHYA FitsIOServer module version", &status);
216 fits_write_date(FitsPtr(), &status);
217 status = 0;
218 fits_write_comment(FitsPtr(), "------------- SOPHYA (http://www.sophya.org) -------------", &status);
219 fits_write_comment(FitsPtr(), " (C) LAL/IN2P3-CNRS Orsay , (C) DAPNIA/CEA Saclay (FRANCE)", &status);
220 fits_write_comment(FitsPtr(), "-----------------------------------------------------------", &status);
221 }
222 MoveAbsToHDU(1);
223 status = 0;
224 if (fptr_) fits_close_file(fptr_, &status);
225 if (status) {
226 cerr << " FitsInOutFile::Close - Error closing fits file !" << endl;
227 fits_report_error(stderr, status);
228 }
229}
230
[2864]231/*! \brief Closes the current fits file and uses \b fios file for subsequent operations.
232 \warning The fits file pointer is owned by the original FitsInOutFile object and
233 should not be closed as long as the current object (this) is being used.
234*/
[2820]235
[2864]236void FitsInOutFile::ShareFitsPtr(FitsInOutFile const& fios)
237{
238 Close();
239 fptr_ = fios.fptr_;
240 fname_ = fios.fname_;
241 mode_ = fios.mode_;
242 ownfptr = false;
243}
244
[2820]245/*-- Methode --*/
246float FitsInOutFile::cfitsioVersion()
247{
248 float ver;
249 fits_get_version(&ver);
250 return ver;
251}
252
253/*-- Methode --*/
254int FitsInOutFile::NbHDUs() const
255{
256 int status = 0;
257 int nbhdu = 0;
258 fits_get_num_hdus(FitsPtr() , &nbhdu, &status);
259 FitsCheckStatus(status, "FitsInOutFile::NbHDUs() Error: ");
260 return nbhdu;
261}
262
263/*-- Methode --*/
264int FitsInOutFile::CurrentHDU() const
265{
266 int status = 0;
267 int curhdu = 0;
268 fits_get_hdu_num(FitsPtr() , &curhdu);
269 return curhdu;
270}
271
272/*-- Methode --*/
273int FitsInOutFile::CurrentHDUType() const
274{
275 int status = 0;
276 int hdutyp = 0;
277 fits_get_hdu_type(FitsPtr() , &hdutyp, &status);
278 FitsCheckStatus(status, "FitsInOutFile::CurrentHDUType() Error: ");
279 return hdutyp;
280}
281
282/*-- Methode --*/
283string FitsInOutFile::CurrentHDUTypeStr() const
284{
285 int status = 0;
286 int hdutyp = 0;
287 fits_get_hdu_type(FitsPtr() , &hdutyp, &status);
288 if ( FitsCheckStatus(status, "FitsInOutFile::CurrentHDUTypeStr() Error: ") )
289 return "Unknown";
290 else {
291 if (hdutyp == IMAGE_HDU) return "IMAGE_HDU";
292 else if (hdutyp == BINARY_TBL) return "BINARY_TBL";
293 else if (hdutyp == ASCII_TBL) return "ASCII_TBL";
294 else return "Unknown";
295 }
296}
297
298/*-- Methode --*/
299int FitsInOutFile::MoveAbsToHDU(int hdunum)
300{
301 int status = 0;
302 int hdutyp = 0;
303 fits_movabs_hdu(FitsPtr() , hdunum, &hdutyp, &status);
304 FitsCheckStatus(status, "FitsInOutFile::MoveAbsToHDU Error: ");
305 return hdutyp;
306}
307
308/*-- Methode --*/
309int FitsInOutFile::MoveRelToHDU(int hdunum)
310{
311 int status = 0;
312 int hdutyp = 0;
313 fits_movrel_hdu(FitsPtr() , hdunum, &hdutyp, &status);
314 FitsCheckStatus(status, "FitsInOutFile::MoveRelToHDU Error: ");
315 return hdutyp;
316}
317
318/*-- Methode --*/
319int FitsInOutFile::MoveToNextHDU()
320{
321 if (CurrentHDU() < NbHDUs())
322 return MoveRelToHDU(1);
323 else return -1;
324}
325
326/*-- Methode --*/
327void FitsInOutFile::CreateImageHDU(int bitpix, int naxis, long* naxes)
328{
329 int status = 0;
330 fits_create_img(fptr_, bitpix, naxis, naxes, &status);
331 FitsCheckStatus(status,"FitsInOutFile::CreateImageHDU() Error: ");
332 return;
333}
334
335/*-- Methode --*/
336 /*!
337 See cfitsio function fits_get_img_param() for more information
338 naxis : input=max naxes dimension / out=image dimension
339 Rc : return the image type (bitpix)
340 */
341int FitsInOutFile::GetImageHDUInfo(int& naxis, long* naxes) const
342{
343 int status = 0;
344 int maxdim = naxis;
345 int bitpix = 0;
346 fits_get_img_param(fptr_, maxdim, &bitpix, &naxis, naxes, &status);
347 FitsCheckStatus(status, "FitsInOutFile::GetImageHDUInfo() Error: ");
348 return bitpix;
349}
350
351/*-- Methode --*/
352long FitsInOutFile::GetNbRows() const
353{
354 int status = 0;
355 long nbrow = 0;
356 fits_get_num_rows(FitsPtr() , &nbrow, &status);
357 FitsCheckStatus(status, "FitsInOutFile::GetNbRows() Error: " );
358 return nbrow;
359}
360
361/*-- Methode --*/
362int FitsInOutFile::GetNbCols() const
363{
364 int status = 0;
365 int nbcol = 0;
366 fits_get_num_cols(FitsPtr() , &nbcol, &status);
367 FitsCheckStatus(status, "FitsInOutFile::GetNbCols() Error: ");
368 return nbcol;
369}
370
371/*-- Methode --*/
372/*!
373 Create a binary or ascii table - See cfitsio routine fits_create_tbl for more information.
374 \param extname : extension name. NextExtensionName() will be used if extname == NULL or extname == "".
375 \param ncols : Number of columns
376 \param ttype : Column names
377 \param tform : Column data types J / V / K / E / D ...
378 \param tunit : Column units
379*/
380void FitsInOutFile::CreateTable(int tbltyp, const char * extname, int ncols,
381 char * ttype[], char * tform[],
382 char * tunit[], long ininr)
383{
384 int status = 0;
385
386 char * extn;
387 if ( (extname != NULL) && (extname[0] != '\0') ) extn = const_cast<char *>(extname);
388 else extn = const_cast<char *>(next_extname_.c_str());
389
390 fits_create_tbl(FitsPtr(), tbltyp, ininr, ncols, ttype,
391 tform, tunit, extn, &status);
392 next_extname_ = "";
393 FitsCheckStatus(status, "FitsInOutFile::CreateTable() Error: ");
394 return;
395}
396
397/*-- Methode --*/
398/*!
399 Create a binary or ascii table - See cfitsio routine fits_create_tbl for more information.
400 number of columns specified by colnames.size()
401 \param extname : extension name
402 \param colnames : Column names
403 \param tform : Column data types J / V / K / E / D ...
404 \param tunit : Column units
405*/
406void FitsInOutFile::CreateTable(int tbltyp, const string & extname,
407 const vector<string> & colnames,
408 const vector<string> & tform,
409 const vector<string> & tunit,
410 long ininr)
411{
412 if ( (colnames.size() != tform.size() ) ||
413 (colnames.size() != tunit.size() ) )
414 throw SzMismatchError("FitsInOutFile::CreateTable(): different sizes for colnames,tform,tunit");
415
416 // On utilise les SegDataBlock<T> pour eviter d'avoir a gerer les new/delete
417 // en plus avec les exceptions ...
418 size_t kk;
419 int ncols = colnames.size();
420
421 SegDataBlock<const char *> colnm(colnames.size(), 1);
422 for(kk=0; kk<colnames.size(); kk++) colnm[kk] = colnames[kk].c_str();
423 SegDataBlock<const char *> tfm(tform.size(), 1);
424 for(kk=0; kk<tform.size(); kk++) tfm[kk] = tform[kk].c_str();
425 SegDataBlock<const char *> tun(tunit.size(), 1);
426 for(kk=0; kk<tunit.size(); kk++) tun[kk] = tunit[kk].c_str();
427
428 CreateTable(tbltyp, const_cast<char *>(extname.c_str()), ncols,
429 const_cast<char **>(colnm.GetSegment(0)),
430 const_cast<char **>(tfm.GetSegment(0)),
431 const_cast<char **>(tun.GetSegment(0)),
432 ininr);
433}
434
435/*-- Methode --*/
436/*!
437 Return number of columns in table (See fits_get_colname and fits_get_coltype for more information)
438 \param colnames : Column names
439 \param coltypes : Column data types ( TSTRING / TSHORT / TFLOAT / ... )
440 \param repcnt : Repeat count (for columns with vector data)
441 \param width : The width (in bytes) of a single element in a column
442
443*/
444long FitsInOutFile::GetColInfo(vector<string> & colnames,
445 vector<int> & coltypes,
446 vector<long> & repcnt,
447 vector<long> & width)
448{
449
450 int status = 0;
451
452 colnames.clear();
453 coltypes.clear();
454 width.clear();
455 repcnt.clear();
456
457 int colnum, typecode;
458 long repeat, colw;
459 int ncols = 0;
460 char colname[128]; // longueur max d'un nom de colonne
461
462 while (status != COL_NOT_FOUND) {
463 fits_get_colname(FitsPtr(), CASEINSEN, "*", colname, &colnum, &status);
464 if (status == COL_NOT_FOUND) break;
[2844]465 if ( (status != COL_NOT_UNIQUE) && (status != 0) ) {
[2820]466 char buff[32];
467 fits_get_errstatus(status, buff);
468 string msg = "FitsInOutFile::GetColInfo() Error(1): " ;
469 msg += buff;
470 throw FitsIOException(msg);
471 }
472 int sta2 = 0;
473 fits_get_coltype(FitsPtr(), colnum, &typecode, &repeat, &colw, &sta2);
474 FitsCheckStatus(sta2, "FitsInOutFile::GetColInfo() Error(2): ");
475
476 colnames.push_back(colname);
477 coltypes.push_back(typecode);
478 repcnt.push_back(repeat);
479 width.push_back(colw);
[2844]480 if (status == 0) break;
[2820]481 }
482 return colnames.size();
483}
484
485/*-- Methode --*/
486void FitsInOutFile::InsertColumn(int numcol, const char* colname, const char* fmt)
487{
488 int status = 0;
489 fits_insert_col(FitsPtr(), numcol, const_cast<char *>(colname),
490 const_cast<char *>(fmt), &status);
491 FitsCheckStatus(status, "FitsInOutFile::AddColumn() Error: ");
492
493 return;
494}
495
496/*-- Methode --*/
[2843]497/*!
498 Return the value associated to the keyword \b key in the header as a string.
499 If the keyword is not found in the fits header, an empty string is returned
500 and the \b nosk flag is set to true.
501*/
502string FitsInOutFile::KeyValue(string const & key, bool& nosk)
[2820]503{
[2843]504 nosk = false;
[2820]505 int status = 0;
506 char value[FLEN_VALUE], comm[FLEN_COMMENT];
507 fits_read_key(FitsPtr(), TSTRING, const_cast<char *>(key.c_str()), value, comm, &status);
[2843]508 if (status == KEY_NO_EXIST) {
509 nosk = true;
510 return "";
511 }
[2820]512 FitsCheckStatus(status, "FitsInOutFile::KeyValue() Error: ");
513 return value;
514}
515
516/*-- Methode --*/
[2932]517/*!
518 Read the current fits header information as pairs of '(keyword,value)' appended
519 to the DVList object \b dvl.
520 \param dvl : DVList object containing filled with (keyword,value) pairs.
521 \param stripkw : if true (default), remove leading and trailing spaces from keyword
[2937]522 \param keepstkey : if true , keep keys of type TYP_STRUC_KEY
[2932]523*/
524int FitsInOutFile::GetHeaderRecords(DVList& dvl, bool stripkw, bool keepstkey)
[2820]525{
526 int status = 0;
527 int nkeys = 0;
528 fits_get_hdrspace(FitsPtr(), &nkeys, NULL, &status);
529 FitsCheckStatus(status, "FitsInOutFile::GetHeaderRecords() Error(1): ");
530
531 char record[FLEN_CARD], value[FLEN_VALUE], comm[FLEN_COMMENT];
532 string comment;
533 int nok = 0;
534 for(int kk=1; kk<=nkeys; kk++) {
535 status = 0;
536 fits_read_record(FitsPtr(), kk, record, &status);
537 FitsCheckStatus(status, "FitsInOutFile::GetHeaderRecords() Error(2): ");
538 int kclas = fits_get_keyclass(record);
[2932]539 if ( (!keepstkey && (kclas == TYP_STRUC_KEY))
540 || (kclas == TYP_NULL_KEY) ) continue;
[2820]541 int len = 0;
542 status = 0;
543 fits_get_keyname(record, value, &len, &status);
544 if (status) continue;
[2932]545 if (stripkw) strip(value, 'B', ' ');
[2820]546 string keyname = value;
547 status = 0;
548 fits_parse_value(record, value, comm, &status);
549 if (status) continue;
550 if (kclas == TYP_COMM_KEY) {
551 if (comment.length() > 0) comment += '\n';
552 comment += value;
553 continue;
554 }
555 char ktyp;
556 status = 0;
557 fits_get_keytype(value, &ktyp, &status);
558 if (status) continue;
559 switch (ktyp) {
560 case 'C' :
561 case 'L' : // Il faudra traiter le cas des nb complexes
562 case 'X' : // idem pour les valeurs logiques
[2932]563 dvl.SetS(keyname, value);
[2820]564 break;
565 case 'I' :
566 dvl.SetI(keyname, atoi(value));
567 break;
568 case 'F' :
569 dvl.SetD(keyname, atof(value));
570 break;
571 }
572 if (strlen(comm) > 0) {
573 string scom = comm;
574 dvl.SetComment(keyname, scom);
575 }
576 nok++;
577 }
578 if (comment.length() > 0) dvl.Comment() = comment;
579 return nok;
580}
581
582/*-- Methode --*/
583void FitsInOutFile::WriteKey(const char * kname, MuTyV const & mtv,
584 const char *comment)
585{
586 CheckFitsPtr(FitsPtr());
587 char keyname[FLEN_KEYWORD], comm[FLEN_COMMENT], sval[FLEN_VALUE];
588 long lval;
589 double dval;
590 string s;
591
592 keyname[0] = '\0';
593 strncpy(keyname, kname, FLEN_KEYWORD); keyname[FLEN_KEYWORD-1] = '\0';
594 comm[0] = '\0';
595 if (comm != NULL)
596 strncpy(comm, comment, FLEN_COMMENT); comm[FLEN_COMMENT-1] = '\0';
597 int status = 0;
598 switch (mtv.Type()) {
599 case MuTyV::MTVInteger :
600 lval = mtv.GetIntPart();
601 fits_write_key(FitsPtr(), TLONG, keyname, &lval, comm, &status);
602 break;
603 case MuTyV::MTVFloat :
604 dval = mtv.GetRealPart();
605 fits_write_key(FitsPtr(), TDOUBLE, keyname, &dval, comm, &status);
606 break;
607 case MuTyV::MTVString :
608 strncpy(sval, mtv.GetStringPointer()->c_str(), FLEN_VALUE);
609 keyname[FLEN_VALUE-1] = '\0';
610 fits_write_key(FitsPtr(), TSTRING, keyname, sval, comm, &status);
611 break;
612 default :
613 s = (string)mtv;
614 strncpy(sval, s.c_str(), FLEN_VALUE);
615 keyname[FLEN_VALUE-1] = '\0';
616 fits_write_key(FitsPtr(), TSTRING, keyname, sval, comm, &status);
617 break;
618 }
619 FitsCheckStatus(status, "FitsInOutFile::WriteKey() Error: ");
620 return;
621}
622
623/*-- Methode --*/
624int FitsInOutFile::WriteHeaderRecords(DVList & dvl)
625{
626
627 CheckFitsPtr(FitsPtr());
628 int status = 0;
629 DVList::ValList::const_iterator it;
630 for(it = dvl.Begin(); it != dvl.End(); it++)
631 WriteKey( (*it).first, (*it).second.elval, (*it).second.elcomm);
632 // Ecriture commentaires
633 return 0;
634
635}
636
637/*-- Methode --*/
638void FitsInOutFile::Print(ostream& os, int lev) const
639{
640 string mode;
641 if (mode_ == Fits_Create) mode = "Create";
642 else if (mode_ == Fits_RO) mode = "ReadOnly";
643 else mode = "ReadWrite";
644 os << " FitsInOutFile(FileName= " << fname_ << " Mode="
645 << mode << ") fitsioVers= " << cfitsioVersion() << endl;
646 os << " TotalNumberHDU= " << NbHDUs() << " CurrentHDU: Num= "
647 << CurrentHDU() << " Type= " << CurrentHDUTypeStr() << endl;
648
649 return;
650}
651
652
Note: See TracBrowser for help on using the repository browser.