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

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

Ajout constructeur de copie (pas parfait) pour FitsInOutFile + modifs classes FitsFile/FitsInFile/FitsOutFile pour heriter de FitsInOutFile avec constructeur a partir de FitsInOutFile - Reza 20/12/2005

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