source: Sophya/trunk/SophyaLib/HiStats/basedtable.cc@ 3204

Last change on this file since 3204 was 3181, checked in by ansari, 19 years ago

Correction bug ds BaseDataTable::GetColumnD() (vu par Farharng), Reza 10/02/2007

File size: 28.3 KB
Line 
1#include "basedtable.h"
2#include <ctype.h>
3#include "sopnamsp.h"
4#include "pexceptions.h"
5
6/*!
7 \class SOPHYA::DataTableRow
8 \ingroup HiStats
9 This class is intented to be used with datatable classes
10 (inheriting from BaseDataTable) for representing a row (line)
11 of the table.
12*/
13DataTableRow::DataTableRow( vector<string> const& colnames )
14{
15 if (colnames.size() < 1)
16 throw ParmError("DataTableRow::DataTableRow(vector<string>& cn) cn.size()==0 ");
17 size_ = colnames.size();
18 mtv_ = new MuTyV[ size_ ];
19 for(sa_size_t k=0; k<size_; k++)
20 nm2idx_[colnames[k]] = k;
21}
22
23DataTableRow::DataTableRow(DataTableRow const & a )
24{
25 size_ = a.size_;
26 mtv_ = new MuTyV[ size_ ];
27 nm2idx_ = a.nm2idx_;
28}
29
30MuTyV DataTableRow::get(string const& colname) const
31{
32 map<string, sa_size_t>::const_iterator it = nm2idx_.find(colname);
33 if (it == nm2idx_.end()) {
34 string msg = "DataTableRow::get( " ;
35 msg += colname; msg += " ) Not found column name";
36 throw NotFoundExc(msg);
37 }
38 return mtv_[(*it).second];
39}
40
41MuTyV& DataTableRow::get(string const& colname)
42{
43 map<string, sa_size_t>::const_iterator it = nm2idx_.find(colname);
44 if (it == nm2idx_.end()) {
45 string msg = "DataTableRow::get( " ;
46 msg += colname; msg += " ) const - Not found column name";
47 throw NotFoundExc(msg);
48 }
49 return mtv_[(*it).second];
50}
51
52ostream& DataTableRow::Print(ostream& os) const
53{
54 for(sa_size_t k=0; k<size_; k++)
55 os << (string)mtv_[k] << " ";
56 return os;
57}
58
59/*!
60 \class SOPHYA::BaseDataTable
61 \ingroup HiStats
62 Base class for data tables. Each line represent a record
63 and the column contains a given data type.
64*/
65
66/*!
67 if fgl == true , return LongForm string
68 \verbatim
69 ----------------------------------------------
70 FieldType ShortForm LongForm
71 ----------------------------------------------
72 IntegerField I Integer
73 LongField L Long Integer
74 FloatField F Float
75 DoubleField D Double
76 ComplexField Zx4 Complex
77 DoubleComplexField Zx8 DoubleComplex
78 StringField S String
79 DateTimeField T DateTime
80 ----------------------------------------------
81 \endverbatim
82*/
83string BaseDataTable::ColTypeToString(FieldType ft, bool fgl)
84{
85 string rs;
86 switch (ft) {
87 case IntegerField :
88 if (fgl) rs = "Integer";
89 else rs = "I";
90 break;
91 case LongField :
92 if (fgl) rs = "Long Integer";
93 else rs = "L";
94 break;
95 case FloatField :
96 if (fgl) rs = "Float";
97 else rs = "F";
98 break;
99 case DoubleField :
100 if (fgl) rs = "Double";
101 else rs = "D";
102 break;
103 case ComplexField :
104 if (fgl) rs = "Complex";
105 else rs = "Zx4";
106 break;
107 case DoubleComplexField :
108 if (fgl) rs = "DoubleComplex";
109 else rs = "Zx8";
110 break;
111 case StringField :
112 if (fgl) rs = "String";
113 else rs = "S";
114 break;
115 case DateTimeField :
116 if (fgl) rs = "DateTime";
117 else rs = "T";
118 break;
119 default:
120 rs = "??";
121 break;
122 }
123 return rs;
124}
125
126BaseDataTable::FieldType BaseDataTable::StringToColType(string const & sctyp)
127{
128 if ( (sctyp == "Integer") || (sctyp == "I") ) return IntegerField;
129 else if ( (sctyp == "Long Integer") || (sctyp == "L") ) return LongField;
130 else if ( (sctyp == "Float") || (sctyp == "F") ) return FloatField;
131 else if ( (sctyp == "Double") || (sctyp == "D") ) return DoubleField;
132 else if ( (sctyp == "Complex") || (sctyp == "Zx4") ) return ComplexField;
133 else if ( (sctyp == "DoubleComplex") || (sctyp == "Zx8") || (sctyp == "Z") )
134 return DoubleComplexField;
135 else if ( (sctyp == "String") || (sctyp == "S") ) return StringField;
136 else if ( (sctyp == "DateTime") || (sctyp == "T") ) return DateTimeField;
137 else return DoubleField;
138}
139
140/* Constructeur */
141BaseDataTable::BaseDataTable(sa_size_t segsz)
142{
143 mNEnt = 0;
144 mSegSz = (segsz > 0) ? segsz : 16;
145 mNSeg = 0;
146 mVarD = NULL;
147 mVarMTV = NULL;
148 mInfo = NULL;
149}
150
151BaseDataTable::~BaseDataTable()
152{
153 if (mVarD) delete[] mVarD;
154 if (mVarMTV) delete[] mVarMTV;
155 if (mInfo) delete mInfo;
156}
157
158sa_size_t BaseDataTable::CopyStructure(BaseDataTable const & a)
159{
160 if (NVar() > 0)
161 throw ParmError("BaseDataTable::CopyStructure() Table already has columns");
162 if (a.NVar() == 0) {
163 cout << "BaseDataTable::CopyStructure(a)/Warning Table a is not initialized" << endl;
164 return 0;
165 }
166 for (size_t kk=0; kk<a.mNames.size(); kk++)
167 AddColumn(a.mNames[kk].type, a.mNames[kk].nom);
168 return NVar();
169}
170
171//! return true is same structure
172bool BaseDataTable::CompareStructure(BaseDataTable const & a)
173{
174 if (NVar() != a.NVar()) return false;
175 for (size_t kk=0; kk<mNames.size(); kk++)
176 if ( (mNames[kk].type != a.mNames[kk].type) ||
177 (mNames[kk].nom != a.mNames[kk].nom) ) return false;
178 return true;
179}
180
181//! Check the validity of column name \b cnom - throw exception.
182bool BaseDataTable::CheckColName(string const & cnom)
183{
184 size_t l,k;
185 l = cnom.length();
186 if (l < 1)
187 throw ParmError("BaseDataTable::CheckColName() zero length column name");
188 if (!isalpha(cnom[0]))
189 throw ParmError("BaseDataTable::CheckColName() first character not alphabetical");
190 for(k=1; k<l; k++)
191 if ((!isalnum(cnom[k])) && (cnom[k] != '_'))
192 throw ParmError("BaseDataTable::CheckColName() Non alphanumeric char in name");
193 for(k=0; k<mNames.size(); k++)
194 if (cnom == mNames[k].nom)
195 throw ParmError("BaseDataTable::CheckColName() already existing name");
196 return true;
197}
198
199/*!
200 \brief Check the validity of column name \b cnom and correct it if necessary
201 return true if \b cnom has been changed
202*/
203bool BaseDataTable::CheckCorrectColName(string& cnom)
204{
205 size_t l,k;
206 l = cnom.length();
207 string ssn;
208 MuTyV mvv = (NCols()+1);
209 mvv.Convert(ssn);
210 bool fgrc = false;
211 if (l < 1) { cnom = "C"+ssn; fgrc = true; }
212 if (!isalpha(cnom[0])) { cnom = "C"+cnom; fgrc = true; }
213 for(k=1; k<l; k++)
214 if ((!isalnum(cnom[k])) && (cnom[k] != '_')) {
215 cnom[k] = '_'; fgrc = true;
216 }
217 bool fgdouble = true;
218 while (fgdouble) {
219 fgdouble = false;
220 for(k=0; k<mNames.size(); k++)
221 if (cnom == mNames[k].nom) {
222 fgdouble = true; break;
223 }
224 if (fgdouble) { cnom = cnom+ssn; fgrc = true; }
225 }
226 return fgrc;
227}
228
229// Retourne une structure
230/*!
231 The returned BaseDataTable object can be used for subsequent call to
232 AddRow() or GetRow() methods.
233 Generate an exception if called for a table with no columns
234*/
235DataTableRow BaseDataTable::EmptyRow()
236{
237 if (NCols() == 0)
238 throw ParmError("BaseDataTable::EmptyRow() Table has no column !");
239 vector<string> nms;
240 for(sa_size_t k=0; k<NVar(); k++) nms.push_back(mNames[k].nom);
241 DataTableRow row(nms);
242 return row;
243}
244
245//
246// A quel index correspond mon nom ?
247//
248sa_size_t BaseDataTable::IndexNom(char const* nom) const
249{
250 for(sa_size_t k=0; k<NVar(); k++)
251 if ( mNames[k].nom == nom ) return k;
252 return -1;
253 // Reza:Avril 2005 : PINtuple se base sur le renvoi de -1 et pas d'une exception
254 // throw NotFoundExc("BaseDataTable::IndexNom() : column name not found ");
255}
256
257string BaseDataTable::NomIndex(sa_size_t k) const
258{
259 if ((k < 0) || (k >= NVar()))
260 throw RangeCheckError("BaseDataTable::NomIndex() out of range column index k");
261 return mNames[k].nom ;
262}
263
264//! Adds a row (or line) to the table with r_8* inout data
265/*!
266 The data to be added is provided as an array (vector) of double (r_8).
267 The necessary data conversion is performed, depending on each
268 column's data typeconverted to the data type.
269 Return the new number of table rows (lines / entries)
270 \param data : Data for each cell of the row to be appended
271 (data[k] k=0..NbColumns())
272*/
273sa_size_t BaseDataTable::AddRow(const r_8* data)
274{
275 if (NVar() == 0)
276 throw ParmError("BaseDataTable::AddRow(const r_8*) Table has no column !");
277 if (NEntry() == SegmentSize()*NbSegments()) Extend();
278 sa_size_t n = NEntry();
279 sa_size_t bid = n/mSegSz;
280 sa_size_t off = n%mSegSz;
281 for(sa_size_t k=0; k<mIColsP.size(); k++)
282 mIColsP[k]->GetSegment(bid)[off] = (int_4)data[mIColIdx[k]];
283 for(sa_size_t k=0; k<mLColsP.size(); k++)
284 mLColsP[k]->GetSegment(bid)[off] = (int_8)data[mLColIdx[k]];
285 for(sa_size_t k=0; k<mFColsP.size(); k++)
286 mFColsP[k]->GetSegment(bid)[off] = (r_4)data[mFColIdx[k]];
287 for(sa_size_t k=0; k<mDColsP.size(); k++)
288 mDColsP[k]->GetSegment(bid)[off] = data[mDColIdx[k]];
289 for(sa_size_t k=0; k<mYColsP.size(); k++)
290 mYColsP[k]->GetSegment(bid)[off] = complex<r_4>(data[mYColIdx[k]],0.);
291 for(sa_size_t k=0; k<mZColsP.size(); k++)
292 mZColsP[k]->GetSegment(bid)[off] = complex<r_8>(data[mZColIdx[k]],0.);
293 for(sa_size_t k=0; k<mSColsP.size(); k++)
294 mSColsP[k]->GetSegment(bid)[off] = (string)MuTyV(data[mSColIdx[k]]);
295
296 mNEnt++;
297 return mNEnt;
298}
299
300//! Adds a row (or line) to the table with input data as an array of MuTyV
301/*!
302 The data to be added is provided as an array (vector) of MuTyV.
303 The MuTyV class conversion operators are used to match against each
304 cell data type.
305 Return the new number of table rows (lines / entries)
306 \param data : Data (MuTyV*) for each cell of the row to be appended
307 (data[k] k=0..NbColumns())
308*/
309sa_size_t BaseDataTable::AddRow(const MuTyV* data)
310{
311 if (NVar() == 0)
312 throw ParmError("BaseDataTable::AddRow(const MuTyV*) Table has no column !");
313 if (NEntry() == SegmentSize()*NbSegments()) Extend();
314 sa_size_t n = NEntry();
315 sa_size_t bid = n/mSegSz;
316 sa_size_t off = n%mSegSz;
317 for(sa_size_t k=0; k<mIColsP.size(); k++)
318 mIColsP[k]->GetSegment(bid)[off] = (int_4)data[mIColIdx[k]];
319 for(sa_size_t k=0; k<mLColsP.size(); k++)
320 mLColsP[k]->GetSegment(bid)[off] = (int_8)data[mLColIdx[k]];
321 for(sa_size_t k=0; k<mSColsP.size(); k++)
322 mSColsP[k]->GetSegment(bid)[off] = (string)data[mSColIdx[k]];
323 for(sa_size_t k=0; k<mFColsP.size(); k++)
324 mFColsP[k]->GetSegment(bid)[off] = (r_4)data[mFColIdx[k]];
325 for(sa_size_t k=0; k<mDColsP.size(); k++)
326 mDColsP[k]->GetSegment(bid)[off] = (r_8)data[mDColIdx[k]];
327 for(sa_size_t k=0; k<mYColsP.size(); k++)
328 mYColsP[k]->GetSegment(bid)[off] =
329 complex<r_4>(data[mYColIdx[k]].GetRealPart(), data[mYColIdx[k]].GetImagPart());
330 for(sa_size_t k=0; k<mZColsP.size(); k++)
331 mZColsP[k]->GetSegment(bid)[off] =
332 complex<r_8>(data[mZColIdx[k]].GetRealPart(), data[mZColIdx[k]].GetImagPart());
333
334 mNEnt++;
335 return mNEnt;
336}
337//! Adds a row (or line) to the table with input data as DataTableRow object
338/*!
339 The internal MuTyV array of the object contains the data and the
340 MuTyV class conversion operators are used to match against each
341 cell data type.
342 Only the size of the input data object is checked.
343 Return the new number of table rows (lines / entries)
344 \param data : Data for each cell of the row to be appended
345 (data[k] k=0..NbColumns())
346*/
347sa_size_t BaseDataTable::AddRow(DataTableRow const& data)
348{
349 if ( data.Size() != NCols() )
350 throw SzMismatchError(" BaseDataTable::AddRow() - data.Size() != NCols() ");
351 return AddRow(data.MTVPtr());
352}
353
354/*!
355 Extends the table (in the row direction). This method is called automatically when needed.
356*/
357sa_size_t BaseDataTable::Extend()
358{
359 for(sa_size_t k=0; k<mIColsP.size(); k++)
360 mIColsP[k]->Extend();
361 for(sa_size_t k=0; k<mLColsP.size(); k++)
362 mLColsP[k]->Extend();
363 for(sa_size_t k=0; k<mFColsP.size(); k++)
364 mFColsP[k]->Extend();
365 for(sa_size_t k=0; k<mDColsP.size(); k++)
366 mDColsP[k]->Extend();
367 for(sa_size_t k=0; k<mYColsP.size(); k++)
368 mYColsP[k]->Extend();
369 for(sa_size_t k=0; k<mZColsP.size(); k++)
370 mZColsP[k]->Extend();
371 for(sa_size_t k=0; k<mSColsP.size(); k++)
372 mSColsP[k]->Extend();
373 mNSeg++;
374 return mNSeg;
375}
376
377/*!
378 Fills the input \b row object with the content of row \b n.
379 Return a reference to the input \b row object.
380 Generate an exception if the input \b row object has the wrong size.
381 This method is slower(less efficient) than the GetRow(n) method.
382*/
383DataTableRow& BaseDataTable::GetRow(sa_size_t n, DataTableRow& row) const
384{
385 if ( row.Size() != NCols() )
386 throw SzMismatchError(" BaseDataTable::GetRow(n, row) - row.Size() != NCols() ");
387 MuTyV* rmtv = GetRow(n);
388 for(sa_size_t k=0; k<NCols(); k++)
389 row[k] = rmtv[k];
390 return row;
391}
392
393MuTyV* BaseDataTable::GetRow(sa_size_t n) const
394{
395 if ((n < 0) || (n >= NEntry()))
396 throw RangeCheckError("BaseDataTable::GetRow() out of range line index n");
397 if (mVarMTV == NULL) mVarMTV = new MuTyV[NVar()];
398
399 sa_size_t bid = n/mSegSz;
400 sa_size_t off = n%mSegSz;
401 for(sa_size_t k=0; k<mIColsP.size(); k++)
402 mVarMTV[mIColIdx[k]] = mIColsP[k]->GetCstSegment(bid)[off];
403 for(sa_size_t k=0; k<mLColsP.size(); k++)
404 mVarMTV[mLColIdx[k]] = mLColsP[k]->GetCstSegment(bid)[off];
405 for(sa_size_t k=0; k<mFColsP.size(); k++)
406 mVarMTV[mFColIdx[k]] = mFColsP[k]->GetCstSegment(bid)[off];
407 for(sa_size_t k=0; k<mDColsP.size(); k++) {
408 if (GetColumType(mDColIdx[k]) == DateTimeField)
409 mVarMTV[mDColIdx[k]] = TimeStamp(mDColsP[k]->GetCstSegment(bid)[off]);
410 else mVarMTV[mDColIdx[k]] = mDColsP[k]->GetCstSegment(bid)[off];
411 }
412 for(sa_size_t k=0; k<mYColsP.size(); k++)
413 mVarMTV[mYColIdx[k]] = mYColsP[k]->GetCstSegment(bid)[off];
414 for(sa_size_t k=0; k<mZColsP.size(); k++)
415 mVarMTV[mZColIdx[k]] = mZColsP[k]->GetCstSegment(bid)[off];
416 for(sa_size_t k=0; k<mSColsP.size(); k++)
417 mVarMTV[mSColIdx[k]] = mSColsP[k]->GetCstSegment(bid)[off];
418
419 return mVarMTV;
420}
421
422#define BADVAL -1.e39
423
424TVector<r_8> BaseDataTable::GetColumnD(sa_size_t k) const
425{
426 if ((k < 0) || (k >= NVar()))
427 throw RangeCheckError("BaseDataTable::GetColumnD() out of range column index k");
428 sa_size_t sk = mNames[k].ser;
429 sa_size_t i = 0;
430 TVector<r_8> rv(NEntry());
431
432 for (sa_size_t is=0; is<NbSegments(); is++) {
433 switch (mNames[k].type) {
434 case IntegerField :
435 for(sa_size_t j=0; (j<SegmentSize())&&(i<NEntry()); j++,i++)
436 rv(i) = mIColsP[sk]->GetCstSegment(is)[j];
437 break;
438 case LongField :
439 for(sa_size_t j=0; (j<SegmentSize())&&(i<NEntry()); j++,i++)
440 rv(i) = mLColsP[sk]->GetCstSegment(is)[j];
441 break;
442 case FloatField :
443 for(sa_size_t j=0; (j<SegmentSize())&&(i<NEntry()); j++,i++)
444 rv(i) = mFColsP[sk]->GetCstSegment(is)[j];
445 break;
446 case DoubleField :
447 case DateTimeField :
448 for(sa_size_t j=0; (j<SegmentSize())&&(i<NEntry()); j++,i++)
449 rv(i) = mDColsP[sk]->GetCstSegment(is)[j];
450 break;
451 case ComplexField :
452 for(sa_size_t j=0; (j<SegmentSize())&&(i<NEntry()); j++,i++)
453 rv(i) = mYColsP[sk]->GetCstSegment(is)[j].real();
454 break;
455 case DoubleComplexField :
456 for(sa_size_t j=0; (j<SegmentSize())&&(i<NEntry()); j++,i++)
457 rv(i) = mZColsP[sk]->GetCstSegment(is)[j].real();
458 break;
459 case StringField :
460 for(sa_size_t j=0; (j<SegmentSize())&&(i<NEntry()); j++,i++)
461 rv = atof(mSColsP[sk]->GetCstSegment(is)[j].c_str());
462 break;
463 default:
464 for(sa_size_t j=0; (j<SegmentSize())&&(i<NEntry()); j++,i++)
465 rv(i) = BADVAL;
466 break;
467 }
468 }
469 return rv ;
470}
471
472void BaseDataTable::CopyMerge(BaseDataTable const& a, bool cp)
473{
474 if (cp && (NEntry() > 0) )
475 throw ParmError("BaseDataTable::CopyMerge(a) Table has entries already");
476 if (a.NVar() == 0) throw ParmError("BaseDataTable::CopyMerge(a) Table a has no column");
477 if (NVar() == 0) CopyStructure(a);
478 else if (!CompareStructure(a))
479 throw SzMismatchError("BaseDataTable::CopyMerge(a) (this,a) have different table structure");
480 if (a.NEntry() == 0) {
481 cout << " BaseDataTable::CopyMerge(a)/Warning : table a has zero (0) entry ! " << endl;
482 return;
483 }
484 for(sa_size_t kk=0; kk<a.NEntry(); kk++)
485 AddRow(a.GetLine(kk));
486}
487
488
489//! Returns the associated DVList object
490DVList& BaseDataTable::Info() const
491{
492 if (mInfo == NULL) mInfo = new DVList;
493 return(*mInfo);
494}
495
496/*!
497 Formatted (text) output of the table, for lines lstart <= l_index < lend , with step lstep
498 \param os : output stream (formatted output)
499 \param lstart : start row (line) index
500 \param lend : end row (line) index
501 \param lstep : row index increment
502*/
503ostream& BaseDataTable::Print(ostream& os, sa_size_t lstart, sa_size_t lend, sa_size_t lstep) const
504{
505 os << "##### BaseDataTable::Print() - Table(NRow=" << NEntry() << " , NCol="
506 << NVar() << ") ##### " << endl;
507 os << "#! " ;
508 for (size_t i=0; i<NVar(); i++) {
509 string nom = mNames[i].nom;
510 nom += ':'; nom += ColTypeToString(mNames[i].type);
511 os << setw(12) << nom << " ";
512 }
513 os << endl;
514 os << "##########################################################################" << endl;
515 for (sa_size_t l=lstart; l<lend; l+=lstep)
516 os << TableRowToString(l, true) << endl;
517 return os;
518}
519
520/*! In addition to printing the number of entries and column names,
521 this method prints also minimum/maximum value for each column.
522 This information might be computed when the Show() method is called.
523 This may take some time for tables with large number of entries (>~ 10^6)
524*/
525void BaseDataTable::Show(ostream& os) const
526{
527 os << "BaseDataTable: NVar= " << NVar() << " NEnt= " << NEntry()
528 << " ( SegSize= " << SegmentSize() << " NbSegments= "
529 << NbSegments() << " )" << endl;
530 os << "--------------------------------------------------------------------" << endl;
531 os << setw(3) << "i" << ":" << setw(20) << " Name" << " ("
532 << setw(4) << "Type" << ") | "
533 << setw(15) << " Min " << " | " << setw(15) << " Max " << endl;
534 os << "--------------------------------------------------------------------" << endl;
535 r_8 min, max ;
536 for(sa_size_t i = 0 ; i < NVar() ; i++) {
537 GetMinMax(i, min, max) ;
538 string nom;
539 if (mNames[i].nom.length() > 20)
540 nom = mNames[i].nom.substr(20);
541 else nom = mNames[i].nom;
542 os << setw(3) << i << ":" << setw(20) << nom << " ("
543 << setw(4) << ColTypeToString(mNames[i].type) << ") | "
544 << setw(15) << min << " | " << setw(15) << max << endl;
545 }
546 os << "--------------------------------------------------------------------" << endl;
547 return;
548}
549
550//! Fills table from an ascii (text) file
551/*
552 Return number of non empt lines (added to table)
553 \param is : input ascii (text) stream
554 \param clm : Lines starting with clm are ignored (comments)
555 \param sep : separator between different fields (columns)
556*/
557sa_size_t BaseDataTable::FillFromASCIIFile(istream& is, char clm, const char* sep)
558{
559 string str;
560 if (mVarMTV == NULL) mVarMTV = new MuTyV[NVar()];
561 sa_size_t iv, nl;
562 nl = 0;
563 while (!is.eof()) {
564 str = "";
565 getline(is, str);
566 if (is.good() || is.eof()) {
567 size_t l = str.length();
568 if ((l == 0) || (str[0]==clm)) continue;
569 for(iv=0; iv<NVar(); iv++) mVarMTV[iv] = 0.;
570 iv = 0;
571 size_t q = 0;
572 size_t p = 0;
573 while ( (q < l) && (iv < NVar()) ) {
574 p = str.find_first_not_of(sep,q);
575 if (p >= l) break;
576 if (str[p] == '\'') { // Decodage d'un string
577 q = str.find('\'',p+1);
578 if (q < l) {
579 mVarMTV[iv] = str.substr(p+1,q-p-1);
580 q++;
581 }
582 else mVarMTV[iv] = str.substr(p+1,l-p-1);
583 iv++;
584 }
585 else {
586 q = str.find_first_of(sep,p);
587 if (q > l) q = l;
588 mVarMTV[iv] = str.substr(p,q-p);
589 iv++;
590 }
591 if (mNames[iv-1].type == DateTimeField) {
592 string tts = (string)mVarMTV[iv-1];
593 mVarMTV[iv-1] = TimeStamp(tts);
594 }
595 }
596 AddRow(mVarMTV);
597 nl++;
598 }
599 } // Fin boucle lignes fichier
600 cout << "BaseDataTable::FillFromASCIIFile()/Info: " << nl << " lines decoded from stream " << endl;
601 return(nl);
602}
603
604
605
606//
607// ------------------------------------
608// ------- Interface NTuple -----------
609// ------------------------------------
610//
611sa_size_t BaseDataTable::NbLines() const
612{
613 return(NEntry());
614}
615
616sa_size_t BaseDataTable::NbColumns() const
617{
618 return(NVar());
619}
620
621r_8* BaseDataTable::GetLineD(sa_size_t n) const
622{
623 if ((n < 0) || (n >= NEntry()))
624 throw RangeCheckError("BaseDataTable::GetLineD() out of range line index n");
625 if (mVarD == NULL) mVarD = new r_8[NVar()];
626
627 sa_size_t bid = n/mSegSz;
628 sa_size_t off = n%mSegSz;
629 for(sa_size_t k=0; k<mIColsP.size(); k++)
630 mVarD[mIColIdx[k]] = mIColsP[k]->GetCstSegment(bid)[off];
631 for(sa_size_t k=0; k<mLColsP.size(); k++)
632 mVarD[mLColIdx[k]] = mLColsP[k]->GetCstSegment(bid)[off];
633 for(sa_size_t k=0; k<mFColsP.size(); k++)
634 mVarD[mFColIdx[k]] = mFColsP[k]->GetCstSegment(bid)[off];
635 for(sa_size_t k=0; k<mDColsP.size(); k++)
636 mVarD[mDColIdx[k]] = mDColsP[k]->GetCstSegment(bid)[off];
637 for(sa_size_t k=0; k<mYColsP.size(); k++)
638 mVarD[mYColIdx[k]] = mYColsP[k]->GetCstSegment(bid)[off].real();
639 for(sa_size_t k=0; k<mZColsP.size(); k++)
640 mVarD[mZColIdx[k]] = mZColsP[k]->GetCstSegment(bid)[off].real();
641 for(sa_size_t k=0; k<mSColsP.size(); k++)
642 mVarD[mSColIdx[k]] = atof(mSColsP[k]->GetCstSegment(bid)[off].c_str());
643
644 return mVarD;
645}
646
647
648r_8 BaseDataTable::GetCell(sa_size_t n, sa_size_t k) const
649{
650 if ((n < 0) || (n >= NEntry()))
651 throw RangeCheckError("BaseDataTable::GetCell() out of range line index n");
652 if ((k < 0) || (k >= NVar()))
653 throw RangeCheckError("BaseDataTable::GetCell() out of range column index k");
654 double rv = BADVAL;
655 sa_size_t sk = mNames[k].ser;
656 sa_size_t bid = n/mSegSz;
657 sa_size_t off = n%mSegSz;
658
659 switch (mNames[k].type) {
660 case IntegerField :
661 rv = mIColsP[sk]->GetCstSegment(bid)[off];
662 break;
663 case LongField :
664 rv = mLColsP[sk]->GetCstSegment(bid)[off];
665 break;
666 case FloatField :
667 rv = mFColsP[sk]->GetCstSegment(bid)[off];
668 break;
669 case DoubleField :
670 case DateTimeField :
671 rv = mDColsP[sk]->GetCstSegment(bid)[off];
672 break;
673 case ComplexField :
674 rv = mYColsP[sk]->GetCstSegment(bid)[off].real();
675 break;
676 case DoubleComplexField :
677 rv = mZColsP[sk]->GetCstSegment(bid)[off].real();
678 break;
679 case StringField :
680 rv = atof(mSColsP[sk]->GetCstSegment(bid)[off].c_str());
681 break;
682 default:
683 rv = BADVAL;
684 break;
685 }
686 return rv ;
687}
688
689
690r_8 BaseDataTable::GetCell(sa_size_t n, string const& nom) const
691{
692 return GetCell(n, IndexNom(nom));
693}
694
695string BaseDataTable::GetCelltoString(sa_size_t n, sa_size_t k) const
696{
697 if ((n < 0) || (n >= NEntry()))
698 throw RangeCheckError("BaseDataTable::GetCell() out of range line index n");
699 if ((k < 0) || (k >= NVar()))
700 throw RangeCheckError("BaseDataTable::GetCell() out of range column index k");
701 MuTyV rv;;
702 sa_size_t sk = mNames[k].ser;
703 sa_size_t bid = n/mSegSz;
704 sa_size_t off = n%mSegSz;
705 switch (mNames[k].type) {
706 case IntegerField :
707 rv = mIColsP[sk]->GetCstSegment(bid)[off];
708 break;
709 case LongField :
710 rv = mLColsP[sk]->GetCstSegment(bid)[off];
711 break;
712 case FloatField :
713 rv = mFColsP[sk]->GetCstSegment(bid)[off];
714 break;
715 case DoubleField :
716 rv = mDColsP[sk]->GetCstSegment(bid)[off];
717 break;
718 case ComplexField :
719 rv = mYColsP[sk]->GetCstSegment(bid)[off];
720 break;
721 case DoubleComplexField :
722 rv = mZColsP[sk]->GetCstSegment(bid)[off];
723 break;
724 case StringField :
725 rv = mSColsP[sk]->GetCstSegment(bid)[off];
726 break;
727 case DateTimeField :
728 rv = TimeStamp(mDColsP[sk]->GetCstSegment(bid)[off]);
729 break;
730 default:
731 rv = " ";
732 break;
733 }
734 return (string)rv ;
735}
736
737void BaseDataTable::GetMinMax(sa_size_t k, double& min, double& max) const
738{
739 min = 9E39 ; max = -9E39 ;
740 if ((k < 0) || (k >= NVar()))
741 throw RangeCheckError("BaseDataTable::GetCell() out of range column index k");
742 if (mMinMaxNEnt.size() < NVar()) {
743 mMin.clear();
744 mMax.clear();
745 mMinMaxNEnt.clear();
746 for(size_t kk=0; kk<NVar(); kk++) {
747 mMin.push_back(0.);
748 mMax.push_back(0.);
749 mMinMaxNEnt.push_back(0);
750 }
751 }
752 if (mMinMaxNEnt[k] == mNEnt) {
753 min = mMin[k];
754 max = mMax[k];
755 return;
756 }
757 sa_size_t sk = mNames[k].ser;
758
759 sa_size_t cnt = 0;
760 switch (mNames[k].type) {
761 case IntegerField :
762 for(size_t is=0; is<mIColsP[sk]->NbSegments(); is++) {
763 const int_4* sp = mIColsP[sk]->GetCstSegment(is);
764 for(size_t n=0; n<mIColsP[sk]->SegmentSize(); n++) {
765 if (cnt >= NEntry()) break;
766 if (sp[n] > max) max = sp[n];
767 if (sp[n] < min) min = sp[n];
768 cnt++;
769 }
770 }
771
772 break;
773 case LongField :
774 for(size_t is=0; is<mLColsP[sk]->NbSegments(); is++) {
775 const int_8* sp = mLColsP[sk]->GetCstSegment(is);
776 for(size_t n=0; n<mLColsP[sk]->SegmentSize(); n++) {
777 if (cnt >= NEntry()) break;
778 if (sp[n] > max) max = sp[n];
779 if (sp[n] < min) min = sp[n];
780 cnt++;
781 }
782 }
783 break;
784 case FloatField :
785 for(size_t is=0; is<mFColsP[sk]->NbSegments(); is++) {
786 const r_4* sp = mFColsP[sk]->GetCstSegment(is);
787 for(size_t n=0; n<mFColsP[sk]->SegmentSize(); n++) {
788 if (cnt >= NEntry()) break;
789 if (sp[n] > max) max = sp[n];
790 if (sp[n] < min) min = sp[n];
791 cnt++;
792 }
793 }
794 break;
795 case DoubleField :
796 case DateTimeField :
797 for(size_t is=0; is<mDColsP[sk]->NbSegments(); is++) {
798 const r_8* sp = mDColsP[sk]->GetCstSegment(is);
799 for(size_t n=0; n<mDColsP[sk]->SegmentSize(); n++) {
800 if (cnt >= NEntry()) break;
801 if (sp[n] > max) max = sp[n];
802 if (sp[n] < min) min = sp[n];
803 cnt++;
804 }
805 }
806 break;
807 case ComplexField :
808 for(size_t is=0; is<mYColsP[sk]->NbSegments(); is++) {
809 const complex<r_4> * sp = mYColsP[sk]->GetCstSegment(is);
810 for(size_t n=0; n<mYColsP[sk]->SegmentSize(); n++) {
811 if (cnt >= NEntry()) break;
812 if (sp[n].real() > max) max = sp[n].real();
813 if (sp[n].real() < min) min = sp[n].real();
814 cnt++;
815 }
816 }
817 break;
818 case DoubleComplexField :
819 for(size_t is=0; is<mZColsP[sk]->NbSegments(); is++) {
820 const complex<r_8> * sp = mZColsP[sk]->GetCstSegment(is);
821 for(size_t n=0; n<mZColsP[sk]->SegmentSize(); n++) {
822 if (cnt >= NEntry()) break;
823 if (sp[n].real() > max) max = sp[n].real();
824 if (sp[n].real() < min) min = sp[n].real();
825 cnt++;
826 }
827 }
828 break;
829 case StringField :
830 return;
831 break;
832 default:
833 return;
834 break;
835 }
836
837 mMinMaxNEnt[k] = cnt;
838 mMin[k] = min;
839 mMax[k] = max;
840 return ;
841}
842
843
844void BaseDataTable::GetMinMax(string const & nom, double& min, double& max) const
845{
846 GetMinMax(IndexNom(nom), min, max) ;
847}
848
849
850sa_size_t BaseDataTable::ColumnIndex(string const& nom) const
851{
852 return IndexNom(nom) ;
853}
854
855
856string BaseDataTable::ColumnName(sa_size_t k) const
857{
858 return NomIndex(k) ;
859}
860
861
862string BaseDataTable::VarList_C(const char* nomx) const
863{
864 string rets="";
865 sa_size_t i;
866 for(i=0; i<NVar(); i++) {
867 if ( (i%5 == 0) && (i > 0) ) rets += ";";
868 if (i%5 == 0) rets += "\ndouble ";
869 else rets += ",";
870 rets += mNames[i].nom;
871 }
872 rets += "; \n";
873 if (nomx) {
874 char buff[256];
875 for(i=0; i<NVar(); i++) {
876 rets += mNames[i].nom;
877 rets += '=';
878
879 sprintf(buff,"%s[%ld]; ", nomx, (long)i);
880 rets += buff;
881 if ( (i%3 == 0) && (i > 0) ) rets += "\n";
882 }
883 }
884 return(rets);
885}
886
887
888string BaseDataTable::LineHeaderToString() const
889{
890 string rets,s;
891
892 for(int i=0; i<NVar(); i++) {
893 s = mNames[i].nom;
894 size_t l = s.length();
895 for(size_t ii=l; ii<12; ii++) s += ' ';
896 if (i > 0) rets += ' ';
897 rets += s;
898 }
899 return(rets);
900}
901
902/*!
903 Return a table row (line) as a string
904 \sa TableRowToString()
905*/
906string BaseDataTable::LineToString(sa_size_t n) const
907{
908 return TableRowToString(n, false);
909}
910
911/*!
912 \param n : table row index ( 0 ... NEntry()-1)
913 \param qstr : if true , enclose strings in quotes ''
914 \param sep : separates fields using \b sep
915 \param fw : minimum field width
916 */
917string BaseDataTable::TableRowToString(sa_size_t n, bool qstr,
918 const char* sep, int fw) const
919{
920 if ((n < 0) || (n >= NEntry()))
921 throw RangeCheckError("BaseDataTable::GetCell() out of range line index n");
922 string rs;
923 MuTyV rv;;
924 sa_size_t bid = n/mSegSz;
925 sa_size_t off = n%mSegSz;
926 for(sa_size_t k=0; k<NVar(); k++) {
927 sa_size_t sk = mNames[k].ser;
928 switch (mNames[k].type) {
929 case IntegerField :
930 rv = mIColsP[sk]->GetCstSegment(bid)[off];
931 break;
932 case LongField :
933 rv = mLColsP[sk]->GetCstSegment(bid)[off];
934 break;
935 case FloatField :
936 rv = mFColsP[sk]->GetCstSegment(bid)[off];
937 break;
938 case DoubleField :
939 rv = mDColsP[sk]->GetCstSegment(bid)[off];
940 break;
941 case ComplexField :
942 rv = mYColsP[sk]->GetCstSegment(bid)[off];
943 break;
944 case DoubleComplexField :
945 rv = mZColsP[sk]->GetCstSegment(bid)[off];
946 break;
947 case StringField :
948 rv = mSColsP[sk]->GetCstSegment(bid)[off];
949 break;
950 case DateTimeField :
951 rv = TimeStamp(mDColsP[sk]->GetCstSegment(bid)[off]);
952 break;
953 default:
954 rv = " ";
955 break;
956 }
957 string s;
958 if ( (mNames[k].type == StringField) && (qstr) ) {
959 s = '\''; s += (string)rv; s += '\'';
960 }
961 else s= (string)rv;
962 size_t l = s.length();
963 for(size_t ii=l; ii<fw; ii++) s += ' ';
964 if (k > 0) rs += sep;
965 rs += s;
966 }
967 return rs;
968}
969
Note: See TracBrowser for help on using the repository browser.