/* Lecteur de colonne de table Fits (binaire ou ASCII) avec buffer */ #include "machdefs.h" #include #include #include "pexceptions.h" #include "fabtcolread.h" //! Class for reading a column in a FITS ASCII or BINARY table /*! \class SOPHYA::FitsABTColRead \ingroup FitsIOServer Class for reading a column in a FITS ASCII or BINARY table \verbatim -- Exemple: FitsABTColRead fbt("myfits.fits","BoloMuv_28",0,1000,1,3); fbt.SetDebug(3); fbt.Print(3); // Read element by element for(long i=0;i data; long n = fbt.Read(32,50,data); cout<<"Number of values read: "<nhdu first binary or ASCII table is taken - bsens>0 read forward bsens<0 read backward bsens==0 read centered \endverbatim \warning ihdu = [1,nhdu] */ FitsABTColRead::FitsABTColRead(string fname,string collabel ,int ihdu,long blen,long bsens,int lp) { Init(fname.c_str(),collabel.c_str(),-1,ihdu,blen,bsens,lp); } /*! Constructor. Same as before but the column is identified by its column number \param colnum : number of the column to be read \warning col = [0,ncol[ */ FitsABTColRead::FitsABTColRead(string fname,int colnum ,int ihdu,long blen,long bsens,int lp) { Init(fname.c_str(),"",colnum,ihdu,blen,bsens,lp); } /*! Constructor. see below */ FitsABTColRead::FitsABTColRead(const char * cfname,const char* collabel ,int ihdu,long blen,long bsens,int lp) { Init(cfname,collabel,-1,ihdu,blen,bsens,lp); } /*! Constructor. see below */ FitsABTColRead::FitsABTColRead(const char * cfname,int colnum ,int ihdu,long blen,long bsens,int lp) { Init(cfname,"",colnum,ihdu,blen,bsens,lp); } /*! Constructor by copy */ FitsABTColRead::FitsABTColRead(FitsABTColRead& fbt) { Init(fbt.GetFileName().c_str(),fbt.GetColLabel().c_str() ,fbt.GetColNum(),fbt.GetHDU() ,fbt.GetBLen(),fbt.GetBSens(),fbt.DbgLevel); } /*! Init routine called by the constructor */ void FitsABTColRead::Init(const char* fname,const char* collabel,int colnum ,int ihdu,long blen,long bsens,int lp) { // Parametres Generaux FitsFN = fname; ColLabel = collabel; ColTUnit = ""; ColTForm = ""; ColNum = colnum; ColTypeCode = 0; IHdu = ihdu; NHdu = 0; HduType = 0; NBcol = 0; NBline = 0; SetNulVal(); SetDebug(lp); NFitsRead = 0; FitsPtr = NULL; LineDeb = LineFin = -1; Buffer = NULL; ChangeBuffer(blen,bsens); ////////////////////////// // Ouverture du fichier // ////////////////////////// int sta=0; if(FitsFN.size() <= 0 ) { IHdu = -1; Delete(); throw ParmError("FitsABTColRead::Init: Fits file name error\n"); } const char * cfitsfn = FitsFN.c_str(); // Open fits if(fits_open_file(&FitsPtr,cfitsfn,READONLY,&sta)) { printerror(sta); Delete(); throw NullPtrError("FitsABTColRead::Init: Error opening Fits file\n"); } // Get number of hdu if(fits_get_num_hdus(FitsPtr,&NHdu,&sta)) { printerror(sta); Delete(); throw NotAvailableOperation("FitsABTColRead::Init: Error getting NHdu\n"); } if(DbgLevel>1) cout<<"FitsABTColRead::Init NHdu="<NHdu on cherche la 1ere bin/ascii table // sinon on se positionne sur IHdu if(IHdu<=0 || IHdu>NHdu) for(int ihdu=1;ihdu<=NHdu;ihdu++) { if(fits_movabs_hdu(FitsPtr,ihdu,&HduType,&sta)) printerror(sta); if(DbgLevel>1) cout<<"...Init ihdu=" <1) cout<<"...Init NBcol="<1) cout<<"...Init NBline="< 0) { strcpy(labelcol,ColLabel.c_str()); if(fits_get_colnum(FitsPtr,CASESEN,labelcol,&ColNum,&sta)) { printerror(sta); Delete(); throw NotAvailableOperation("FitsABTColRead::Init: Error getting column name\n"); } ColNum--; // Convention [0,ncol[ } if(DbgLevel>1) cout<<"...Init ColNum="<=NBcol) { Delete(); throw RangeCheckError("FitsABTColRead::Init: Bad column number\n"); } // Get column type if(fits_get_coltype(FitsPtr,ColNum+1,&ColTypeCode,NULL,NULL,&sta)) { printerror(sta); Delete(); throw ParmError("FitsABTColRead::Init: Error getting column type\n"); } if(DbgLevel>1) cout<<"...Init ColTypeCode="<25%) if(oldnbufferNBuffer+long(0.25*NBuffer)) ) {delete [] Buffer; Buffer=NULL;} } // Re-allocate if(Buffer==NULL) Buffer = new double[NBuffer]; // Tell program that nothing is into buffer LineDeb = LineFin = -1; } /*! Delete called by the destructor */ void FitsABTColRead::Delete() { if(Buffer!=NULL) {delete [] Buffer; Buffer=NULL;} LineDeb = LineFin = -1; int sta = 0; if(fits_close_file(FitsPtr,&sta)) printerror(sta); FitsPtr = NULL; } ///////////////////////////////////////////////// /*! Read row "n" and return the value into a double \warning be carefull for the range: row = [0,NRows[ \return value in double \param n : number of the row to be read. \verbatim usebuffer == true : use read optimisation with bufferisation == false : no optimisation with bufferisation just read one value \endverbatim */ double FitsABTColRead::Read(long n,bool usebuffer) // Attention: n=nline [0,NBline[, cfistio veut [1,NBline] // Attention: colnum [0,NBcol[ , cfistio veut [1,NBcol] { int sta=0; if(n<0 || n>=NBline) throw RangeCheckError("FitsABTColRead::Read try to read outside line range\n"); // Pas de bufferisation, on lit betement if(NBuffer==1 || !usebuffer) { NFitsRead++; double val; fits_read_col(FitsPtr,TDOUBLE,ColNum+1,n+1,1,1,NULL,&val,NULL,&sta); if(sta) { printerror(sta); throw NotAvailableOperation("FitsABTColRead::Read: Error Reading Fits file\n"); } // On ne remplit Buffer[0] que si on a choisit // un mode de lecture non bufferise (n==1) DES LE DEBUT. // Si on a initialement choisit un mode bufferise (avec n>1), // Buffer contient les valeurs chargees auparavent. // Il ne faut pas faire {Buffer[0]=val; LineDeb=LineFin=n;} // car on perd l'info de ces valeurs. if(NBuffer==1) {Buffer[0]=val; LineDeb=LineFin=n;} return val; } // Gestion avec bufferisation if(!Buffer) throw RangeCheckError("FitsABTColRead::Read: Buffer not allocated\n"); if(nLineFin) { NFitsRead++; long row1,row2,nrow; if(BuffSens>0) { // Cas remplissage forward row1 = n+1; row2 = row1+NBuffer-1; if(row2>NBline) row2 = NBline; } else if(BuffSens<0) { // Cas remplissage backward row2 = n+1; row1 = row2-NBuffer+1; if(row1<1) row1 = 1; } else { // Cas remplissage centre row1 = n+1 - NBuffer/2; if(row1<1) row1 = 1; row2 = n+1 + NBuffer/2; if(row2>NBline) row2 = NBline; } nrow = row2 - row1 + 1; LineDeb = row1-1; LineFin = row2-1; //cout<<"DBG-FitsRead: row1="< V(5); bt.Read(3,5,V) -> read rows=3,4,5 -> V.Size()==5 -> return 3 bt.Read(3,-1,V) -> read rows=3,4,5,6,7 -> V.Size()==5 -> return 5 bt.Read(7,-1,V) -> read rows=7,8,9 -> V.Size()==5 -> return 3 bt.Read(2,-1,V) -> read rows=2,3,4,5,6 -> V.Size()==5 -> return 5 bt.Read(-1,5,V) -> throw exception TVector V(5); bt.Read(3,99,V) -> read rows=3,4,5,6,7,8,9 -> V.Size()==7 -> return 7 TVector V(5); bt.Read(2,8,V) -> read rows=2,3,4,5,6,7,8 -> V.Size()==7 -> return 7 TVector V; bt.Read(3,5,V) -> read rows=3,4,5 -> V.Size()==3 -> return 3 TVector V; bt.Read(3,-1,V) -> throw exception ------------------------------------------------------------------------- \endverbatim */ long FitsABTColRead::Read(long n1,long n2,TVector& data) { if(n1<0 || n1>=NBline) throw RangeCheckError("FitsABTColRead::Read TVector bad requested 1srt line \n"); if(data.Size()<=0 && n2=NBline) n2 = NBline-1; sa_size_t nread = n2-n1+1; if(data.Size(): Error Reading Fits file\n"); } return nread; } /*! idem before but for TVector of float */ long FitsABTColRead::Read(long n1,long n2,TVector& data) { if(n1<0 || n1>=NBline) throw RangeCheckError("FitsABTColRead::Read TVector bad requested 1srt line \n"); if(data.Size()<=0 && n2=NBline) n2 = NBline-1; sa_size_t nread = n2-n1+1; if(data.Size(): Error Reading Fits file\n"); } return nread; } /*! idem before but for TVector of unsigned short */ long FitsABTColRead::Read(long n1,long n2,TVector& data) { if(n1<0 || n1>=NBline) throw RangeCheckError("FitsABTColRead::Read TVector bad requested 1srt line \n"); if(data.Size()<=0 && n2=NBline) n2 = NBline-1; sa_size_t nread = n2-n1+1; if(data.Size(): Error Reading Fits file\n"); } return nread; } /*! idem before but for TVector of int_4 */ long FitsABTColRead::Read(long n1,long n2,TVector& data) { if(n1<0 || n1>=NBline) throw RangeCheckError("FitsABTColRead::Read TVector bad requested 1srt line \n"); if(data.Size()<=0 && n2=NBline) n2 = NBline-1; sa_size_t nread = n2-n1+1; if(data.Size(): Error Reading Fits file\n"); } return nread; } /*! idem before but for TVector of int_8 */ long FitsABTColRead::Read(long n1,long n2,TVector& data) { #ifdef TLONGLONG if(n1<0 || n1>=NBline) throw RangeCheckError("FitsABTColRead::Read TVector bad requested 1srt line \n"); if(data.Size()<=0 && n2=NBline) n2 = NBline-1; sa_size_t nread = n2-n1+1; if(data.Size(): Error Reading Fits file\n"); } return nread; #else throw PException("FitsABTColRead::Read(..,TVector&) Not in that cfitsio version"); #endif } ///////////////////////////////////////////////// /*! Return the number of the first row where "val1"<=val<="val2" starting at row "rowstart" \verbatim - The search is performed from "rowstart" to the end in ascending order (from "rowstart" to nrows). - Warning: "rowstart<0" means "rowstart==0" (search all the table column) That is the default \endverbatim \return <0 means not found */ long FitsABTColRead::FirstRow(double val1,double val2,long rowstart) { long row = -1; if(NBline==0) return row; // Change buffer for efficiency long bsens=BuffSens; bool bchange=false; if(bsens<=0) {ChangeBuffer(BuffLen,1); bchange=true;} if(rowstart<0) rowstart = 0; if(rowstart>=NBline) rowstart = NBline-1; for(long i=rowstart;ival2) continue; row = i; break; } if(bchange) ChangeBuffer(BuffLen,bsens); return row; } /*! Return the number of the first row where val1<=val<=val2 starting at row rowstart \return <0 means not found \verbatim - The search is performed from "rowstart" to the beginning in descending order (from "rowstart" to 0). - Warning: "rowstart<0" means "rowstart==nrows-1" (search all the table column) That is the default \endverbatim */ long FitsABTColRead::LastRow(double val1,double val2,long rowstart) { long row = -1; if(NBline==0) return row; // Change buffer for efficiency long bsens=BuffSens; bool bchange=false; if(bsens>=0) {ChangeBuffer(BuffLen,-1); bchange=true;} if(rowstart<0 || rowstart>=NBline) rowstart = NBline-1; for(long i=rowstart;i>=0;i--) { double val = Read(i); if(valval2) continue; row = i; break; } if(bchange) ChangeBuffer(BuffLen,bsens); return row; } ///////////////////////////////////////////////// void FitsABTColRead::printerror(int sta) const { int stat = sta; fits_report_error(stdout,stat); fflush(stdout); return; } /*! Print on stream os */ void FitsABTColRead::Print(ostream& os,int lp) const { os<<"FitsABTColRead:Print ("<