#include "basedtable.h" #include #include "sopnamsp.h" #include "pexceptions.h" /*! \class SOPHYA::BaseDataTable \ingroup HiStats Base class for data tables. Each line represent a record and the column contains a given data type. */ /*! if fgl == true , return LongForm string \verbatim ---------------------------------------------- FieldType ShortForm LongForm ---------------------------------------------- IntegerField I Integer LongField L Long Integer FloatField F Float DoubleField D Double ComplexField Zx4 Complex DoubleComplexField Zx8 DoubleComplex StringField S String DateTimeField T DateTime ---------------------------------------------- \endverbatim */ string BaseDataTable::ColTypeToString(FieldType ft, bool fgl) { string rs; switch (ft) { case IntegerField : if (fgl) rs = "Integer"; else rs = "I"; break; case LongField : if (fgl) rs = "Long Integer"; else rs = "L"; break; case FloatField : if (fgl) rs = "Float"; else rs = "F"; break; case DoubleField : if (fgl) rs = "Double"; else rs = "D"; break; case ComplexField : if (fgl) rs = "Complex"; else rs = "Zx4"; break; case DoubleComplexField : if (fgl) rs = "DoubleComplex"; else rs = "Zx8"; break; case StringField : if (fgl) rs = "String"; else rs = "S"; break; case DateTimeField : if (fgl) rs = "DateTime"; else rs = "T"; break; default: rs = "??"; break; } return rs; } BaseDataTable::FieldType BaseDataTable::StringToColType(string const & sctyp) { if ( (sctyp == "Integer") || (sctyp == "I") ) return IntegerField; else if ( (sctyp == "Long Integer") || (sctyp == "L") ) return LongField; else if ( (sctyp == "Float") || (sctyp == "F") ) return FloatField; else if ( (sctyp == "Double") || (sctyp == "D") ) return DoubleField; else if ( (sctyp == "Complex") || (sctyp == "Zx4") ) return ComplexField; else if ( (sctyp == "DoubleComplex") || (sctyp == "Zx8") || (sctyp == "Z") ) return DoubleComplexField; else if ( (sctyp == "String") || (sctyp == "S") ) return StringField; else if ( (sctyp == "DateTime") || (sctyp == "T") ) return DateTimeField; else return DoubleField; } /* Constructeur */ BaseDataTable::BaseDataTable(sa_size_t segsz) { mNEnt = 0; mSegSz = (segsz > 0) ? segsz : 16; mNSeg = 0; mVarD = NULL; mVarMTV = NULL; mInfo = NULL; } BaseDataTable::~BaseDataTable() { if (mVarD) delete[] mVarD; if (mVarMTV) delete[] mVarMTV; if (mInfo) delete mInfo; } sa_size_t BaseDataTable::CopyStructure(BaseDataTable const & a) { if (NVar() > 0) throw ParmError("BaseDataTable::CopyStructure() Table already has columns"); if (a.NVar() == 0) { cout << "BaseDataTable::CopyStructure(a)/Warning Table a is not initialized" << endl; return 0; } for (size_t kk=0; kk= NVar())) throw RangeCheckError("BaseDataTable::NomIndex() out of range column index k"); return mNames[k].nom ; } //! Adds a line (or row to the table) with r_8* inout data /*! The data to be added is provided as an array (vector) of double (r_8). The necessary data conversion is performed, depending on each column's data typeconverted to the data type. Return the new number of table rows (lines / entries) \param data : Data for each cell of the row to be appended (data[k] k=0..NbColumns()) */ sa_size_t BaseDataTable::AddLine(const r_8* data) { if (NVar() == 0) throw ParmError("BaseDataTable::AddLine(const r_8*) Table has no column !"); if (NEntry() == SegmentSize()*NbSegments()) Extend(); sa_size_t n = NEntry(); sa_size_t bid = n/mSegSz; sa_size_t off = n%mSegSz; for(sa_size_t k=0; kGetSegment(bid)[off] = (int_4)data[mIColIdx[k]]; for(sa_size_t k=0; kGetSegment(bid)[off] = (int_8)data[mLColIdx[k]]; for(sa_size_t k=0; kGetSegment(bid)[off] = (r_4)data[mFColIdx[k]]; for(sa_size_t k=0; kGetSegment(bid)[off] = data[mDColIdx[k]]; for(sa_size_t k=0; kGetSegment(bid)[off] = complex(data[mYColIdx[k]],0.); for(sa_size_t k=0; kGetSegment(bid)[off] = complex(data[mZColIdx[k]],0.); for(sa_size_t k=0; kGetSegment(bid)[off] = (string)MuTyV(data[mSColIdx[k]]); mNEnt++; return mNEnt; } //! Adds a line (or row to the table) with input data as an array of MuTyV /*! The data to be added is provided as an array (vector) of MuTyV. The MuTyV class conversion operators are used to match against each cell data type. Return the new number of table rows (lines / entries) \param data : Data (MuTyV*) for each cell of the row to be appended (data[k] k=0..NbColumns()) */ sa_size_t BaseDataTable::AddLine(const MuTyV* data) { if (NVar() == 0) throw ParmError("BaseDataTable::AddLine(const MuTyV*) Table has no column !"); if (NEntry() == SegmentSize()*NbSegments()) Extend(); sa_size_t n = NEntry(); sa_size_t bid = n/mSegSz; sa_size_t off = n%mSegSz; for(sa_size_t k=0; kGetSegment(bid)[off] = (int_4)data[mIColIdx[k]]; for(sa_size_t k=0; kGetSegment(bid)[off] = (int_8)data[mLColIdx[k]]; for(sa_size_t k=0; kGetSegment(bid)[off] = (string)data[mSColIdx[k]]; for(sa_size_t k=0; kGetSegment(bid)[off] = (r_4)data[mFColIdx[k]]; for(sa_size_t k=0; kGetSegment(bid)[off] = (r_8)data[mDColIdx[k]]; for(sa_size_t k=0; kGetSegment(bid)[off] = complex(data[mYColIdx[k]].GetRealPart(), data[mYColIdx[k]].GetImagPart()); for(sa_size_t k=0; kGetSegment(bid)[off] = complex(data[mZColIdx[k]].GetRealPart(), data[mZColIdx[k]].GetImagPart()); mNEnt++; return mNEnt; } sa_size_t BaseDataTable::Extend() { for(sa_size_t k=0; kExtend(); for(sa_size_t k=0; kExtend(); for(sa_size_t k=0; kExtend(); for(sa_size_t k=0; kExtend(); for(sa_size_t k=0; kExtend(); for(sa_size_t k=0; kExtend(); for(sa_size_t k=0; kExtend(); mNSeg++; return mNSeg; } MuTyV* BaseDataTable::GetLine(sa_size_t n) const { if ((n < 0) || (n >= NEntry())) throw RangeCheckError("BaseDataTable::GetLine() out of range line index n"); if (mVarMTV == NULL) mVarMTV = new MuTyV[NVar()]; sa_size_t bid = n/mSegSz; sa_size_t off = n%mSegSz; for(sa_size_t k=0; kGetCstSegment(bid)[off]; for(sa_size_t k=0; kGetCstSegment(bid)[off]; for(sa_size_t k=0; kGetCstSegment(bid)[off]; for(sa_size_t k=0; kGetCstSegment(bid)[off]; for(sa_size_t k=0; kGetCstSegment(bid)[off]; for(sa_size_t k=0; kGetCstSegment(bid)[off]; for(sa_size_t k=0; kGetCstSegment(bid)[off].c_str()); return mVarMTV; } #define BADVAL -1.e39 TVector BaseDataTable::GetColumnD(sa_size_t k) const { if ((k < 0) || (k >= NVar())) throw RangeCheckError("BaseDataTable::GetColumnD() out of range column index k"); sa_size_t sk = mNames[k].ser; sa_size_t i = 0; TVector rv(NEntry()); for (sa_size_t is=0; isGetCstSegment(is)[j]; break; case LongField : for(sa_size_t j=0; jGetCstSegment(is)[j]; break; case FloatField : for(sa_size_t j=0; jGetCstSegment(is)[j]; break; case DoubleField : case DateTimeField : for(sa_size_t j=0; jGetCstSegment(is)[j]; break; case ComplexField : for(sa_size_t j=0; jGetCstSegment(is)[j].real(); break; case DoubleComplexField : for(sa_size_t j=0; jGetCstSegment(is)[j].real(); break; case StringField : for(sa_size_t j=0; jGetCstSegment(is)[j].c_str()); break; default: for(sa_size_t j=0; j 0) ) throw ParmError("BaseDataTable::CopyMerge(a) Table has entries already"); if (a.NVar() == 0) throw ParmError("BaseDataTable::CopyMerge(a) Table a has no column"); if (NVar() == 0) CopyStructure(a); else if (!CompareStructure(a)) throw SzMismatchError("BaseDataTable::CopyMerge(a) (this,a) have different table structure"); if (a.NEntry() == 0) { cout << " BaseDataTable::CopyMerge(a)/Warning : table a has zero (0) entry ! " << endl; return; } for(sa_size_t kk=0; kk~ 10^6) */ void BaseDataTable::Show(ostream& os) const { os << "BaseDataTable: NVar= " << NVar() << " NEnt= " << NEntry() << " ( SegSize= " << SegmentSize() << " NbSegments= " << NbSegments() << " )" << endl; os << "--------------------------------------------------------------------" << endl; os << setw(3) << "i" << ":" << setw(20) << " Name" << " (" << setw(4) << "Type" << ") | " << setw(15) << " Min " << " | " << setw(15) << " Max " << endl; os << "--------------------------------------------------------------------" << endl; r_8 min, max ; for(sa_size_t i = 0 ; i < NVar() ; i++) { GetMinMax(i, min, max) ; string nom; if (mNames[i].nom.length() > 20) nom = mNames[i].nom.substr(20); else nom = mNames[i].nom; os << setw(3) << i << ":" << setw(20) << nom << " (" << setw(4) << ColTypeToString(mNames[i].type) << ") | " << setw(15) << min << " | " << setw(15) << max << endl; } os << "--------------------------------------------------------------------" << endl; return; } //! Fills table from an ascii (text) file /* Return number of non empt lines (added to table) \param is : input ascii (text) stream \param clm : Lines starting with clm are ignored (comments) \param sep : separator between different fields (columns) */ sa_size_t BaseDataTable::FillFromASCIIFile(istream& is, char clm, const char* sep) { string str; if (mVarMTV == NULL) mVarMTV = new MuTyV[NVar()]; sa_size_t iv, nl; nl = 0; while (!is.eof()) { str = ""; getline(is, str); if (is.good() || is.eof()) { size_t l = str.length(); if ((l == 0) || (str[0]==clm)) continue; for(iv=0; iv= l) break; if (str[p] == '\'') { // Decodage d'un string q = str.find('\'',p+1); if (q < l) { mVarMTV[iv] = str.substr(p+1,q-p-1); q++; } else mVarMTV[iv] = str.substr(p+1,l-p-1); iv++; } else { q = str.find_first_of(sep,p); if (q > l) q = l; mVarMTV[iv] = str.substr(p,q-p); iv++; } if (mNames[iv-1].type == DateTimeField) { string tts = (string)mVarMTV[iv-1]; mVarMTV[iv-1] = TimeStamp(tts); } } AddLine(mVarMTV); nl++; } } // Fin boucle lignes fichier cout << "BaseDataTable::FillFromASCIIFile()/Info: " << nl << " lines decoded from stream " << endl; return(nl); } // // ------------------------------------ // ------- Interface NTuple ----------- // ------------------------------------ // sa_size_t BaseDataTable::NbLines() const { return(NEntry()); } sa_size_t BaseDataTable::NbColumns() const { return(NVar()); } r_8* BaseDataTable::GetLineD(sa_size_t n) const { if ((n < 0) || (n >= NEntry())) throw RangeCheckError("BaseDataTable::GetLineD() out of range line index n"); if (mVarD == NULL) mVarD = new r_8[NVar()]; sa_size_t bid = n/mSegSz; sa_size_t off = n%mSegSz; for(sa_size_t k=0; kGetCstSegment(bid)[off]; for(sa_size_t k=0; kGetCstSegment(bid)[off]; for(sa_size_t k=0; kGetCstSegment(bid)[off]; for(sa_size_t k=0; kGetCstSegment(bid)[off]; for(sa_size_t k=0; kGetCstSegment(bid)[off].real(); for(sa_size_t k=0; kGetCstSegment(bid)[off].real(); for(sa_size_t k=0; kGetCstSegment(bid)[off].c_str()); return mVarD; } r_8 BaseDataTable::GetCell(sa_size_t n, sa_size_t k) const { if ((n < 0) || (n >= NEntry())) throw RangeCheckError("BaseDataTable::GetCell() out of range line index n"); if ((k < 0) || (k >= NVar())) throw RangeCheckError("BaseDataTable::GetCell() out of range column index k"); double rv = BADVAL; sa_size_t sk = mNames[k].ser; sa_size_t bid = n/mSegSz; sa_size_t off = n%mSegSz; switch (mNames[k].type) { case IntegerField : rv = mIColsP[sk]->GetCstSegment(bid)[off]; break; case LongField : rv = mLColsP[sk]->GetCstSegment(bid)[off]; break; case FloatField : rv = mFColsP[sk]->GetCstSegment(bid)[off]; break; case DoubleField : case DateTimeField : rv = mDColsP[sk]->GetCstSegment(bid)[off]; break; case ComplexField : rv = mYColsP[sk]->GetCstSegment(bid)[off].real(); break; case DoubleComplexField : rv = mZColsP[sk]->GetCstSegment(bid)[off].real(); break; case StringField : rv = atof(mSColsP[sk]->GetCstSegment(bid)[off].c_str()); break; default: rv = BADVAL; break; } return rv ; } r_8 BaseDataTable::GetCell(sa_size_t n, string const& nom) const { return GetCell(n, IndexNom(nom)); } string BaseDataTable::GetCelltoString(sa_size_t n, sa_size_t k) const { if ((n < 0) || (n >= NEntry())) throw RangeCheckError("BaseDataTable::GetCell() out of range line index n"); if ((k < 0) || (k >= NVar())) throw RangeCheckError("BaseDataTable::GetCell() out of range column index k"); MuTyV rv;; sa_size_t sk = mNames[k].ser; sa_size_t bid = n/mSegSz; sa_size_t off = n%mSegSz; switch (mNames[k].type) { case IntegerField : rv = mIColsP[sk]->GetCstSegment(bid)[off]; break; case LongField : rv = mLColsP[sk]->GetCstSegment(bid)[off]; break; case FloatField : rv = mFColsP[sk]->GetCstSegment(bid)[off]; break; case DoubleField : rv = mDColsP[sk]->GetCstSegment(bid)[off]; break; case ComplexField : rv = mYColsP[sk]->GetCstSegment(bid)[off]; break; case DoubleComplexField : rv = mZColsP[sk]->GetCstSegment(bid)[off]; break; case StringField : rv = mSColsP[sk]->GetCstSegment(bid)[off]; break; case DateTimeField : rv = TimeStamp(mDColsP[sk]->GetCstSegment(bid)[off]); break; default: rv = " "; break; } return (string)rv ; } void BaseDataTable::GetMinMax(sa_size_t k, double& min, double& max) const { min = 9E39 ; max = -9E39 ; if ((k < 0) || (k >= NVar())) throw RangeCheckError("BaseDataTable::GetCell() out of range column index k"); if (mMinMaxNEnt.size() < NVar()) { mMin.clear(); mMax.clear(); mMinMaxNEnt.clear(); for(size_t kk=0; kkNbSegments(); is++) { const int_4* sp = mIColsP[sk]->GetCstSegment(is); for(size_t n=0; nSegmentSize(); n++) { if (cnt >= NEntry()) break; if (sp[n] > max) max = sp[n]; if (sp[n] < min) min = sp[n]; cnt++; } } break; case LongField : for(size_t is=0; isNbSegments(); is++) { const int_8* sp = mLColsP[sk]->GetCstSegment(is); for(size_t n=0; nSegmentSize(); n++) { if (cnt >= NEntry()) break; if (sp[n] > max) max = sp[n]; if (sp[n] < min) min = sp[n]; cnt++; } } break; case FloatField : for(size_t is=0; isNbSegments(); is++) { const r_4* sp = mFColsP[sk]->GetCstSegment(is); for(size_t n=0; nSegmentSize(); n++) { if (cnt >= NEntry()) break; if (sp[n] > max) max = sp[n]; if (sp[n] < min) min = sp[n]; cnt++; } } break; case DoubleField : case DateTimeField : for(size_t is=0; isNbSegments(); is++) { const r_8* sp = mDColsP[sk]->GetCstSegment(is); for(size_t n=0; nSegmentSize(); n++) { if (cnt >= NEntry()) break; if (sp[n] > max) max = sp[n]; if (sp[n] < min) min = sp[n]; cnt++; } } break; case ComplexField : for(size_t is=0; isNbSegments(); is++) { const complex * sp = mYColsP[sk]->GetCstSegment(is); for(size_t n=0; nSegmentSize(); n++) { if (cnt >= NEntry()) break; if (sp[n].real() > max) max = sp[n].real(); if (sp[n].real() < min) min = sp[n].real(); cnt++; } } break; case DoubleComplexField : for(size_t is=0; isNbSegments(); is++) { const complex * sp = mZColsP[sk]->GetCstSegment(is); for(size_t n=0; nSegmentSize(); n++) { if (cnt >= NEntry()) break; if (sp[n].real() > max) max = sp[n].real(); if (sp[n].real() < min) min = sp[n].real(); cnt++; } } break; case StringField : return; break; default: return; break; } mMinMaxNEnt[k] = cnt; mMin[k] = min; mMax[k] = max; return ; } void BaseDataTable::GetMinMax(string const & nom, double& min, double& max) const { GetMinMax(IndexNom(nom), min, max) ; } sa_size_t BaseDataTable::ColumnIndex(string const& nom) const { return IndexNom(nom) ; } string BaseDataTable::ColumnName(sa_size_t k) const { return NomIndex(k) ; } string BaseDataTable::VarList_C(const char* nomx) const { string rets=""; sa_size_t i; for(i=0; i 0) ) rets += ";"; if (i%5 == 0) rets += "\ndouble "; else rets += ","; rets += mNames[i].nom; } rets += "; \n"; if (nomx) { char buff[256]; for(i=0; i 0) ) rets += "\n"; } } return(rets); } string BaseDataTable::LineHeaderToString() const { string rets,s; for(int i=0; i 0) rets += ' '; rets += s; } return(rets); } /*! Return a table row (line) as a string \sa TableRowToString() */ string BaseDataTable::LineToString(sa_size_t n) const { return TableRowToString(n, false); } /*! \param n : table row index ( 0 ... NEntry()-1) \param qstr : if true , enclose strings in quotes '' \param sep : separates fields using \b sep \param fw : minimum field width */ string BaseDataTable::TableRowToString(sa_size_t n, bool qstr, const char* sep, int fw) const { if ((n < 0) || (n >= NEntry())) throw RangeCheckError("BaseDataTable::GetCell() out of range line index n"); string rs; MuTyV rv;; sa_size_t bid = n/mSegSz; sa_size_t off = n%mSegSz; for(sa_size_t k=0; kGetCstSegment(bid)[off]; break; case LongField : rv = mLColsP[sk]->GetCstSegment(bid)[off]; break; case FloatField : rv = mFColsP[sk]->GetCstSegment(bid)[off]; break; case DoubleField : rv = mDColsP[sk]->GetCstSegment(bid)[off]; break; case ComplexField : rv = mYColsP[sk]->GetCstSegment(bid)[off]; break; case DoubleComplexField : rv = mZColsP[sk]->GetCstSegment(bid)[off]; break; case StringField : rv = mSColsP[sk]->GetCstSegment(bid)[off]; break; case DateTimeField : rv = TimeStamp(mDColsP[sk]->GetCstSegment(bid)[off]); break; default: rv = " "; break; } string s; if ( (mNames[k].type == StringField) && (qstr) ) { s = '\''; s += (string)rv; s += '\''; } else s= (string)rv; size_t l = s.length(); for(size_t ii=l; ii 0) rs += sep; rs += s; } return rs; }