source: Sophya/trunk/SophyaExt/FitsIOServer/fitsfile.cc@ 2197

Last change on this file since 2197 was 2197, checked in by lemeur, 23 years ago

toilette d'ete : rationalisation de types...

File size: 68.2 KB
RevLine 
[949]1#include "machdefs.h"
2#include <stdlib.h>
[839]3#include "fitsfile.h"
4#include "pexceptions.h"
5#include "strutil.h"
[903]6#include "anydataobj.h"
7#include "fitsspherehealpix.h"
[1136]8
[1371]9/*!
10 \defgroup FitsIOServer FitsIOServer module
11 This module contains classes which handle FITS format I/O for
12 SOPHYA objects. This module uses cfitsio library.
13*/
[1136]14
[1359]15void BnTblLine::setFormat(int dc, int fc, int ic, int lc, int bc,int cc, vector<string> names)
[1218]16 {
[1359]17 int nbcols = dc + fc + ic + cc + lc + bc;
[1218]18 int maxName = names.size();
19 if (nbcols != maxName)
20 {
21 cout << " WARNING: BnTblLine:: length of vector of column names not equal to total number of columns" << endl;
22 maxName = nbcols < maxName ? nbcols : maxName;
23 }
24 ColName_ = vector<string>(nbcols);
25 for (int k=0; k < maxName; k++) ColName_[k] = names[k];
26 if (dc >0) ddata_ = vector<double>(dc);
27 if (fc >0) fdata_ = vector<float>(fc);
[2197]28 if (ic >0) idata_ = vector<int>(ic);
[1359]29 if (lc >0) ldata_ = vector<long>(lc);
30 if (bc >0) bdata_ = vector<unsigned char>(bc);
[2197]31 if (cc >0) cdata_ = vector<string>(cc);
[1218]32 }
33
34bool BnTblLine::sameFormat(const BnTblLine& btl) const
35 {
[1359]36 if (btl.ddata_.size() == ddata_.size() && btl.fdata_.size() == fdata_.size() && btl.idata_.size() == idata_.size() && btl.cdata_.size() == cdata_.size() && btl.ldata_.size() == ldata_.size() && btl.bdata_.size() == bdata_.size()) return true;
[1218]37 else return false;
38 }
39
40void BnTblLine::Print()
41 {
42 int k;
43 cout << " ********* ligne ************* " << endl;
44 cout << " *** noms de variables " << endl;
45 for (k=0; k < ColName_.size(); k++) cout << ColName_[k] << " ";
46 cout << endl;
47 cout << " *** variables doubles " << endl;
48 for (k=0; k < ddata_.size(); k++) cout << ddata_[k] << " ";
49 cout << endl;
50 cout << " *** variables float " << endl;
51 for (k=0; k < fdata_.size(); k++) cout << fdata_[k] << " ";
52 cout << endl;
53 cout << " *** variables int " << endl;
54 for (k=0; k < idata_.size(); k++) cout << idata_[k] << " ";
55 cout << endl;
56 cout << " *** variables string " << endl;
57 for (k=0; k < cdata_.size(); k++) cout << cdata_[k] << " ";
58 cout << endl;
[1359]59 cout << " *** variables long " << endl;
60 for (k=0; k < ldata_.size(); k++) cout << ldata_[k] << " ";
61 cout << endl;
62 cout << " *** variables byte " << endl;
63 for (k=0; k < bdata_.size(); k++) cout << (int)bdata_[k] << " ";
64 cout << endl;
[1218]65 cout << " ***************************** " << endl;
66 }
67
[2197]68FitsFile::BufferLine::BufferLine(const vector<FitsFile::FitsDataType>& types)
69{
[1218]70
71
[2197]72 int dc=0;
73 int fc=0;
74 int shc=0;
75 int ic=0;
76 int lc=0;
77 int cc=0;
78 int bc=0;
79 id_ = vector< pair<FitsFile::FitsDataType, int> >(types.size());
80 for (int k= 0; k < types.size(); k++)
81 {
82 switch( types[k] )
83 {
84 case FitsFile::FitsDataType_double :
85 {
86 id_[k] = pair<FitsFile::FitsDataType, int>(FitsFile::FitsDataType_double, dc);
87 dc++;
88 break;
89 }
90 case FitsFile::FitsDataType_float :
91 {
92 id_[k] = pair<FitsFile::FitsDataType, int>(FitsFile::FitsDataType_float, fc);
93 fc++;
94 break;
95 }
96 case FitsFile::FitsDataType_short :
97 {
98 id_[k] = pair<FitsFile::FitsDataType, int>(FitsDataType_short, shc);
99 shc++;
100 break;
101 }
102 case FitsFile::FitsDataType_int :
103 {
104 id_[k] = pair<FitsFile::FitsDataType, int>(FitsDataType_int, ic);
105 ic++;
106 break;
107 }
108 case FitsFile::FitsDataType_long :
109 {
110 id_[k] = pair<FitsFile::FitsDataType, int>(FitsFile::FitsDataType_long, lc);
111 lc++;
112 break;
113 }
114 case FitsFile::FitsDataType_byte :
115 {
116 id_[k] = pair<FitsFile::FitsDataType, int>(FitsFile::FitsDataType_byte, bc);
117 bc++;
118 break;
119 }
120 case FitsDataType_char :
121 {
122 id_[k] = pair<FitsFile::FitsDataType, int>(FitsFile::FitsDataType_char, cc);
123 cc++;
124 break;
125 }
126 default:
127 {
128 throw PException(" FitsFile::getHeaderWithSophyaObject() : unsupported FITS data type");
129 }
130 }
131 }
132
133 if (dc >0) ddata_ = vector<r_8>(dc);
134 if (fc >0) fdata_ = vector<r_4>(fc);
135 if (shc >0) shdata_ = vector<int_2>(shc);
136 if (ic >0) idata_ = vector<int_4>(ic);
137 if (lc >0) ldata_ = vector<int_8>(lc);
138 if (cc >0) cdata_ = vector<string>(cc);
139 if (bc >0) bdata_ = vector<unsigned char>(bc);
140}
141
142
143void FitsFile::BufferLine::Print() const
144{
145 cout << " impression de la ligne: " << endl;
146
147 cout << " doubles : " << endl;
148 for (int k=0; k< ddata_.size(); k++)
149 {
150 cout << ddata_[k] << " " ;
151 }
152 cout << endl;
153
154 cout << " floats : " << endl;
155 for (int k=0; k< fdata_.size(); k++)
156 {
157 cout << fdata_[k] << " " ;
158 }
159 cout << endl;
160
161 cout << " entiers courts: " << endl;
162 for (int k=0; k< shdata_.size(); k++)
163 {
164 cout << shdata_[k] << " " ;
165 }
166 cout << endl;
167 cout << " entiers : " << endl;
168 for (int k=0; k< idata_.size(); k++)
169 {
170 cout << idata_[k] << " " ;
171 }
172 cout << endl;
173
174 cout << " entiers longs : " << endl;
175 for (int k=0; k< ldata_.size(); k++)
176 {
177 cout << ldata_[k] << " " ;
178 }
179 cout << endl;
180
181 cout << " chaines carac. : " << endl;
182 for (int k=0; k< cdata_.size(); k++)
183 {
184 cout << cdata_[k] << " " ;
185 }
186 cout << endl;
187
188 cout << " bytes : " << endl;
189 for (int k=0; k< bdata_.size(); k++)
190 {
191 cout << (char)bdata_[k] << " " ;
192 }
193 cout << endl;
194
195
196}
197
[1218]198/*!
199 \class SOPHYA::FitsIOHandler
[1371]200 \ingroup FitsIOServer
[1218]201The class structure is analogous to Sophya-PPersist system :
202Each SOPHYA object XXX is associated with a object of class FITS_XXX
203 (inheriting from FitsFileHandler), to which input/output operations with FITS
204 files are delegated (through a class Hierarchy : FitsFile (virtual),
205 FitsInFile, FitsOutFile) . A typical example of use is the following :
206
207\verbatim
208 int m=... ;
209 SphereHEALPix<r_8> sphere1(m); // definition of the SOPHYA object
210 .... fill the sphere ....
211
212 FITS_SphereHEALPix<r_8> fits_sph1(sphere1);
213 // delegated object
214 fits_sph.Write("myfile.fits"); // writing on FITS file
215
216 FITS_SphereHEALPix<r_8> fits_sph2("myfile.fits");
217 // load a delegated object
218 // from FITS file
219 SphereHEALPix<r_8> sphere2=(SphereHEALPix<r_8>)fits_sph2;
220 // casting the delegated object
221 // into a SOPHYA object
222\endverbatim
223
224
225*/
226
227/*! \fn void SOPHYA::FitsIOHandler::Read(char flnm[],int hdunum)
228
229this method is called from inherited objects :
230
231opens a file 'flnm'
232
233gets parameters in extension-header (hdunum)
234
235calls the method 'ReadFromFits' from the inherited object
236*/
[1136]237void FitsIOHandler::Read(char flnm[],int hdunum)
[839]238{
[1136]239 FitsInFile ifts(flnm);
240 Read(ifts, hdunum);
[839]241}
[1218]242
243 /*! \fn void SOPHYA::FitsIOHandler::Read(FitsInFile& is, int hdunum)
244Read the data on extension hdunum (or primary header, if hdunum=1) from FitsInFIle. If hdunum is not addressed, , one reads the next extension, with respect to the current position.
245 */
[1136]246void FitsIOHandler::Read(FitsInFile& is, int hdunum)
247{
[1300]248 is.ReadHeader(hdunum);
[1136]249 ReadFromFits(is);
250}
251
252
[1218]253/*! \fn void SOPHYA::FitsIOHandler::Write(char flnm[])
254this method is called from inherited objects.
255
256for writing a new object in a new fits-extension :
257
[1234]258\warning By convention, primary header may contain fits-image data.
259For switching off this convention (i.e. to make sure that all data will be on fits-extensions) use the method :
[1218]260
261firstImageOnPrimaryHeader() (see below)
262
263calls the method 'WriteToFits' from the inherited object
264
265*/
[1193]266void FitsIOHandler::Write(char flnm[])
[1136]267
268{
[1231]269 FitsOutFile of(flnm, FitsFile::unknown);
[1136]270 Write(of);
271}
272
273void FitsIOHandler::Write(FitsOutFile& os)
274{
275 WriteToFits(os);
276}
277
278
279
[839]280
281FitsFile::~FitsFile()
282{
283 int status = 0;
[1175]284 if( fptr_ != NULL)
[903]285 {
286 fits_close_file(fptr_,&status);
[1175]287 // je ne fais pas delete fptr_, c'est la lib. fitsio qui a fait
288 // new...
[903]289 }
[1175]290 if( status ) printerror( status );
[839]291}
[903]292
[1136]293
294void FitsFile::printerror(int &status)
295 //*****************************************************/
296 //* Print out cfitsio error messages and exit program */
297 //*****************************************************/
[1045]298{
[1136]299 if( status )
300 {
301 fits_report_error(stderr,status);
302 throw IOExc("FitsFile:: error FITSIO status");
303 }
304 return;
305}
[903]306
[1136]307void FitsFile::printerror(int& status, char* texte)
308 //*****************************************************/
309 //* Print out cfitsio error messages and exit program */
310 //*****************************************************/
311{
312 // print out cfitsio error messages and exit program
313 // print error report
[1235]314 fits_report_error(stderr, status);
[1136]315 cout << " erreur:: " << texte << endl;
316 throw IOExc("FitsFile:: error FITSIO status");
317}
[1703]318void FitsFile::printerrorAndContinue(int& status, char* texte)
319 //*****************************************************/
320 //* Print out cfitsio error messages and exit program */
321 //*****************************************************/
322{
323 // print out cfitsio error messages and exit program
324 // print error report
325 fits_report_error(stderr, status);
326 cout << " erreur:: " << texte << endl;
327 // throw IOExc("FitsFile:: error FITSIO status");
328}
[1136]329
330void FitsFile::ResetStatus(int& status)
331{
332 fits_status_ = status;
333 status = 0;
[1235]334 fits_clear_errmsg();
[1136]335}
336
[1209]337string FitsFile::GetErrStatus(int status)
[1136]338{
339 char text[31];
340 fits_get_errstatus(status, text);
341 return string(text);
342}
343
[1218]344/*!
345 \class SOPHYA::FitsInFile
[1371]346 \ingroup FitsIOServer
[1246]347class for reading SOPHYA objects from FITS Format Files (uses cfitsio lib)
[1218]348*/
349
[1136]350FitsInFile::FitsInFile()
351{
352 InitNull();
353}
[1218]354
[1231]355FitsInFile::FitsInFile(string const & flnm)
[1136]356{
[1175]357 InitNull();
358 int status = 0;
[1231]359 fits_open_file(&fptr_,flnm.c_str(),READONLY,&status);
360 if( status ) printerror( status );
361}
362
363FitsInFile::FitsInFile(const char * flnm)
364{
365 InitNull();
366 int status = 0;
[1175]367 fits_open_file(&fptr_,flnm,READONLY,&status);
368 if( status ) printerror( status );
[1136]369}
370
371
372void FitsInFile::InitNull()
373{
[1300]374 imageDataType_ = FitsDataType_NULL;
[1045]375 naxis_ = 0;
376 nbData_ = 0;
377 nrows_ = 0;
378 nbcols_ = 0;
379 naxisn_.clear();
380 repeat_.clear();
381 noms_.clear();
382 taille_des_chaines_.clear();
383 dvl_.Clear();
[1978]384
385 dnull_ = 1.e-300;
386 fnull_ = 1.e-33;
387 inull_= 99999;
388 cnull_= string("xxx");
[1175]389
[1978]390
[1045]391}
392
[1218]393//////////////////////////////////////////////////////////
394// methods with general purpose
395/////////////////////////////////////////////////////////
[1045]396
[1136]397int FitsInFile::NbBlocks(char flnm[])
[903]398{
399 int status = 0;
400 int nbhdu = 0;
401 fitsfile* fileptr;
402 fits_open_file(&fileptr,flnm,READONLY,&status);
403 if( status ) printerror( status, "NbBlocks: erreur ouverture fichier" );
404 fits_get_num_hdus(fileptr, &nbhdu, &status);
405 fits_close_file(fileptr,&status);
406 return nbhdu;
407}
[1334]408int FitsInFile::NbBlocks()
409{
410 int status = 0;
411 int nbhdu = 0;
412 fits_get_num_hdus(fptr_, &nbhdu, &status);
413 return nbhdu;
414}
[903]415
[1231]416void FitsInFile::GetBlockType(char flnm[], int hdunum, FitsExtensionType& typeOfExtension, int& naxis, vector<int>& naxisn, FitsDataType& dataType, DVList& dvl )
[903]417{
418 int status = 0;
419 fitsfile* fileptr;
420 fits_open_file(&fileptr,flnm,READONLY,&status);
[1209]421 if( status ) printerror( status, "GetBlockType: erreur ouverture fichier" );
[903]422 // move to the specified HDU number
423 int hdutype = 0;
424 fits_movabs_hdu(fileptr,hdunum,&hdutype,&status);
[1209]425 if( status ) printerror( status,"GetBlockType: erreur movabs");
[903]426 if(hdutype == IMAGE_HDU)
427 {
[1231]428 typeOfExtension = FitsExtensionType_IMAGE;
[1300]429 GetImageParameters (fileptr, dataType, naxis, naxisn);
[903]430 }
431 else
432 if(hdutype == ASCII_TBL || hdutype == BINARY_TBL)
433 {
434 int nrows = 0;
435 vector<string> noms;
[1300]436 vector<FitsDataType> types;
[903]437 vector<int> taille_des_chaines;
[971]438 GetBinTabParameters(fileptr, naxis, nrows, naxisn, noms, types, taille_des_chaines);
439 int k;
440 for (k=0; k< naxisn.size(); k++) naxisn[k] *= nrows;
[903]441 if(hdutype == ASCII_TBL)
442 {
[1231]443 typeOfExtension = FitsExtensionType_ASCII_TBL;
444 dataType = FitsDataType_ASCII;
[903]445 }
446 else
447 {
[1231]448 typeOfExtension = FitsExtensionType_BINARY_TBL;
[1300]449 dataType = types[0];
[903]450 }
451 }
452 else
453 {
454 cout << " hdutype= " << hdutype << endl;
[1209]455 throw IOExc("FitsFile::GetBlockType: this HDU type is unknown");
[903]456 }
457
[971]458 KeywordsIntoDVList(fileptr, dvl, hdunum);
[903]459 fits_close_file(fileptr,&status);
460}
461
[1136]462
[1300]463void FitsInFile::ReadHeader(int hdunum)
[1045]464{
[1300]465 // InitNull();
[1045]466 int status = 0;
[1334]467 if (hdunum<0)
468 {
[1703]469 throw PException(" FitsInFile::ReadHeader : hdu number must be not negative");
[1334]470 }
[1234]471 if (hdunum != 0 ) hdunum_ = hdunum;
472
473 // si le numero de header non precise
474 else
[1045]475 {
[1234]476 // si c'est le premier objet a lire
477 if (hdunum_ == 0)
[1045]478 {
[1234]479 // on calcule le numero de header a lire
[1246]480 if (imageOnPrimary_ == true ) hdunum_ = 1;
[1234]481 else hdunum_ = 2;
[1045]482 }
[1234]483 // sinon objet suivant
484 else hdunum_++;
[1045]485 }
[1771]486 getHeaderWithSophyaObject();
[1334]487 if ( hdutype_ == FitsExtensionType_NULL )
488 {
489 if (hdunum == 0 && hdunum_ == 1)
490 {
491 hdunum_++;
[1771]492 getHeaderWithSophyaObject();
[1334]493 }
494 else
495 {
496 cout << " WARNING (FitsInFile::ReadHeader) : no SOPHYA object on HDU number : " << hdunum_ << endl;
497 }
498 }
[1418]499 if ( hdutype_ == FitsExtensionType_EOF )
500 {
501 throw PException("FitsFile::ReadHeader, attempt to read through EOF");
502 }
[1045]503}
504
[1354]505string FitsInFile::getStringKeyword(int hdunum, string keyw, int& retStatus)
506{
507 string s;
508 retStatus = 0;
509 int status = 0;
510 if (hdunum != hdunum_ )
511 {
512 int hdutype;
513 fits_movabs_hdu(fptr_,hdunum,&hdutype,&status);
514 }
515
516 char value[FLEN_VALUE];
517 char* keyname= const_cast<char*>(keyw.c_str());
518 fits_read_key_str(fptr_,keyname,value,NULL,&status);
519 if (status == 0)
520 s = string(value);
521 else retStatus = status;
522 if (hdunum != hdunum_ )
523 {
524 int hdutype;
525 if (hdunum_ != 0)
526 fits_movabs_hdu(fptr_,hdunum_,&hdutype,&status);
527 else fits_movabs_hdu(fptr_,1,&hdutype,&status);
528
529 }
530 return s;
531}
532bool FitsInFile::hasKeyword(int hdunum, string keyw)
[1353]533 {
534 bool has=false;
535 int status = 0;
536 if (hdunum != hdunum_ )
537 {
538 int hdutype;
539 fits_movabs_hdu(fptr_,hdunum,&hdutype,&status);
540 }
[1218]541
[1353]542 char value[FLEN_VALUE];
543 char* keyname= const_cast<char*>(keyw.c_str());
544 fits_read_keyword(fptr_,keyname,value,NULL,&status);
545 if (status == 0)
546 has = true;
547 else
548 if (status == KEY_NO_EXIST ) status =0;
549 else fits_report_error(stderr,status);
550 if (hdunum != hdunum_ )
551 {
552 int hdutype;
553 if (hdunum_ != 0)
554 fits_movabs_hdu(fptr_,hdunum_,&hdutype,&status);
555 else fits_movabs_hdu(fptr_,1,&hdutype,&status);
556
557 }
558 return has;
559 }
560
[1771]561void FitsInFile::GetKeywordsFromHeader (int hdunum, list<FitsKeyword>& mots_cles) const
562{
563 int status = 0;
564 int hdutype;
565 fits_movabs_hdu(fptr_,hdunum,&hdutype,&status);
566 if( status ) fits_report_error(stderr,status);
567
568 // get number of keywords
569 int nkeys,keypos;
570 fits_get_hdrpos(fptr_, &nkeys, &keypos,&status);
571 if( status ) fits_report_error(stderr,status);
572 // shift with the number of mandatory keywords
573 int num= 0;
574 // if primary header
575 if (hdunum == 1)
576 {
577 // read NAXIS
578 int naxis=0;
579 fits_read_key(fptr_,TINT,"NAXIS",&naxis,NULL,&status);
580 // number of mandatory keywords
581 num = naxis+3;
582 }
583 // extensions
584 else
585 {
586 if (hdutype == IMAGE_HDU)
587 {
588 // read NAXIS
589 int naxis=0;
590 fits_read_key(fptr_,TINT,"NAXIS",&naxis,NULL,&status);
591 // number of mandatory keywords
592 num = naxis+5;
593 }
594 else
595 if(hdutype == ASCII_TBL || hdutype == BINARY_TBL)
596 {
597 // number of mandatory keywords
598 num = 8;
599 }
600 }
601 int j;
602 char keyname[LEN_KEYWORD];
603 char value[FLEN_VALUE];
604 char comment[FLEN_COMMENT];
605 for(j = num+1; j <= nkeys; j++)
606 {
607 char dtype;
608 fits_read_keyn(fptr_,j,keyname,value,comment,&status);
609 if(status)
610 {
611 fits_report_error(stderr,status);
612 status=0;
613 }
614 string kn(keyname);
615 string cm(comment);
616 string val(value);
617 FitsKeyword kw(kn, val, cm);
618 mots_cles.push_back(kw);
619 }
620 if (hdunum_ > 0) fits_movabs_hdu(fptr_,hdunum_,&hdutype,&status);
621
622}
[1300]623void FitsInFile::GetImageParameters (fitsfile* fileptr,FitsDataType& dataType,int& naxis,vector<int>& naxisn)
[1218]624{
625 int hdunum=0;
[1334]626 // cout << " Reading a FITS image in HDU : " << fits_get_hdu_num(fileptr,&hdunum) << endl;
[1218]627 int status= 0;
628
629 // bits per pixels
[1300]630 int bitpix=0;
[1218]631 fits_read_key(fileptr,TINT,"BITPIX",&bitpix,NULL,&status);
632 if( status ) printerror( status );
[1300]633 if(bitpix == DOUBLE_IMG) dataType = FitsDataType_double;
634 else if(bitpix == FLOAT_IMG) dataType = FitsDataType_float;
635 else if(bitpix == LONG_IMG || bitpix == SHORT_IMG ) dataType = FitsDataType_int;
636 else if (bitpix == BYTE_IMG) dataType = FitsDataType_char;
637 else
638 {
639 cout << " bitpix= " << bitpix << endl;
640 throw PException(" FitsFile::GetImageParameters : unsupported FITS data type");
641 }
[1218]642
643 // number of dimensions in the FITS array
644 naxis= 0;
645 fits_read_key(fileptr,TINT,"NAXIS",&naxis,NULL,&status);
646 if( status ) printerror( status );
647 // read the NAXISn keywords to get image size
648 long* naxes = new long[naxis] ;
649 int nfound;
650 fits_read_keys_lng(fileptr,"NAXIS",1,naxis,naxes,&nfound,&status);
651 if( status ) printerror( status );
652 if (nfound != naxis )
653 cout << " WARNING : " << nfound << " axes found, expected naxis= " << naxis << endl;
654 int k;
655 for (k=0; k<naxis; k++)
656 {
657 naxisn.push_back( (int)naxes[k] );
658 }
659 delete [] naxes;
660}
661
662
663
664
665 /*! \fn DVList SOPHYA::FitsInFile::DVListFromPrimaryHeader() const
666
667 \return the keywords of primary header in a DVList
668
669*/
[1143]670DVList FitsInFile::DVListFromPrimaryHeader() const
671 {
672 int status;
673 DVList dvl;
674 KeywordsIntoDVList(fptr_, dvl, 1);
675 int hdutype = 0;
676 if (hdunum_ > 0) fits_movabs_hdu(fptr_,hdunum_,&hdutype,&status);
677 return dvl;
678 }
[1136]679
[1771]680void FitsInFile::getHeaderWithSophyaObject()
[971]681{
[1300]682 // si hdunum_ > 1 lit le header correspondant
683 // si hdunum_ = 1 se positionne au (et lit le) premier header qui
684 // contient reellement un objet
[1234]685 int status=0;
686 if (hdunum_ < 1) throw PException(" attempt to read hdunum < 1");
[1300]687 InitNull();
[1234]688 if (hdunum_ == 1)
[839]689 {
[1234]690 // presence of image ?
691 int naxis= 0;
692 fits_read_key(fptr_,TINT,"NAXIS",&naxis,NULL,&status);
693 if( status ) printerror( status );
694 if (naxis > 0 ) // there is an image
695 {
[1334]696 hdutype_ = FitsExtensionType_IMAGE;
[1300]697 GetImageParameters (fptr_, imageDataType_, naxis_, naxisn_);
[1234]698 nbData_ = 1;
699 int k;
700 for (k=0; k<naxis_; k++) if (naxisn_[k] > 0) nbData_ *= naxisn_[k];
701 KeywordsIntoDVList(fptr_, dvl_,hdunum_);
702 }
703 else
704 {
[1334]705 hdutype_ = FitsExtensionType_NULL;
706 KeywordsIntoDVList(fptr_, dvl_,hdunum_);
[1234]707 }
[839]708 }
[1234]709 else
[839]710 {
[1234]711 int hdutype;
712 fits_movabs_hdu(fptr_,hdunum_,&hdutype,&status);
[1334]713
714 if( status )
[1234]715 {
[1334]716 if (status == END_OF_FILE)
717 {
718 hdutype_= FitsExtensionType_EOF;
719 status =0;
720 return;
721 }
722 else
723 {
[1771]724 cout << "WARNING (FitsInFile::getHeaderWithSophyaObject) : error during movabs" << endl;
[1334]725 hdutype_= FitsExtensionType_ERROR;
726 status =0;
727 return;
728 }
729 // printerror( status,":FitsInFile::getHeader : erreur movabs");
730 }
[2197]731
732
[1334]733 if(hdutype == IMAGE_HDU)
734 {
735 hdutype_= FitsExtensionType_IMAGE;
[1300]736 GetImageParameters (fptr_, imageDataType_, naxis_, naxisn_);
[1234]737 nbData_ = 1;
738 int k;
739 for (k=0; k<naxis_; k++) if (naxisn_[k] > 0) nbData_ *= naxisn_[k];
740 KeywordsIntoDVList(fptr_, dvl_,hdunum_);
741 }
[1334]742 else if(hdutype == ASCII_TBL)
[1234]743 {
[1334]744 hdutype_= FitsExtensionType_ASCII_TBL;
[1234]745 GetBinTabParameters(fptr_,nbcols_, nrows_,repeat_, noms_, types_, taille_des_chaines_);
746 KeywordsIntoDVList(fptr_, dvl_, hdunum_);
747 }
[1334]748 else if(hdutype == BINARY_TBL)
749 {
750 hdutype_= FitsExtensionType_BINARY_TBL;
751 GetBinTabParameters(fptr_,nbcols_, nrows_,repeat_, noms_, types_, taille_des_chaines_);
752 KeywordsIntoDVList(fptr_, dvl_, hdunum_);
753 }
754 else
755 {
756 hdutype_= FitsExtensionType_NULL;
757 KeywordsIntoDVList(fptr_, dvl_, hdunum_);
758 }
[2197]759
[839]760 }
[2197]761 if (hdutype_ == FitsExtensionType_BINARY_TBL || hdutype_ == FitsExtensionType_ASCII_TBL)
762 {
763 bfl_ = BufferLine(types_);
764 }
[971]765}
[839]766
[1136]767
[1234]768void FitsInFile::moveToFollowingHeader()
769{
770 int status = 0;
771 hdunum_++;
[1771]772 getHeaderWithSophyaObject();
[1334]773 if ( hdutype_ == FitsExtensionType_NULL )
774 {
775 cout << " WARNING (FitsInFile::ReadHeader) : no SOPHYA object on HDU number : " << hdunum_ << endl;
776
777 }
[1234]778}
[1218]779
780
781
[1234]782
783
[1218]784/*! \fn int SOPHYA::FitsInFile::NbColsFromFits() const
785\return number of columns (return 1 if IMAGE)
786*/
[1136]787int FitsInFile::NbColsFromFits() const
[839]788{
[1334]789 if(hdutype_ == FitsExtensionType_BINARY_TBL) return nbcols_;
[971]790 else
[1334]791 if(hdutype_ == FitsExtensionType_ASCII_TBL || hdutype_ == FitsExtensionType_IMAGE) return 1;
[839]792 else
793 {
[1379]794 cout << " hdutype= " << (int) hdutype_ << endl;
[1334]795 throw PException("FitsFile::NbColsFromFits, HDU not supported");
[839]796 }
797}
798
[1218]799/*! \fn int SOPHYA::FitsInFile::NentriesFromFits(int nocol) const
800\return number of data in the current IMAGE extension on FITS file, or number
801 of data of column number 'nocol' of the current BINTABLE extension
802*/
[1136]803int FitsInFile::NentriesFromFits(int nocol) const
[839]804{
[1334]805 if(hdutype_ == FitsExtensionType_BINARY_TBL) return nrows_*repeat_[nocol];
[1136]806 else
[1334]807 if(hdutype_ == FitsExtensionType_ASCII_TBL) return nrows_;
[1136]808 else
[1334]809 if(hdutype_ == FitsExtensionType_IMAGE) return nbData_;
[1136]810 else
[839]811 {
[1379]812 cout << "hdutype= " << (int) hdutype_ << endl;
[1334]813 throw PException("FitsFile::NentriesFromFits, this HDU is not supported");
[839]814 }
815}
816
[1218]817/*! \fn char SOPHYA::FitsInFile::ColTypeFromFits(int nocol) const
818
819return a character denoting data type of column number 'nocol' in a BINTABLE :
820
821D : double
822
823E : float
824
825I : integer
826
827S : character string
828
829 */
830
[1300]831FitsFile::FitsDataType FitsInFile::ColTypeFromFits(int nocol) const
[839]832{
[1334]833 if(hdutype_ != FitsExtensionType_ASCII_TBL && hdutype_ != FitsExtensionType_BINARY_TBL)
[839]834 {
[1136]835 throw IOExc("FitsFile::TypeFromFits, this HDU is not an ASCII table nor a binary table");
[839]836 }
[1136]837 return types_[nocol];
[839]838}
[1218]839
840
841/*! \fn string SOPHYA::FitsInFile::ColNameFromFits(int nocol) const
842
843\return name of the column number 'nocol' of the current BINTABLE extension
844 */
845
[1136]846string FitsInFile::ColNameFromFits(int nocol) const
[839]847{
[1334]848 if(hdutype_ != FitsExtensionType_ASCII_TBL && hdutype_ != FitsExtensionType_BINARY_TBL)
[1045]849 {
[1136]850 throw IOExc("FitsFile::TypeFromFits, this HDU is not an ASCII table nor a binary table");
[1045]851 }
[1136]852 return noms_[nocol];
[839]853}
854
[1218]855/*! \fn int DSOPHYA::FitsInFile::ColStringLengthFromFits(int nocol) const
856
857 \return number of characters of each data for the column number 'nocol' (if char* typed) of the current BINTABLE extension
858*/
859
[1136]860int FitsInFile::ColStringLengthFromFits(int nocol) const
[839]861{
[1334]862 if(hdutype_ != FitsExtensionType_ASCII_TBL && hdutype_ != FitsExtensionType_BINARY_TBL)
[1136]863 {
864 throw IOExc("FitsFile::TypeFromFits, this HDU is not an ASCII table nor a binary table");
865 }
866 int index=-1;
867 int k;
868 for (k=0; k<=nocol; k++)
869 {
[1300]870 if (types_[k] == FitsDataType_char) index++;
[1136]871 }
872 return taille_des_chaines_[index];
[839]873}
[1218]874
[2197]875const FitsFile::BufferLine& FitsInFile::GetBufferLine(long NoLine)
876{
877 int status= 0;
878 int anynul;
879 double dnull= dnull_;
880 float fnull= fnull_;
881 int inull= inull_;
882 char* cnull= const_cast<char*>(cnull_.c_str());
883 int ncol;
884 long nels=1;
885 double dval;
886 float fval;
887 int ival;
[1218]888
[2197]889 // pas d'entier de longueur superieure a 32 bits, pour cfitsio
890 int lval;
[1218]891
[2197]892 unsigned char usval;
893 int rang = 0;
894 int ccount = 0;
895 for (ncol=0; ncol<nbcols_; ncol++)
896 {
897 rang = bfl_.identificateur()[ncol].second;
898 // cout << " fitsfile : relecture col " << ncol << " type " << bfl_.identificateur()[ncol].first << " rang " << rang << endl;
899 switch (bfl_.identificateur()[ncol].first)
900 {
901 case FitsDataType_double :
902 fits_read_col(fptr_,TDOUBLE,ncol+1,NoLine+1,1,1,&dnull, &dval,&anynul,&status);
903 bfl_.r_8Array(rang) = (r_8)dval;
904 break;
905 case FitsDataType_float :
906 fits_read_col(fptr_,TFLOAT,ncol+1,NoLine+1,1,1,&fnull,&fval,&anynul,&status);
907 bfl_.r_4Array(rang) = (r_4)fval;
908 break;
909 case FitsDataType_short :
910 fits_read_col(fptr_,TSHORT,ncol+1,NoLine+1,1,1,&inull,&ival, &anynul,&status);
911 bfl_.int_2Array(rang) = (int_2)ival;
912 break;
913 case FitsDataType_int :
914 fits_read_col(fptr_,TINT,ncol+1,NoLine+1,1,1,&inull,&ival, &anynul,&status);
915 bfl_.int_4Array(rang) = (int_4)ival;
916 break;
917 case FitsDataType_long :
918 fits_read_col(fptr_,TLONG,ncol+1,NoLine+1,1,1,&inull,&lval, &anynul,&status);
919 bfl_.int_8Array(rang) = (int_8)lval;
920 break;
921 case FitsDataType_byte :
922 fits_read_col(fptr_,TBYTE,ncol+1,NoLine+1,1,1,&inull, &usval, &anynul,&status);
923 bfl_.u_charArray(rang) = usval;
924 break;
925 case FitsDataType_char :
926 char* chaine = new char[taille_des_chaines_[ccount++]];
927 fits_read_col(fptr_,TSTRING,ncol+1,NoLine+1,1,1,cnull,&chaine,&anynul,&status);
928 bfl_.stringArray(rang) = string(chaine);
929 break;
930 }
931 if (status)
932 {
933 ResetStatus(status);
934 break;
935 }
936 }
937 // cout << " fitsfile : ligne relue " << endl;
938 // bfl_.Print();
939 return bfl_;
940}
941
942
943
[1218]944/*! \fn void SOPHYA::FitsInFile::GetBinTabLine(int NoLine, double* ddata, float* fdata, int* idata, char ** cdata)
945
946Get the NoLine-th 'line' from the current BINTABLE extension on FITS file,
947 */
948
[1193]949void FitsInFile::GetBinTabLine(int NoLine, double* ddata, float* fdata, int* idata, char ** cdata)
[839]950{
951 int status= 0;
[1978]952 int anynul;
953 double dnull= dnull_;
954 float fnull= fnull_;
955 int inull= inull_;
956 char* cnull= const_cast<char*>(cnull_.c_str());
[1136]957 int dcount = 0.;
958 int fcount = 0.;
959 int icount = 0;
960 int ccount =0;
961 int ncol;
962 long nels=1;
[1499]963 int ligneAsolue = NoLine+1;
[1136]964 for (ncol=0; ncol<nbcols_; ncol++)
[861]965 {
[1499]966 int repetition =repeat_[ncol];
967 int ligneALire = ligneAsolue/repetition;
968 int premierElement = ligneAsolue-ligneALire*repetition;
969 if (premierElement != 0 )
970 {
971 ligneALire++;
972 }
973 else premierElement = repetition;
974
[1136]975 switch (types_[ncol])
976 {
[1300]977 case FitsDataType_double :
[1499]978 {
[1978]979 fits_read_col(fptr_,TDOUBLE,ncol+1,ligneALire,premierElement,1,&dnull,&ddata[dcount++],&anynul,&status);
[1136]980 break;
[1499]981 }
[2197]982 case FitsDataType_float :
983 {
984 fits_read_col(fptr_,TFLOAT,ncol+1,ligneALire,premierElement,1,&fnull,&fdata[fcount++],&anynul,&status);
985 break;
986 }
[1300]987 case FitsDataType_int :
[2197]988 {
989 fits_read_col(fptr_,TINT,ncol+1,ligneALire,premierElement,1,&inull,&idata[icount++],
[1978]990 &anynul,&status);
[2197]991 break;
992 }
[1499]993 case FitsDataType_long :
[2197]994 {
995 fits_read_col(fptr_,TLONG,ncol+1,ligneALire,premierElement,1,&inull,&idata[icount++], &anynul,&status);
996 break;
997 }
[1499]998 case FitsDataType_byte :
999 {
1000 unsigned char uschar = 0;
[1978]1001 fits_read_col(fptr_,TBYTE,ncol+1,ligneALire,premierElement,1,&inull,&uschar, &anynul,&status);
[1499]1002 idata[icount++] = (int)uschar;
[2197]1003 break;
[1499]1004 }
[1300]1005 case FitsDataType_char :
[2197]1006 {
1007 fits_read_col(fptr_,TSTRING,ncol+1,ligneALire,premierElement,1,cnull,&cdata[ccount++],&anynul,&status);
1008 break;
1009 }
1010 default:
1011 {
1012 throw PException(" FitsInFile::GetBinTabLine : unsupported FITS data type");
1013 }
[1136]1014 }
1015 if (status)
1016 {
1017 ResetStatus(status);
1018 break;
1019 }
[861]1020 }
[903]1021}
[839]1022
[1218]1023/*! \fn void SOPHYA::FitsInFile::GetBinTabLine(long NoLine, BnTblLine& ligne)
1024Get the NoLine-th 'line' from the current BINTABLE extension on FITS file,
1025*/
[1193]1026void FitsInFile::GetBinTabLine(long NoLine, BnTblLine& ligne)
1027{
1028 int status= 0;
[1978]1029 int anynul;
1030 double dnull= dnull_;
1031 float fnull= fnull_;
1032 int inull= inull_;
1033 char* cnull= const_cast<char*>(cnull_.c_str());
[1193]1034 int dcount = 0.;
1035 int fcount = 0.;
1036 int icount = 0;
1037 int ccount =0;
1038 int ncol;
1039 long nels=1;
1040 for (ncol=0; ncol<nbcols_; ncol++)
1041 {
1042 switch (types_[ncol])
1043 {
[1300]1044 case FitsDataType_double :
[2197]1045 {
1046 fits_read_col(fptr_,TDOUBLE,ncol+1,NoLine+1,1,1,&dnull,&ligne.ddata_[dcount++],&anynul,&status);
1047 break;
1048 }
[1300]1049 case FitsDataType_float :
[2197]1050 {
1051 fits_read_col(fptr_,TFLOAT,ncol+1,NoLine+1,1,1,&fnull,&ligne.fdata_[fcount++],&anynul,&status);
1052 break;
1053 }
[1300]1054 case FitsDataType_int :
[2197]1055 {
1056 fits_read_col(fptr_,TINT,ncol+1,NoLine+1,1,1,&inull,&ligne.idata_[icount++], &anynul,&status);
1057 break;
1058 }
[1359]1059 case FitsDataType_long :
[2197]1060 {
1061 fits_read_col(fptr_,TLONG,ncol+1,NoLine+1,1,1,&inull,&ligne.ldata_[icount++], &anynul,&status);
1062 break;
1063 }
[1359]1064 case FitsDataType_byte :
[2197]1065 {
1066 fits_read_col(fptr_,TBYTE,ncol+1,NoLine+1,1,1,&inull,&ligne.bdata_[icount++], &anynul,&status);
1067 break;
1068 }
[1300]1069 case FitsDataType_char :
[2197]1070 {
1071 char* chaine = new char[taille_des_chaines_[ccount]];
1072 fits_read_col(fptr_,TSTRING,ncol+1,NoLine+1,1,1,cnull,&chaine,&anynul,&status);
1073 ligne.cdata_[ccount++] = string(chaine);
1074 break;
1075 }
1076 default:
1077 {
1078 throw PException(" FitsInFile::GetBinTabLine : unsupported FITS data type");
1079 }
[1193]1080 }
1081 if (status)
1082 {
1083 ResetStatus(status);
1084 break;
1085 }
1086 }
1087}
1088
[2197]1089
1090
[1218]1091/*! \fn void SOPHYA::FitsInFile::GetBinTabLine(int NoLine, float* fdata)
1092
1093Get the NoLine-th float 'line' from the current BINTABLE extension on FITS file,
1094*/
[1136]1095void FitsInFile::GetBinTabLine(int NoLine, float* fdata)
[903]1096{
[1136]1097 int status= 0;
[1978]1098 int anynul;
1099 float fnull= fnull_;
[1136]1100 long nels=1;
1101 int ncol;
1102 for (ncol=0; ncol<nbcols_; ncol++)
[861]1103 {
[1978]1104 fits_read_col(fptr_,TFLOAT,ncol+1,NoLine+1,1,1,&fnull,&fdata[ncol],&anynul,&status);
[1136]1105 if (status)
[903]1106 {
[1136]1107 ResetStatus(status);
1108 break;
[903]1109 }
[1136]1110 }
1111}
[839]1112
[903]1113
[1218]1114/*! \fn void SPOPHYA::FitsInFile::GetBinTabFCol(double* valeurs,int nentries, int NoCol) const
1115
1116fill the array 'valeurs' with double data from the current BINTABLE extension on FITS file, from column number 'NoCol'
1117
1118\param <nentries> number of data to be read
1119*/
[1379]1120void FitsInFile::GetBinTabFCol(r_8* valeurs,int nentries, int NoCol) const
[839]1121 {
1122 int status= 0;
1123 int DTYPE;
1124 long repeat,width;
1125 fits_get_coltype(fptr_, NoCol+1,&DTYPE,&repeat,&width,&status);
1126 if( DTYPE != TDOUBLE)
1127 {
[1045]1128 if (DTYPE == TFLOAT) cout << " WARNING: reading double from float : conversion will be made by fitsio library" << endl;
1129 else
1130 throw IOExc("FitsFile::GetBinTabFCol, tentative de lecture non double");
[839]1131 }
1132 long nels=nentries;
[1978]1133 int anynul;
1134 double dnull= dnull_;
1135
[839]1136 fits_read_col(fptr_,TDOUBLE,NoCol+1,1,1,nels,&dnull,valeurs,
[1978]1137 &anynul,&status);
[1703]1138 if( status )
1139 {
1140 printerrorAndContinue( status,"erreur lecture de colonne" );
1141 }
[839]1142 }
1143
[1218]1144/*! \fn void SOPHYA::FitsInFile::GetBinTabFCol(float* valeurs,int nentries, int NoCol) const
1145
1146 same as previous method with float data
1147*/
[1379]1148void FitsInFile::GetBinTabFCol(r_4* valeurs,int nentries, int NoCol) const
[839]1149 {
1150 int status= 0;
1151 int DTYPE;
1152 long repeat,width;
1153 fits_get_coltype(fptr_, NoCol+1,&DTYPE,&repeat,&width,&status);
1154 if( DTYPE != TFLOAT)
1155 {
[1045]1156 if (DTYPE == TDOUBLE) cout << " WARNING: reading float from double : conversion will be made by fitsio library" << endl;
1157 else
1158 throw IOExc("FitsFile::GetBinTabFCol, tentative de lecture non float");
[839]1159 }
1160 long nels=nentries;
[1978]1161 int anynul;
1162 float fnull= fnull_;
[839]1163 fits_read_col(fptr_,TFLOAT,NoCol+1,1,1,nels,&fnull,valeurs,
[1978]1164 &anynul,&status);
[1703]1165 if( status ) printerrorAndContinue( status,"erreur lecture de colonne" );
[839]1166 }
[1136]1167
[1218]1168/*! \fn void SOPHYA::FitsInFile::GetBinTabFCol(int* valeurs,int nentries, int NoCol) const
1169
1170 same as previous method with int data
1171*/
1172
[1379]1173void FitsInFile::GetBinTabFCol(int_4* valeurs,int nentries, int NoCol) const
[839]1174 {
1175 int status= 0;
1176 int DTYPE;
1177 long repeat,width;
1178 fits_get_coltype(fptr_, NoCol+1,&DTYPE,&repeat,&width,&status);
[1752]1179 if( DTYPE != TLONG && DTYPE != TINT)
[839]1180 {
[1752]1181 throw IOExc("FitsFile::GetBinTabFCol, probleme de lecture d'entiers");
[839]1182 }
1183 long nels=nentries;
[1978]1184 int anynul;
1185 int inull= inull_;
[1752]1186
1187
1188
1189 // voir commentaire dans putColToFits()
[839]1190 fits_read_col(fptr_,TINT,NoCol+1,1,1,nels,&inull,valeurs,
[1978]1191 &anynul,&status);
[1703]1192 if( status ) printerrorAndContinue( status,"erreur lecture de colonne" );
[839]1193 }
[1136]1194
[1218]1195/*! \fn void SOPHYA::FitsInFile::GetBinTabFCol(char** valeurs, int nentries, int NoCol) const
1196
1197 same as previous method with char* data
1198*/
1199
[1136]1200void FitsInFile::GetBinTabFCol(char** valeurs, int nentries, int NoCol) const
[839]1201 {
1202 int status= 0;
1203 int DTYPE;
1204 long repeat,width;
1205 fits_get_coltype(fptr_, NoCol+1,&DTYPE,&repeat,&width,&status);
[1300]1206 if( DTYPE != TSTRING && DTYPE != TBYTE)
[839]1207 {
[1300]1208 throw IOExc("FitsFile::GetBinTabFCol, tentative de lecture non string");
[839]1209 }
1210 long nels=nentries;
[1978]1211 int anynul;
1212 char* cnull= const_cast<char*>(cnull_.c_str());
[839]1213 long frow=1;
1214 long felem=1;
1215 fits_read_col(fptr_,TSTRING,NoCol+1,frow,felem,nels,cnull,valeurs,
[1978]1216 &anynul,&status);
[1703]1217 if( status ) printerrorAndContinue( status,"erreur lecture de colonne" );
[839]1218 }
[1045]1219
[1218]1220/*! \fn void SOPHYA::FitsInFile::GetSingleColumn(double* map, int nentries) const
1221fill the array 'map' with double data from the current extension on FITS file.
1222If the extension is BINTABLE, the first column is provided.
1223
1224\param <nentries> number of data to be read
1225*/
[1379]1226void FitsInFile::GetSingleColumn(r_8* map, int nentries) const
[1136]1227{
1228 int status = 0;
[1334]1229 if(hdutype_ == FitsExtensionType_IMAGE)
[1045]1230 {
[1136]1231
[1300]1232 if(imageDataType_ != FitsDataType_double)
[1047]1233 {
[1136]1234 cout << " The data type on fits file is not double...";
1235 cout << " Conversion to double achieved by cfitsio lib" << endl;
[1047]1236 }
[1136]1237
[1978]1238 int anynul;
1239 double dnull= dnull_;
[1136]1240
1241 long nels= nentries;
[1978]1242 fits_read_img(fptr_,TDOUBLE,1,nels,&dnull,map,&anynul,&status);
[1136]1243 if( status ) printerror( status );
[1045]1244 }
[1136]1245 else
[1334]1246 if(hdutype_ == FitsExtensionType_ASCII_TBL || hdutype_ == FitsExtensionType_BINARY_TBL)
[1136]1247 {
1248 GetBinTabFCol(map,nentries, 0);
1249 }
1250 else
1251 {
[1379]1252 cout << " hdutype= " << (int) hdutype_ << endl;
[1334]1253 throw IOExc("FitsFile::GetSingleColumn, this HDU is unknown");
[1136]1254 }
[1045]1255}
1256
[1218]1257/*! \fn void SOPHYA::FitsInFile::GetSingleColumn(float* map, int nentries) const
1258same as above with float data
1259*/
[1379]1260void FitsInFile::GetSingleColumn(r_4* map, int nentries) const
[1045]1261{
[1136]1262 int status = 0;
[1334]1263 if(hdutype_ == FitsExtensionType_IMAGE)
[1045]1264 {
[1300]1265 if(imageDataType_ != FitsDataType_float)
[1047]1266 {
[1136]1267 cout << " The data type on fits file is not float ";
1268 cout << " Conversion to float achieved by cfitsio lib" << endl;
[1047]1269 }
[1978]1270 int anynul;
1271 float fnull= fnull_;
[1136]1272
1273 long nels= nentries;
[1978]1274 fits_read_img(fptr_,TFLOAT,1,nels,&fnull, map,&anynul,&status);
[1136]1275 if( status ) printerror( status );
[1045]1276 }
[839]1277 else
[1334]1278 if(hdutype_ == FitsExtensionType_ASCII_TBL || hdutype_ == FitsExtensionType_BINARY_TBL)
[1136]1279 {
1280 GetBinTabFCol(map,nentries, 0);
1281 }
[839]1282 else
1283 {
[1379]1284 cout << " hdutype= " << (int) hdutype_ << endl;
[1136]1285 throw IOExc("FitsFile::GetSingleColumn this HDU is unknown");
[839]1286 }
1287}
1288
[1218]1289/*! \fn void SOPHYA::FitsInFile::GetSingleColumn( int* map, int nentries) const
1290 same as above with int data
1291*/
[1379]1292void FitsInFile::GetSingleColumn( int_4* map, int nentries) const
[839]1293{
[1136]1294 int status = 0;
[1334]1295 if(hdutype_ == FitsExtensionType_IMAGE)
[839]1296 {
[1300]1297 if(imageDataType_ != FitsDataType_int)
[1136]1298 {
1299 cout << " The data type on fits file is not int ";
1300 cout << " Conversion to float achieved by cfitsio lib" << endl;
1301 }
[1978]1302 int anynul;
1303 float fnull= fnull_;
[1136]1304
1305 long nels= nentries;
[1978]1306 fits_read_img(fptr_,TINT,1,nels,&fnull,map,&anynul,&status);
[1136]1307 if( status ) printerror( status );
[839]1308 }
1309 else
[1334]1310 if(hdutype_ == FitsExtensionType_ASCII_TBL || hdutype_ == FitsExtensionType_BINARY_TBL)
[1136]1311 {
1312 GetBinTabFCol(map,nentries, 0);
1313 }
[839]1314 else
[1136]1315 {
[1379]1316 cout << " hdutype= " << (int) hdutype_ << endl;
[1136]1317 throw IOExc("FitsFile::GetSingleColumn this HDU is unknown");
1318 }
[839]1319}
1320
[1136]1321void FitsInFile::GetBinTabParameters(fitsfile* fileptr, int& nbcols, int& nrows,
[903]1322 vector<int>& repeat,
1323 vector<string>& noms,
[1300]1324 vector<FitsDataType>& types,
[903]1325 vector<int>& taille_des_chaines)
[839]1326{
1327 int status= 0;
[903]1328 int hdunum=0;
1329 int hdutype=0;
1330 fits_get_hdu_num(fileptr,&hdunum);
1331 fits_get_hdu_type(fileptr, &hdutype, &status);
1332
1333 if(hdutype != ASCII_TBL && hdutype != BINARY_TBL)
[839]1334 {
[903]1335 throw IOExc("FitsFile::GetBinTabParameters this HDU is not an ASCII table nor a binary table");
[839]1336 }
[1334]1337 // if(hdutype == ASCII_TBL)
1338 // cout << " Reading a FITS ascii table in HDU : " << hdunum << endl;
1339 // if(hdutype == BINARY_TBL)
1340 // cout << " Reading a FITS binary table in HDU : " << hdunum << endl;
[839]1341
1342 // get the number of columns
[903]1343 fits_get_num_cols(fileptr, &nbcols,&status);
[839]1344 if( status ) printerror( status );
1345
1346 // get the number of rows
1347 long naxis2= 0;
[903]1348 fits_get_num_rows(fileptr,&naxis2,&status);
[839]1349 if( status ) printerror( status );
[903]1350 nrows = (int)naxis2;
[839]1351
1352 // get the datatype, names and the repeat count
[903]1353 noms.clear();
1354 noms.reserve(nbcols);
1355 types.clear();
1356 types.reserve(nbcols);
1357 repeat.clear();
1358 repeat.reserve(nbcols);
1359 taille_des_chaines.clear();
[839]1360 char **ttype = new char*[nbcols];
[923]1361 int ii;
[1175]1362 //
1363 //
[923]1364 for (ii=0; ii < nbcols; ii++) ttype[ii]=new char[FLEN_VALUE];
[839]1365 int nfound;
[903]1366 fits_read_keys_str(fileptr, "TTYPE",1,nbcols,ttype,&nfound, &status);
[839]1367 if( status ) printerror( status,"erreur lecture des noms de colonne");
1368 int rept=0;
[1300]1369 if(hdutype == ASCII_TBL)
[839]1370 {
[1300]1371 for(ii = 0; ii < nbcols; ii++)
[839]1372 {
[1300]1373 int DTYPE;
1374 long width;
1375 long repete = 0;
1376 fits_get_coltype(fileptr,ii+1,&DTYPE,&repete,&width,&status);
1377 if( status ) printerror( status,"erreur lecture type de colonne");
1378 rept = repete;
1379 noms.push_back(string(ttype[ii]));
1380 switch (DTYPE)
1381 {
1382 case TDOUBLE :
1383 types.push_back(FitsDataType_double);
1384 break;
1385 case TFLOAT :
1386 types.push_back(FitsDataType_float);
1387 break;
1388 case TLONG :
[1359]1389 types.push_back(FitsDataType_long);
[1300]1390 break;
[2197]1391 case TINT :
[1300]1392 types.push_back(FitsDataType_int);
1393 break;
[2197]1394 case TSHORT :
1395 types.push_back(FitsDataType_short);
1396 break;
[1300]1397 case TSTRING :
1398 types.push_back(FitsDataType_char);
1399 taille_des_chaines.push_back(width);
1400 rept/=width;
1401 break;
1402 default :
1403 cout << " field " << ii+1 << " DTYPE= " << DTYPE << endl;
1404 throw IOExc("FitsFile::GetBinTabParameters, unsupported data type of field, for ASCII table");
1405 }
1406 repeat.push_back(rept);
[839]1407 }
[1136]1408 }
[1300]1409 else
1410 {
1411 for(ii = 0; ii < nbcols; ii++)
1412 {
1413 int DTYPE;
1414 long width;
1415 long repete = 0;
1416 fits_get_coltype(fileptr,ii+1,&DTYPE,&repete,&width,&status);
1417 if( status ) printerror( status,"erreur lecture type de colonne");
1418 rept = repete;
1419 noms.push_back(string(ttype[ii]));
1420 switch (DTYPE)
1421 {
1422 case TDOUBLE :
1423 types.push_back(FitsDataType_double);
1424 break;
1425 case TFLOAT :
1426 types.push_back(FitsDataType_float);
1427 break;
1428 case TLONG :
[1359]1429 types.push_back(FitsDataType_long);
[1300]1430 break;
1431 case TINT :
1432 types.push_back(FitsDataType_int);
1433 break;
1434 case TSHORT :
[2197]1435 types.push_back(FitsDataType_short);
[1300]1436 break;
1437 case TSTRING :
1438 types.push_back(FitsDataType_char);
1439 taille_des_chaines.push_back(width);
1440 rept/=width;
1441 break;
1442 case TBYTE :
[1359]1443 types.push_back(FitsDataType_byte);
[1300]1444 break;
1445 default :
1446 cout << " field " << ii+1 << " DTYPE= " << DTYPE << endl;
1447 throw IOExc("FitsFile::GetBinTabParameters, unsupported data type of field, for BINTABLE");
1448 }
1449 repeat.push_back(rept);
1450 }
1451 }
[1136]1452 for (ii=0; ii < nbcols; ii++) delete [] ttype[ii];
1453 delete [] ttype;
1454}
1455
1456void FitsInFile::KeywordsIntoDVList(fitsfile* fileptr, DVList& dvl, int hdunum)
1457{
1458 int status = 0;
1459 int hdutype;
1460 fits_movabs_hdu(fileptr,hdunum,&hdutype,&status);
1461 if( status ) printerror( status,":KeywordsIntoDVList : erreur movabs");
1462 // get number of keywords
1463 int nkeys,keypos;
1464 fits_get_hdrpos(fileptr,&nkeys,&keypos,&status);
1465 if( status ) printerror( status );
1466
1467 // put keywords in a DVList object
1468 char keyname[LEN_KEYWORD]= "";
1469 char strval[FLEN_VALUE]= "";
1470 char dtype;
1471 char card[FLEN_CARD];
1472 char *comkey = "COMMENT";
[1143]1473 char comment[FLEN_COMMENT];
[1136]1474
1475 // shift with the number of mandatory keywords
[1143]1476 // int num= 8;
1477 int num= 0;
1478 // primary header
1479 if (hdunum == 1)
1480 {
1481 // read NAXIS
1482 int naxis=0;
1483 fits_read_key(fileptr,TINT,"NAXIS",&naxis,NULL,&status);
1484 // number of mandatory keywords
1485 num = naxis+3;
1486 }
1487 // extensions
1488 else
1489 {
1490 if (hdutype == IMAGE_HDU)
1491 {
1492 // read NAXIS
1493 int naxis=0;
1494 fits_read_key(fileptr,TINT,"NAXIS",&naxis,NULL,&status);
1495 // number of mandatory keywords
1496 num = naxis+5;
1497 }
1498 else
1499 if(hdutype == ASCII_TBL || hdutype == BINARY_TBL)
1500 {
1501 // number of mandatory keywords
1502 num = 8;
1503 }
1504 }
[1136]1505 int j;
1506 for(j = num+1; j <= nkeys; j++)
1507 {
1508 fits_read_keyn(fileptr,j,card,strval,NULL,&status);
1509 if(status) printerror(status);
1510
1511 strncpy(keyname,card,LEN_KEYWORD-1);
1512 if(strncmp(keyname,comkey,LEN_KEYWORD-1) != 0 && strlen(keyname) != 0
1513 && strlen(strval) != 0)
1514 {
1515 fits_get_keytype(strval,&dtype,&status);
1516 if(status) printerror(status);
1517
1518 strip(keyname, 'B',' ');
1519 strip(strval, 'B',' ');
1520 strip(strval, 'B','\'');
1521
1522 switch( dtype )
1523 {
1524 case 'C':
[1143]1525 fits_read_key(fileptr,TSTRING,keyname,strval,comment,&status);
[1978]1526 if ( strncmp(keyname,"TTYPE",5) == 0 ||
1527 strncmp(keyname,"TFORM",5) == 0 ||
1528 strncmp(keyname,"TBCOL",5) == 0 ) break;
[1143]1529 dvl[keyname]= strval;
1530 dvl.SetComment(keyname, comment);
[1136]1531 break;
1532 case 'I':
1533 int ival;
[1143]1534 fits_read_key(fileptr,TINT,keyname,&ival,comment,&status);
[1136]1535 dvl[keyname]= (int_4) ival; // Portage mac DY
[1143]1536 dvl.SetComment(keyname, comment);
[1136]1537 break;
1538 case 'L':
1539 int ilog;
[1143]1540 fits_read_key(fileptr,TLOGICAL,keyname,&ilog,comment,&status);
[1136]1541 dvl[keyname]= (int_4) ilog;
[1143]1542 dvl.SetComment(keyname, comment);
[1136]1543 break;
1544 case 'F':
1545 double dval;
[1143]1546 fits_read_key(fileptr,TDOUBLE,keyname,&dval,comment,&status);
[1136]1547 dvl[keyname]= dval;
[1143]1548 dvl.SetComment(keyname, comment);
[1136]1549 break;
1550 }
1551
1552 }
[839]1553 }
[1978]1554 // dvl.Print();
[1136]1555}
1556
[1218]1557
1558/*!
1559 \class SOPHYA::FitsOutFile
[1371]1560 \ingroup FitsIOServer
[1218]1561 Class for loading SOPHYA objects from FITS Format Files (uses cfitsio lib)
1562*/
1563
[1136]1564FitsOutFile::FitsOutFile()
1565{
[1193]1566 InitNull();
[903]1567}
[839]1568
[1218]1569 /*! \fn SOPHYA::FitsOutFile::FitsOutFile(char flnm[], WriteMode wrm)
1570
1571\param <WriteMode> enum , WriteMode = clear -> if alreadyy exists, the file will be overwritten (else created) ; WriteMode = append -> further objects will be appended to the file if it exists (else : file created). WriteMode = unknown -> file created if does not exist, else : exception. (the last situation is the default)
1572
1573 */
[1231]1574
1575FitsOutFile::FitsOutFile(string const & flnm, WriteMode wrm)
[1136]1576{
[1231]1577 InitNull();
1578 openoutputfitsfile(flnm.c_str(), wrm);
1579}
[839]1580
[1231]1581FitsOutFile::FitsOutFile(const char * flnm, WriteMode wrm)
1582{
[1136]1583 InitNull();
[1231]1584 openoutputfitsfile(flnm, wrm);
1585}
1586
1587void FitsOutFile::openoutputfitsfile(const char * flnm, WriteMode wrm)
1588{
[1136]1589 int status = 0;
[839]1590
[1136]1591 // create new FITS file
[1183]1592 fits_create_file(&fptr_,flnm,&status);
1593 if( status )
[1136]1594 {
[1193]1595
1596 switch (wrm)
1597 {
[1183]1598 // si on veut ecrire a la fin de ce fichier
[1193]1599 case append :
[1183]1600 status = 0;
[1235]1601 fits_clear_errmsg();
[1183]1602 fits_open_file(&fptr_,flnm,READWRITE,&status);
1603 if( status )
1604 {
1605 cout << " error opening file: " << flnm << endl;
1606 printerror(status, "failure opening a file supposed to exist");
1607 }
1608 else cout << " file " << flnm << " opened, new objects will be appended " << endl;
1609 fits_get_num_hdus(fptr_, &hdunum_, &status);
1610 int hdutype;
1611 fits_movabs_hdu(fptr_,hdunum_,&hdutype,&status);
1612 if( status ) printerror( status,":FitsFile::WriteF : erreur movabs");
[1193]1613 break;
1614
1615 case clear :
[1183]1616 {
1617 status = 0;
[1235]1618 fits_clear_errmsg();
[1183]1619 char* newname = new char[strlen(flnm)+1];
1620 //
1621 newname[0] = '!';
1622 newname[1] = '\0';
1623 strcat(newname, flnm);
1624 fits_create_file(&fptr_,newname,&status);
[1193]1625 delete [] newname;
[1183]1626 if (status)
1627 {
1628 cout << " error opening file: " << flnm << endl;
1629 printerror(status, "unable to open file, supposed to exist");
1630 }
[1193]1631 else cout << " WARNING : file " << flnm << " is overwritten " << endl;
1632 break;
[1183]1633 }
[1193]1634 case unknown :
1635 printerror(status, " file seems already to exist");
1636 break;
[1183]1637
[1193]1638 }
[1136]1639 }
1640}
1641
1642
1643
[1218]1644/*! \fn void SOPHYA::FitsOutFile::makeHeaderImageOnFits(char type, int nbdim, int* naxisn, DVList &dvl)
1645
1646create an IMAGE header on FITS file.
1647\param <type> type of data (see method ColTypeFromFits)
1648\param <nbdim> number of dimensions : 1D, 2D, 3D etc. = NAXIS
1649\param <naxisn> array containind sizes of the different dimensions
1650*/
[1221]1651void FitsOutFile::makeHeaderImageOnFits(char type, int nbdim, int* naxisn, DVList* ptr_dvl)
[1136]1652{
1653 int status = 0;
1654 long naxis = nbdim;
1655 long* naxes = new long[nbdim];
[1246]1656 bool hdunfirst= (hdunum_ == 0);
1657 if (hdunfirst)
[1136]1658 {
[1143]1659 if (imageOnPrimary_ == false)
1660 {
[1234]1661 hdunum_ = 1;
[1143]1662 fits_create_img(fptr_,FLOAT_IMG,0,naxes,&status);
[1246]1663 }
[1136]1664 }
1665 int k;
1666 for (k=0; k< nbdim; k++) naxes[k] = (long)naxisn[k];
1667 if (type == 'D')
1668 fits_create_img(fptr_,DOUBLE_IMG,naxis,naxes,&status);
1669 else
1670 if (type == 'E')
1671 fits_create_img(fptr_,FLOAT_IMG,naxis,naxes,&status);
1672 else
1673 if (type == 'I')
1674 fits_create_img(fptr_,LONG_IMG,naxis,naxes,&status);
1675 else
1676 {
1677 cout << " type of data: " << type << endl;
1678 throw PException("FitsFile:::makeHeaderImageOnFits:unprogrammed type of data ");
1679 }
[1353]1680
[1246]1681 // on ajoute eventuellement un dvlist prepare et la doc SOPHYA
[1136]1682 hdunum_++;
[1246]1683 if (hdunfirst)
1684 {
1685 addDVListOnPrimary();
1686 writeSignatureOnFits(1);
1687 }
[1143]1688
[1353]1689 // header format FITS
1690
1691 writeAppendedHeaderOnFits();
1692
1693 // write supplementary keywords (from SOPHYA)
[1143]1694 // dvl.Print();
[1221]1695 if (ptr_dvl != NULL) addKeywordsOfDVList(*ptr_dvl);
[1143]1696
[1136]1697 delete [] naxes;
1698 if( status ) printerror( status, "erreur creation HDU IMAGE" );
1699
1700}
[1218]1701
1702
1703/*! \fn void SOPHYA::FitsOutFile::PutImageToFits(int nbData, double* map) const
1704
1705write double data from array 'map'on an IMAGE extension
1706\param <nbData> number of data to be written
1707*/
[1379]1708void FitsOutFile::PutImageToFits(int nbData, r_8* map) const
[1136]1709{
1710 int status = 0;
1711 long npix= nbData;
1712 fits_write_img(fptr_,TDOUBLE,1,npix,map,&status);
[1209]1713 if( status ) printerror( status, "erreur ecriture PutImageToFits" );
[1136]1714}
1715
[1218]1716/*! \fn void SOPHYA::FitsOutFile::PutImageToFits(int nbData, float* map) const
1717
1718same as previous method with float data
1719*/
[1379]1720void FitsOutFile::PutImageToFits(int nbData, r_4* map) const
[1136]1721{
1722 int status = 0;
1723 long npix= nbData;
1724 fits_write_img(fptr_,TFLOAT,1,npix, map,&status);
[1209]1725 if( status ) printerror( status, "erreur ecriture PutImageToFits" );
[1136]1726
1727}
[1218]1728
1729 /*! \fn void SOPHYA::FitsOutFile::PutImageToFits( int nbData, int* map) const
1730
1731 same as previous method with int data */
[1379]1732void FitsOutFile::PutImageToFits( int nbData, int_4* map) const
[1136]1733{
1734 int status = 0;
1735
1736 long npix= nbData;
1737 fits_write_img(fptr_,TINT,1,npix,map,&status);
[1209]1738 if( status ) printerror( status, "erreur ecriture PutImageToFits" );
[1136]1739}
1740
1741
1742
[1218]1743/*! \fn void SOPHYA::FitsOutFile::makeHeaderBntblOnFits( string fieldType, vector<string> Noms, int nentries, int tfields, DVList &dvl, string extname, vector<int> taille_des_chaines)
1744
1745create an BINTABLE header on FITS file.
1746\param <fieldType> array conta
1747ining characters denoting types of the different column (see method ColTypeFromFits)
1748\param <Noms> array of the names of columns
1749\param <nentries> number of data of each column
1750\param <tfields> number of columns
1751\param <dvl> a SOPHYA DVList containing keywords to be appended
1752\param <extname> keyword EXTNAME for FITS file
1753\param <taille_des_chaines> vector containing the number of characters of data for each char* typed column, with order of appearance in 'fieldType'
1754*/
[1300]1755void FitsOutFile::makeHeaderBntblOnFits(string fieldType, vector<string> Noms, int nentries, int tfields, DVList* ptr_dvl, string extname, vector<int> taille_des_chaines)
[839]1756{
[1209]1757 int k;
[839]1758 int status = 0;
1759 long nrows;
[1300]1760 // verifications de coherences
[1209]1761
[1193]1762 if (fieldType.length() != tfields)
[839]1763 {
[1193]1764 cout << " nombre de champs :" << tfields << "nombre de types: " << fieldType.length() << endl;
[1136]1765 throw ParmError("FitsFile:: fields and types don't match");
[839]1766
1767 }
[1209]1768 if (tfields > Noms.size())
1769 {
1770 cout << " WARNING: FitsOutFile::makeHeaderBntblOnFits, length of vector of column names not equal to total number of columns" << endl;
1771 for (k=0; k<(tfields-Noms.size()); k++) Noms.push_back( string(" "));
1772 }
1773
1774 // nombre de variables "chaines de caracteres"
1775 int nbString = 0;
1776 for (k=0; k<tfields;k++) if (fieldType[k] == 'A') nbString++;
1777 // coherence de la longueur du vecteur des tailles
1778 if (nbString > taille_des_chaines.size())
1779 {
1780 cout << " WARNING: FitsOutFile::makeHeaderBntblOnFits, length of vector of string lengths not equal to total number of columns" << endl;
1781 int strSz=0;
1782 for (k=0; k<taille_des_chaines.size(); k++) if ( taille_des_chaines[k] > strSz) strSz = taille_des_chaines[k];
1783 for (k=0; k<(nbString-taille_des_chaines.size()); k++) taille_des_chaines.push_back(strSz);
1784 }
[839]1785 char ** ttype= new char*[tfields];
1786 char ** tform= new char*[tfields];
1787 char largeur[FLEN_VALUE];
1788 int noColString=0;
[971]1789 for (k=0; k<tfields;k++)
[839]1790 {
1791 char format[FLEN_VALUE];
1792
1793 if(nentries < 1024)
1794 {
1795 nrows= nentries;
1796 if (fieldType[k] == 'A')
1797 {
1798 sprintf(largeur,"%d",taille_des_chaines[noColString++]);
1799 strcpy(format,largeur);
1800 }
1801 else strcpy(format,"1");
1802 }
1803 else
1804 {
1805 nrows = nentries/1024;
1806 if(nentries%1024 != 0) nrows++;
1807 if (fieldType[k] == 'A')
1808 {
[1136]1809 char largaux[FLEN_VALUE];
1810 sprintf(largeur,"%d",taille_des_chaines[noColString]);
1811 sprintf(largaux,"%d",1024*taille_des_chaines[noColString]);
1812 noColString++;
1813 strcpy(format, largaux);
[839]1814 }
1815 else strcpy(format,"1024");
1816 }
1817 strncat(format,&fieldType[k],1);
1818 if (fieldType[k] == 'A')
1819 {
1820 strcat(format,largeur);
1821 }
[1193]1822 ttype[k] = const_cast<char*>(Noms[k].c_str());
[839]1823 tform[k]= new char[FLEN_VALUE];
1824 strcpy(tform[k],format);
1825 }
[1193]1826 char* extn = const_cast<char*>(extname.c_str());
[839]1827
1828 // create a new empty binary table onto the FITS file
1829 // physical units if they exist, are defined in the DVList object
1830 // so the NULL pointer is given for the tunit parameters.
1831 nrows=0;
1832 fits_create_tbl(fptr_,BINARY_TBL,nrows,tfields,ttype,tform,
1833 NULL,extn,&status);
1834 if( status ) printerror( status );
[1353]1835
1836 int ii;
1837 for(ii = 0; ii < tfields; ii++)
1838 {
1839 delete [] tform[ii];
1840 }
1841 delete [] ttype;
1842 delete [] tform;
1843
1844 // on ajoute eventuellement des mots-cles
1845
[1246]1846 if ( hdunum_ == 0 )
1847 {
1848 hdunum_ = 2;
1849 addDVListOnPrimary();
1850 writeSignatureOnFits(1);
1851 }
[1026]1852 else hdunum_++;
[1353]1853
1854 // header format FITS
1855
1856 writeAppendedHeaderOnFits();
1857
1858 // write SOPHYA keywords
[1221]1859 if (ptr_dvl != NULL) addKeywordsOfDVList(*ptr_dvl);
[839]1860}
1861
[1353]1862
1863
[1218]1864/*! \fn void SOPHYA::FitsOutFile::PutColToFits(int nocol, int nentries, double* donnees) const
1865
1866write double data from array 'donnees ' on column number 'nocol' of a BINTABLE extension.
1867\param <nentries> number of data to be written
1868*/
[1353]1869
[1379]1870void FitsOutFile::PutColToFits(int nocol, int nentries, r_8* donnees) const
[839]1871{
1872 int status = 0;
[971]1873 int hdutype;
[839]1874 fits_movabs_hdu(fptr_,hdunum_,&hdutype,&status);
[1209]1875 if( status ) printerror(status,"PutColToFits: le movabs a foire");
[839]1876 fits_get_hdu_type(fptr_, &hdutype, &status);
[867]1877 if(hdutype != ASCII_TBL && hdutype != BINARY_TBL)
1878 {
1879 cout << " hdunum= " << hdunum_ << " hdutype= " << hdutype << endl;
[1209]1880 throw IOExc("FitsFile::PutColToFits, this HDU is not an ASCII table nor a binary table");
[867]1881 }
[839]1882 int code;
1883 long repeat, width;
1884 fits_get_coltype(fptr_, nocol+1, &code, &repeat,&width, &status);
1885 if( code != TDOUBLE)
1886 {
[1209]1887 cout << " WARNING : types don't match (PutColToFits) : on fits file= " << code << " to be written= DOUBLE " << endl;
[839]1888 }
[1499]1889 // cout << " 10 elements de colonne " << endl;
1890 // for (int toto=0; toto < 10; toto++) cout << donnees[toto] << endl;
[839]1891 fits_write_col(fptr_,TDOUBLE,nocol+1,1,1,nentries, donnees ,&status);
[1752]1892 if( status ) printerror( status,"erreur ecriture col. double, dans fichier fits" );
[839]1893}
[1218]1894
1895
1896
1897 /*! \fn void SOPHYA::FitsOutFile::PutColToFits(int nocol, int nentries, float* donnees) const
1898
1899same as previous method with float data
1900*/
[1379]1901void FitsOutFile::PutColToFits(int nocol, int nentries, r_4* donnees) const
[839]1902{
1903 int status = 0;
1904 int hdutype;
1905 fits_movabs_hdu(fptr_,hdunum_,&hdutype,&status);
[1209]1906 if( status ) printerror(status,"PutColToFits: le movabs a foire");
[839]1907 fits_get_hdu_type(fptr_, &hdutype, &status);
1908 if(hdutype != ASCII_TBL && hdutype != BINARY_TBL)
1909 {
1910 cout << " hdunum= " << hdunum_ << " hdutype= " << hdutype << endl;
[1209]1911 throw IOExc("FitsFile::PutColToFits, this HDU is not an ASCII table nor a binary table");
[839]1912 }
1913 if(hdutype == ASCII_TBL && nocol>0)
1914 {
[1209]1915 throw IOExc("FitsFile::PutColToFits, this HDU is an ASCII table, nocol>0 forbidden");
[839]1916 }
1917 int code;
1918 long repeat, width;
1919 fits_get_coltype(fptr_, nocol+1, &code, &repeat,&width, &status);
1920 if( code != TFLOAT)
1921 {
[1209]1922 cout << " WARNING : types don't match (PutColToFits) : on fits file= " << code << " (FITS code), to be written= FLOAT " << endl;
[839]1923 }
1924 fits_write_col(fptr_,TFLOAT,nocol+1,1,1,nentries, donnees ,&status);
[1752]1925 if( status ) printerror( status,"erreur ecriture col. floats, dans fichier fits" );
[839]1926}
[1218]1927
1928
1929/*! \fn void FitsOutFile::PutColToFits(int nocol, int nentries, int* donnees) const
1930
1931same as previous method with int data
1932*/
[1379]1933void FitsOutFile::PutColToFits(int nocol, int nentries, int_4* donnees) const
[839]1934{
1935 int status = 0;
1936 int hdutype;
1937 fits_movabs_hdu(fptr_,hdunum_,&hdutype,&status);
[1209]1938 if( status ) printerror(status,"PutColToFits: le movabs a foire");
[839]1939 fits_get_hdu_type(fptr_, &hdutype, &status);
1940 if(hdutype != ASCII_TBL && hdutype != BINARY_TBL)
1941 {
1942 cout << " hdunum= " << hdunum_ << " hdutype= " << hdutype << endl;
[1209]1943 throw IOExc("FitsFile::PutColToFits, this HDU is not an ASCII table nor a binary table");
[839]1944 }
1945 if(hdutype == ASCII_TBL && nocol>0)
1946 {
[1209]1947 throw IOExc("FitsFile::PutColToFits, this HDU is an ASCII table, nocol>0 forbidden");
[839]1948 }
1949 int code;
1950 long repeat, width;
1951 fits_get_coltype(fptr_, nocol+1, &code, &repeat,&width, &status);
[1752]1952
1953
[2197]1954
1955 if (code == TINT || code == TLONG)
[839]1956 {
[2197]1957 // cfitsio n'a que des entiers de longueur inferieure a 32 bits.
1958 // ici, a l'ecriture TLONG impliquerait que le tableau de donnees
1959 // soit un tableau int_8. Donc c'est toujours TINT qu;il faut mettre
1960 // De plus, j'ai l'impression que TINT va devenir obsolete dans cfitsio
1961 // (GLM)
[1752]1962 fits_write_col(fptr_,TINT,nocol+1,1,1,nentries, donnees ,&status);
1963 }
1964 else
1965 {
1966 cout << " WARNING : types don't match (PutColToFits) : on fits file= " << code << " (FITS code), to be written= integers " << endl;
[839]1967 }
[1752]1968 if( status ) printerror( status,"erreur ecriture col. entiers, dans fichier fits" );
[839]1969}
[1218]1970
1971
1972/*! \fn void SOPHYA::FitsOutFile::PutColToFits(int nocol, int nentries, char** donnees) const
1973same as previous method with char* data
1974*/
[1209]1975void FitsOutFile::PutColToFits(int nocol, int nentries, char** donnees) const
[839]1976{
1977 int status = 0;
1978 int hdutype;
1979 fits_movabs_hdu(fptr_,hdunum_,&hdutype,&status);
[1209]1980 if( status ) printerror(status,"PutColToFits: le movabs a foire");
[839]1981 fits_get_hdu_type(fptr_, &hdutype, &status);
1982 if(hdutype != ASCII_TBL && hdutype != BINARY_TBL)
1983 {
1984 cout << " hdunum= " << hdunum_ << " hdutype= " << hdutype << endl;
[1209]1985 throw IOExc("FitsFile::PutColToFits, this HDU is not an ASCII table nor a binary table");
[839]1986 }
1987 if(hdutype == ASCII_TBL && nocol>0)
1988 {
[1209]1989 throw IOExc("FitsFile::PutColToFits, this HDU is an ASCII table, nocol>0 forbidden");
[839]1990 }
1991 int code;
1992 long repeat, width;
1993 fits_get_coltype(fptr_, nocol+1, &code, &repeat,&width, &status);
1994 if( code != TSTRING)
1995 {
[1209]1996 cout << " WARNING : types don't match (PutColToFits) : on fits file= " << code << " (FITS code), to be written= char** " << endl;
[839]1997 }
1998 fits_write_col(fptr_,TSTRING,nocol+1,1,1,nentries, donnees ,&status);
[1752]1999 if( status ) printerror( status,"erreur ecriture col. chars, dans fichier fits" );
[839]2000}
2001
[1209]2002void FitsOutFile::PutBinTabLine(long NoLine, BnTblLine& ligne) const
[1193]2003{
[1209]2004 // on ne fait pas de verification de type, ni de dimension ici, pour
2005 // des raisons de performances
2006 int k;
[1193]2007 int status= 0;
[1978]2008 int anynul;
[1209]2009 int ncol=0;
[1193]2010 long nels=1;
[1209]2011 // int nbcols;
2012 // fits_get_num_cols(fptr_, &nbcols,&status);
2013 for (k=0; k<ligne.ddata_.size(); k++, ncol++)
[1193]2014 {
[1209]2015 fits_write_col(fptr_,TDOUBLE,ncol+1,NoLine+1,1,1, &ligne.ddata_[k] ,&status);
2016 if( status ) printerror( status, "PutBinTabLine : erreur ecriture double" );
[1193]2017 }
[1209]2018 for (k=0; k<ligne.fdata_.size(); k++, ncol++)
2019 {
2020 fits_write_col(fptr_,TFLOAT,ncol+1,NoLine+1,1,1, &ligne.fdata_[k] ,&status);
2021 if( status ) printerror( status, "PutBinTabLine : erreur ecriture float" );
2022 }
2023 for (k=0; k<ligne.idata_.size(); k++, ncol++)
2024 {
2025 fits_write_col(fptr_,TINT,ncol+1,NoLine+1,1,1, &ligne.idata_[k] ,&status);
2026 if( status ) printerror( status, "PutBinTabLine : erreur ecriture entier" );
2027 }
[1359]2028 for (k=0; k<ligne.ldata_.size(); k++, ncol++)
2029 {
2030 fits_write_col(fptr_,TLONG,ncol+1,NoLine+1,1,1, &ligne.ldata_[k] ,&status);
2031 if( status ) printerror( status, "PutBinTabLine : erreur ecriture entier long" );
2032 }
2033 for (k=0; k<ligne.bdata_.size(); k++, ncol++)
2034 {
2035 fits_write_col(fptr_,TBYTE,ncol+1,NoLine+1,1,1, &ligne.bdata_[k] ,&status);
2036 if( status ) printerror( status, "PutBinTabLine : erreur ecriture byte" );
2037 }
[1209]2038
2039 for (k=0; k<ligne.cdata_.size(); k++, ncol++)
2040 {
[1220]2041 fits_write_col(fptr_,TSTRING,ncol+1,NoLine+1,1,1, (void*)ligne.cdata_[k].c_str() ,&status);
[1209]2042 if( status ) printerror( status, "PutBinTabLine : erreur ecriture caracteres" );
2043 }
[1193]2044}
2045
2046
[1218]2047/* \fn void SOPHYA::FitsOutFile::DVListIntoPrimaryHeader(DVList& dvl) const
2048
2049Put keywords from a DVList into the primary header of the fits-file
2050*/
[1246]2051void FitsOutFile::DVListIntoPrimaryHeader(DVList& dvl)
[1143]2052{
2053 int status = 0;
2054 int hdutype;
[1246]2055 if (hdunum_ == 0)
2056 {
2057 if (dvlToPrimary_ == NULL) dvlToPrimary_ = new DVList(dvl);
2058 else dvlToPrimary_->Merge(dvl);
2059 }
2060 else
2061 {
2062 fits_movabs_hdu(fptr_,1,&hdutype,&status);
2063 addKeywordsOfDVList(dvl);
2064 fits_movabs_hdu(fptr_,hdunum_,&hdutype,&status);
2065 }
[1143]2066}
[839]2067
[1143]2068
[1246]2069void FitsOutFile::writeSignatureOnFits(int hdunum) const
[839]2070{
2071 int status = 0;
[1246]2072 int hdutype;
[839]2073 char keyname[LEN_KEYWORD];
2074 char strval[FLEN_VALUE];
2075 char comment[FLEN_COMMENT];
[1246]2076 if (hdunum_ == 0)
2077 {
2078 cerr << " WARNING : can't write keywords on non existing primary header" << endl;
2079 return;
2080 }
2081 fits_movabs_hdu(fptr_,1,&hdutype,&status);
2082 //
[971]2083 strncpy(keyname, "CREATOR", LEN_KEYWORD);
[1418]2084 keyname[7] = '\0';
[971]2085 strcpy(strval, "SOPHYA");
2086 strcpy(comment," SOPHYA Package - FITSIOServer ");
2087 fits_write_key(fptr_, TSTRING, keyname, &strval, comment, &status);
2088 if( status ) printerror( status );
[1143]2089 fits_write_date(fptr_, &status);
[971]2090 fits_write_comment(fptr_,"..............................................", &status);
2091 fits_write_comment(fptr_, " SOPHYA package - FITSIOSever ", &status);
2092 fits_write_comment(fptr_, " (C) LAL/IN2P3-CNRS Orsay, FRANCE 2000", &status);
2093 fits_write_comment(fptr_, " (C) DAPNIA/CEA Saclay, FRANCE 2000", &status);
2094 fits_write_comment(fptr_,"..............................................", &status);
[1045]2095 if( status ) printerror( status, "erreur writeSignatureOnFits" );
[1246]2096 //
2097 fits_movabs_hdu(fptr_,hdunum_,&hdutype,&status);
[839]2098}
2099
[903]2100
[1246]2101void FitsOutFile::addKeywordsOfDVList( DVList& dvl) const
[1143]2102{
2103 int status = 0;
2104 fits_write_comment(fptr_,"---------- keywords from SOPHYA ---------", &status);
2105 DVList::ValList::const_iterator it;
2106 for(it = dvl.Begin(); it != dvl.End(); it++)
2107 {
[1311]2108 MuTyV::MTVType keytype= (*it).second.elval.Type();
[1418]2109 char keyname[LEN_KEYWORD];
2110 strncpy(keyname,(*it).first.substr(0,64).c_str(),LEN_KEYWORD);
2111 int bout = ((*it).first.substr(0,64).length() < LEN_KEYWORD) ? (*it).first.substr(0,64).length() : LEN_KEYWORD-1;
2112 keyname[bout] = '\0';
2113 string key((*it).first.substr(0,64));
2114 // string key(keyname);
[1143]2115 char comment[FLEN_COMMENT];
2116 char strval[FLEN_VALUE]= "";
2117 char *comkey = "COMMENT";
[1353]2118 // fits_read_keyword(fptr_, keyname, strval, NULL, &status);
2119 // if (status != 0 || strncmp(keyname,comkey,LEN_KEYWORD-1) == 0 )
[1143]2120 {
[1183]2121 string coco = dvl.GetComment(key);
2122 coco.copy( comment, FLEN_COMMENT-1);
2123 int bout = (coco.length() < FLEN_COMMENT) ? coco.length() : FLEN_COMMENT-1;
2124 comment[bout]= '\0';
[1143]2125 status = 0;
2126 switch (keytype)
2127 {
[1311]2128 case MuTyV::MTVInteger :
[1143]2129 {
[1183]2130 int ival = (int)dvl.GetI(key);
2131 fits_write_key(fptr_,TINT,keyname,&ival, comment,&status);
[1143]2132 break;
2133 }
[1311]2134 case MuTyV::MTVFloat :
[1143]2135 {
[1183]2136 double dval= (double)dvl.GetD(key);
[1143]2137 fits_write_key(fptr_,TDOUBLE,keyname,&dval,comment,&status);
2138 break;
2139 }
[1311]2140 case MuTyV::MTVString :
[1143]2141 {
[1183]2142 char strvaleur[FLEN_VALUE]= "";
2143 string valChaine = dvl.GetS(key);
2144 valChaine.copy(strvaleur, FLEN_VALUE-1);
2145 int fin = (valChaine.length() < FLEN_VALUE) ? valChaine.length() : FLEN_VALUE-1;
2146 strvaleur[fin]= '\0';
2147
2148 fits_write_key(fptr_,TSTRING,keyname,&strvaleur,comment,&status);
[1143]2149 break;
2150 }
2151 }
2152 }
2153 if( status ) printerror( status,"fitsfile: probleme ecriture mot-cle du dvlist" );
2154 }
2155 fits_write_comment(fptr_,"--------------------------------------", &status);
2156}
[903]2157
2158
[1246]2159void FitsOutFile::addDVListOnPrimary()
2160 {
2161 int status = 0;
2162 int hdutype;
2163 if (hdunum_ == 0)
2164 {
2165 cerr << " WARNING : can't write keywords on non existing primary header" << endl;
2166 return;
2167 }
2168 if (dvlToPrimary_ != NULL)
2169 {
2170 fits_movabs_hdu(fptr_,1,&hdutype,&status);
2171 addKeywordsOfDVList(*dvlToPrimary_);
2172 delete dvlToPrimary_;
2173 dvlToPrimary_ = NULL;
2174 fits_movabs_hdu(fptr_,hdunum_,&hdutype,&status);
2175 }
2176 }
[839]2177
[1353]2178
2179/*! \fn void FitsOutFile::appendInHeader(FitsInFile& infits, int hdunum)
2180
2181get a header from FitsInFile and append to the header beeing built
2182(shifting mandatory keywords)
2183*/
2184
2185void FitsOutFile::appendInputHeader(FitsInFile& infits, int hdunum)
2186{
[1771]2187
2188 infits.GetKeywordsFromHeader(hdunum, mots_cles_);
2189 /*
[1353]2190 int status = 0;
2191 int hdutype;
2192 fitsfile* fptr=infits.fitsfilePtr();
2193 fits_movabs_hdu(fptr,hdunum,&hdutype,&status);
2194 if( status ) fits_report_error(stderr,status);
2195
2196 // get number of keywords
2197 int nkeys,keypos;
2198 fits_get_hdrpos(fptr,&nkeys,&keypos,&status);
2199 if( status ) fits_report_error(stderr,status);
2200 // shift with the number of mandatory keywords
2201 int num= 0;
2202 // if primary header
2203 if (hdunum == 1)
2204 {
2205 // read NAXIS
2206 int naxis=0;
2207 fits_read_key(fptr,TINT,"NAXIS",&naxis,NULL,&status);
2208 // number of mandatory keywords
2209 num = naxis+3;
2210 }
2211 // extensions
2212 else
2213 {
2214 if (hdutype == IMAGE_HDU)
2215 {
2216 // read NAXIS
2217 int naxis=0;
2218 fits_read_key(fptr,TINT,"NAXIS",&naxis,NULL,&status);
2219 // number of mandatory keywords
2220 num = naxis+5;
2221 }
2222 else
2223 if(hdutype == ASCII_TBL || hdutype == BINARY_TBL)
2224 {
2225 // number of mandatory keywords
2226 num = 8;
2227 }
2228 }
2229 int j;
2230 char keyname[LEN_KEYWORD];
2231 char value[FLEN_VALUE];
2232 char comment[FLEN_COMMENT];
2233 for(j = num+1; j <= nkeys; j++)
2234 {
2235 char dtype;
2236 fits_read_keyn(fptr,j,keyname,value,comment,&status);
2237 if(status)
2238 {
2239 fits_report_error(stderr,status);
2240 status=0;
2241 }
2242 string kn(keyname);
2243 string cm(comment);
2244 string val(value);
2245 FitsKeyword kw(kn, val, cm);
2246 mots_cles_.push_back(kw);
2247 }
[1771]2248 */
[1353]2249}
2250void FitsOutFile::writeAppendedHeaderOnFits()
2251{
2252 for (list<FitsKeyword>::iterator it=mots_cles_.begin(); it !=mots_cles_.end(); it++)
2253 {
2254 (*it).writeOnFits(fptr_);
2255 }
2256 mots_cles_.clear();
2257}
2258
2259void FitsOutFile::insertKeywordOnHeader(string keyname, double value, string comment)
2260{
[1418]2261 char cvalue[16];
[1353]2262 sprintf(cvalue,"%e",value);
[1418]2263 FitsKeyword kw(keyname, string(cvalue), comment, 'F');
[1353]2264 mots_cles_.push_back(kw);
2265}
[1418]2266void FitsOutFile::insertKeywordOnHeader(string keyname, int value, string comment)
2267{
2268 char cvalue[16];
2269 sprintf(cvalue,"%d",value);
2270 FitsKeyword kw(keyname, string(cvalue), comment, 'I');
2271 mots_cles_.push_back(kw);
2272}
2273void FitsOutFile::insertKeywordOnHeader(string keyname, string value, string comment)
2274{
2275 FitsKeyword kw(keyname, value , comment, 'C');
2276 mots_cles_.push_back(kw);
2277}
[1353]2278
2279void FitsOutFile::insertCommentLineOnHeader(string comment)
2280{
2281 FitsKeyword kw(comment);
2282 mots_cles_.push_back(kw);
2283}
2284
2285void FitsOutFile::PrintHeaderToBeAppended()
2286{
2287 cout << " contenu du header en cours de fabrication " << endl;
2288 for (list<FitsKeyword>::iterator it=mots_cles_.begin(); it !=mots_cles_.end(); it++)
2289 {
2290 (*it).Print();
2291 }
2292}
2293
2294
2295FitsKeyword::FitsKeyword()
2296 {
2297 datatype_=' ';
2298 keyname_ = string("");
2299 dvalue_=0.;
2300 ivalue_=1;
2301 svalue_=string("");
2302 comment_=string("");
2303 }
2304
2305FitsKeyword::FitsKeyword(string comment)
2306 {
2307 datatype_=' ';
2308 keyname_=string("COMMENT");
2309 comment_=comment;
[1418]2310 }
[1353]2311
2312FitsKeyword::FitsKeyword(string keyname, string value, string comment) : keyname_(keyname), comment_(comment)
2313 {
2314 int status=0;
2315 char dtype;
2316 const char* val= value.c_str();
2317 char* valk = const_cast<char*>(val);
2318 fits_get_keytype(valk,&dtype,&status);
2319 if(status)
2320 {
2321 status=0;
[1354]2322 if (status == VALUE_UNDEFINED) cout << "WARNING (FitsKeyword) : undefined keyword value " << endl;
[1353]2323 datatype_=' ';
2324 }
2325 else datatype_=dtype;
2326
2327 switch( datatype_ )
2328 {
2329 case 'C':
2330 {
[1354]2331 strip(valk, 'B','\'');
2332 svalue_ = string(valk);
[1353]2333 break;
2334 }
2335 case 'I':
2336 {
2337 ivalue_ = atoi(val);
2338 break;
2339 }
2340 case 'L':
2341 {
[1354]2342 bool bb = value.c_str();
2343 ivalue_ = (int)bb;
[1353]2344 break;
2345 }
2346 case 'F':
2347 {
2348 dvalue_ = atof(val);
2349 break;
2350 }
2351 case 'X':
2352 {
2353 throw IOExc("FitsKeyword , complex keyword value not supported");
2354 }
2355 }
2356 }
2357
[1418]2358// constructeur pour les mots-cles maison (ne prvenant pas de la lecture d'un fichier fits)
2359FitsKeyword::FitsKeyword(string keyname, string value, string comment, char type) : keyname_(keyname), comment_(comment), datatype_(type)
2360 {
2361 char dtype;
2362 const char* val= value.c_str();
2363 char* valk = const_cast<char*>(val);
2364 switch( datatype_ )
2365 {
2366 case 'C':
2367 {
2368 strip(valk, 'B','\'');
2369 svalue_ = string(valk);
2370 break;
2371 }
2372 case 'I':
2373 {
2374 ivalue_ = atoi(val);
2375 break;
2376 }
2377 case 'L':
2378 {
2379 bool bb = value.c_str();
2380 ivalue_ = (int)bb;
2381 break;
2382 }
2383 case 'F':
2384 {
2385 dvalue_ = atof(val);
2386 break;
2387 }
2388 case 'X':
2389 {
2390 throw IOExc("FitsKeyword , complex keyword value not supported");
2391 }
2392 }
2393 }
2394
[1353]2395void FitsKeyword::writeOnFits(fitsfile* ptr)
2396 {
2397 int status=0;
[1418]2398 char keyname[LEN_KEYWORD];
2399 char comment[FLEN_COMMENT];
2400 keyname_.copy(keyname, LEN_KEYWORD);
2401 int bout = (keyname_.length() < LEN_KEYWORD) ? keyname_.length() : LEN_KEYWORD-1;
2402 keyname[bout] = '\0';
2403 comment_.copy( comment, FLEN_COMMENT);
2404 bout = (comment_.length() < FLEN_COMMENT) ? comment_.length() : FLEN_COMMENT-1;
2405 comment[bout]= '\0';
2406
[1353]2407 int nkeys,keypos;
2408 fits_get_hdrpos(ptr,&nkeys,&keypos,&status);
2409 switch( datatype_ )
2410 {
2411 case 'C':
2412 {
[1418]2413 char value[FLEN_VALUE]="";
2414 svalue_.copy(value, FLEN_VALUE-1);
2415 int fin = (svalue_.length() < FLEN_VALUE) ? svalue_.length() : FLEN_VALUE-1;
2416 value[fin]= '\0';
[1353]2417 fits_write_key(ptr,TSTRING,keyname,&value, comment,&status);
2418 fits_report_error(stderr,status);
2419 break;
2420 }
2421 case 'I':
2422 {
2423 fits_write_key(ptr,TINT,keyname,&ivalue_, comment,&status);
2424 fits_report_error(stderr,status);
2425 break;
2426 }
2427 case 'L':
2428 {
2429 fits_write_key(ptr,TLOGICAL,keyname,&ivalue_, comment,&status);
2430 fits_report_error(stderr,status);
2431 break;
2432 }
2433 case 'F':
2434 {
2435 fits_write_key(ptr,TDOUBLE,keyname,&dvalue_, comment,&status);
2436 fits_report_error(stderr,status);
2437 break;
2438 }
2439 case 'X':
2440 {
2441 cout << "FitsKeyword : complex keyword value not supported" << endl;;
[2197]2442 break;
[1353]2443 }
2444 default :
2445 {
2446 char *comkey = "COMMENT";
2447 if(strncmp(keyname,comkey,LEN_KEYWORD-1) == 0)
2448 {
2449 fits_write_comment(ptr,comment,&status);
2450 fits_report_error(stderr,status);
2451 }
2452 else
2453 {
2454 cout << " WARNING (FitsKeyword::writeOnFits) : unrecognized keyword : " << keyname_ << endl;
2455 }
2456 }
2457 }
2458 }
2459
2460void FitsKeyword::Print()
2461 {
2462 switch( datatype_ )
2463 {
2464 case 'C':
2465 {
2466 cout << " mot cle : " << keyname_ << " valeur : " << svalue_ << " commentaire : " << comment_ <<endl;
2467 break;
2468 }
2469 case 'I':
2470 {
2471 cout << " mot cle : " << keyname_ << " valeur : " << ivalue_ << " commentaire : " << comment_ <<endl;
2472 break;
2473 }
2474 case 'L':
2475 {
2476 cout << " mot cle : " << keyname_ << " valeur : " << ivalue_ << " commentaire : " << comment_ <<endl;
2477 break;
2478 }
2479 case 'F':
2480 {
2481 cout << " mot cle : " << keyname_ << " valeur : " << dvalue_ << " commentaire : " << comment_ <<endl;
2482 break;
2483 }
2484 case 'X':
2485 {
2486 cout << "FitsKeyword : complex keyword value not supported" << endl;;
2487 }
2488 default :
2489 {
2490 cout << " mot cle : " << keyname_ << " commentaire : " << comment_ <<endl;
2491 }
2492 }
2493 }
Note: See TracBrowser for help on using the repository browser.