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

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

Ajout methode BaseDataTable::CheckCorrectColName() pour correction des noms de colonnes (pour lecture FITS en particulier), Reza 2/6/2006

File size: 28.2 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(); j++,i++)
436 rv(i) = mIColsP[sk]->GetCstSegment(is)[j];
437 break;
438 case LongField :
439 for(sa_size_t j=0; j<SegmentSize(); j++,i++)
440 rv(i) = mLColsP[sk]->GetCstSegment(is)[j];
441 break;
442 case FloatField :
443 for(sa_size_t j=0; j<SegmentSize(); 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(); j++,i++)
449 rv(i) = mDColsP[sk]->GetCstSegment(is)[j];
450 break;
451 case ComplexField :
452 for(sa_size_t j=0; j<SegmentSize(); 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(); 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(); 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(); j++,i++) rv(i) = BADVAL;
465 break;
466 }
467 }
468 return rv ;
469}
470
471void BaseDataTable::CopyMerge(BaseDataTable const& a, bool cp)
472{
473 if (cp && (NEntry() > 0) )
474 throw ParmError("BaseDataTable::CopyMerge(a) Table has entries already");
475 if (a.NVar() == 0) throw ParmError("BaseDataTable::CopyMerge(a) Table a has no column");
476 if (NVar() == 0) CopyStructure(a);
477 else if (!CompareStructure(a))
478 throw SzMismatchError("BaseDataTable::CopyMerge(a) (this,a) have different table structure");
479 if (a.NEntry() == 0) {
480 cout << " BaseDataTable::CopyMerge(a)/Warning : table a has zero (0) entry ! " << endl;
481 return;
482 }
483 for(sa_size_t kk=0; kk<a.NEntry(); kk++)
484 AddRow(a.GetLine(kk));
485}
486
487
488//! Returns the associated DVList object
489DVList& BaseDataTable::Info() const
490{
491 if (mInfo == NULL) mInfo = new DVList;
492 return(*mInfo);
493}
494
495/*!
496 Formatted (text) output of the table, for lines lstart <= l_index < lend , with step lstep
497 \param os : output stream (formatted output)
498 \param lstart : start row (line) index
499 \param lend : end row (line) index
500 \param lstep : row index increment
501*/
502ostream& BaseDataTable::Print(ostream& os, sa_size_t lstart, sa_size_t lend, sa_size_t lstep) const
503{
504 os << "##### BaseDataTable::Print() - Table(NRow=" << NEntry() << " , NCol="
505 << NVar() << ") ##### " << endl;
506 os << "#! " ;
507 for (size_t i=0; i<NVar(); i++) {
508 string nom = mNames[i].nom;
509 nom += ':'; nom += ColTypeToString(mNames[i].type);
510 os << setw(12) << nom << " ";
511 }
512 os << endl;
513 os << "##########################################################################" << endl;
514 for (sa_size_t l=lstart; l<lend; l+=lstep)
515 os << TableRowToString(l, true) << endl;
516 return os;
517}
518
519/*! In addition to printing the number of entries and column names,
520 this method prints also minimum/maximum value for each column.
521 This information might be computed when the Show() method is called.
522 This may take some time for tables with large number of entries (>~ 10^6)
523*/
524void BaseDataTable::Show(ostream& os) const
525{
526 os << "BaseDataTable: NVar= " << NVar() << " NEnt= " << NEntry()
527 << " ( SegSize= " << SegmentSize() << " NbSegments= "
528 << NbSegments() << " )" << endl;
529 os << "--------------------------------------------------------------------" << endl;
530 os << setw(3) << "i" << ":" << setw(20) << " Name" << " ("
531 << setw(4) << "Type" << ") | "
532 << setw(15) << " Min " << " | " << setw(15) << " Max " << endl;
533 os << "--------------------------------------------------------------------" << endl;
534 r_8 min, max ;
535 for(sa_size_t i = 0 ; i < NVar() ; i++) {
536 GetMinMax(i, min, max) ;
537 string nom;
538 if (mNames[i].nom.length() > 20)
539 nom = mNames[i].nom.substr(20);
540 else nom = mNames[i].nom;
541 os << setw(3) << i << ":" << setw(20) << nom << " ("
542 << setw(4) << ColTypeToString(mNames[i].type) << ") | "
543 << setw(15) << min << " | " << setw(15) << max << endl;
544 }
545 os << "--------------------------------------------------------------------" << endl;
546 return;
547}
548
549//! Fills table from an ascii (text) file
550/*
551 Return number of non empt lines (added to table)
552 \param is : input ascii (text) stream
553 \param clm : Lines starting with clm are ignored (comments)
554 \param sep : separator between different fields (columns)
555*/
556sa_size_t BaseDataTable::FillFromASCIIFile(istream& is, char clm, const char* sep)
557{
558 string str;
559 if (mVarMTV == NULL) mVarMTV = new MuTyV[NVar()];
560 sa_size_t iv, nl;
561 nl = 0;
562 while (!is.eof()) {
563 str = "";
564 getline(is, str);
565 if (is.good() || is.eof()) {
566 size_t l = str.length();
567 if ((l == 0) || (str[0]==clm)) continue;
568 for(iv=0; iv<NVar(); iv++) mVarMTV[iv] = 0.;
569 iv = 0;
570 size_t q = 0;
571 size_t p = 0;
572 while ( (q < l) && (iv < NVar()) ) {
573 p = str.find_first_not_of(sep,q);
574 if (p >= l) break;
575 if (str[p] == '\'') { // Decodage d'un string
576 q = str.find('\'',p+1);
577 if (q < l) {
578 mVarMTV[iv] = str.substr(p+1,q-p-1);
579 q++;
580 }
581 else mVarMTV[iv] = str.substr(p+1,l-p-1);
582 iv++;
583 }
584 else {
585 q = str.find_first_of(sep,p);
586 if (q > l) q = l;
587 mVarMTV[iv] = str.substr(p,q-p);
588 iv++;
589 }
590 if (mNames[iv-1].type == DateTimeField) {
591 string tts = (string)mVarMTV[iv-1];
592 mVarMTV[iv-1] = TimeStamp(tts);
593 }
594 }
595 AddRow(mVarMTV);
596 nl++;
597 }
598 } // Fin boucle lignes fichier
599 cout << "BaseDataTable::FillFromASCIIFile()/Info: " << nl << " lines decoded from stream " << endl;
600 return(nl);
601}
602
603
604
605//
606// ------------------------------------
607// ------- Interface NTuple -----------
608// ------------------------------------
609//
610sa_size_t BaseDataTable::NbLines() const
611{
612 return(NEntry());
613}
614
615sa_size_t BaseDataTable::NbColumns() const
616{
617 return(NVar());
618}
619
620r_8* BaseDataTable::GetLineD(sa_size_t n) const
621{
622 if ((n < 0) || (n >= NEntry()))
623 throw RangeCheckError("BaseDataTable::GetLineD() out of range line index n");
624 if (mVarD == NULL) mVarD = new r_8[NVar()];
625
626 sa_size_t bid = n/mSegSz;
627 sa_size_t off = n%mSegSz;
628 for(sa_size_t k=0; k<mIColsP.size(); k++)
629 mVarD[mIColIdx[k]] = mIColsP[k]->GetCstSegment(bid)[off];
630 for(sa_size_t k=0; k<mLColsP.size(); k++)
631 mVarD[mLColIdx[k]] = mLColsP[k]->GetCstSegment(bid)[off];
632 for(sa_size_t k=0; k<mFColsP.size(); k++)
633 mVarD[mFColIdx[k]] = mFColsP[k]->GetCstSegment(bid)[off];
634 for(sa_size_t k=0; k<mDColsP.size(); k++)
635 mVarD[mDColIdx[k]] = mDColsP[k]->GetCstSegment(bid)[off];
636 for(sa_size_t k=0; k<mYColsP.size(); k++)
637 mVarD[mYColIdx[k]] = mYColsP[k]->GetCstSegment(bid)[off].real();
638 for(sa_size_t k=0; k<mZColsP.size(); k++)
639 mVarD[mZColIdx[k]] = mZColsP[k]->GetCstSegment(bid)[off].real();
640 for(sa_size_t k=0; k<mSColsP.size(); k++)
641 mVarD[mSColIdx[k]] = atof(mSColsP[k]->GetCstSegment(bid)[off].c_str());
642
643 return mVarD;
644}
645
646
647r_8 BaseDataTable::GetCell(sa_size_t n, sa_size_t k) const
648{
649 if ((n < 0) || (n >= NEntry()))
650 throw RangeCheckError("BaseDataTable::GetCell() out of range line index n");
651 if ((k < 0) || (k >= NVar()))
652 throw RangeCheckError("BaseDataTable::GetCell() out of range column index k");
653 double rv = BADVAL;
654 sa_size_t sk = mNames[k].ser;
655 sa_size_t bid = n/mSegSz;
656 sa_size_t off = n%mSegSz;
657
658 switch (mNames[k].type) {
659 case IntegerField :
660 rv = mIColsP[sk]->GetCstSegment(bid)[off];
661 break;
662 case LongField :
663 rv = mLColsP[sk]->GetCstSegment(bid)[off];
664 break;
665 case FloatField :
666 rv = mFColsP[sk]->GetCstSegment(bid)[off];
667 break;
668 case DoubleField :
669 case DateTimeField :
670 rv = mDColsP[sk]->GetCstSegment(bid)[off];
671 break;
672 case ComplexField :
673 rv = mYColsP[sk]->GetCstSegment(bid)[off].real();
674 break;
675 case DoubleComplexField :
676 rv = mZColsP[sk]->GetCstSegment(bid)[off].real();
677 break;
678 case StringField :
679 rv = atof(mSColsP[sk]->GetCstSegment(bid)[off].c_str());
680 break;
681 default:
682 rv = BADVAL;
683 break;
684 }
685 return rv ;
686}
687
688
689r_8 BaseDataTable::GetCell(sa_size_t n, string const& nom) const
690{
691 return GetCell(n, IndexNom(nom));
692}
693
694string BaseDataTable::GetCelltoString(sa_size_t n, sa_size_t k) const
695{
696 if ((n < 0) || (n >= NEntry()))
697 throw RangeCheckError("BaseDataTable::GetCell() out of range line index n");
698 if ((k < 0) || (k >= NVar()))
699 throw RangeCheckError("BaseDataTable::GetCell() out of range column index k");
700 MuTyV rv;;
701 sa_size_t sk = mNames[k].ser;
702 sa_size_t bid = n/mSegSz;
703 sa_size_t off = n%mSegSz;
704 switch (mNames[k].type) {
705 case IntegerField :
706 rv = mIColsP[sk]->GetCstSegment(bid)[off];
707 break;
708 case LongField :
709 rv = mLColsP[sk]->GetCstSegment(bid)[off];
710 break;
711 case FloatField :
712 rv = mFColsP[sk]->GetCstSegment(bid)[off];
713 break;
714 case DoubleField :
715 rv = mDColsP[sk]->GetCstSegment(bid)[off];
716 break;
717 case ComplexField :
718 rv = mYColsP[sk]->GetCstSegment(bid)[off];
719 break;
720 case DoubleComplexField :
721 rv = mZColsP[sk]->GetCstSegment(bid)[off];
722 break;
723 case StringField :
724 rv = mSColsP[sk]->GetCstSegment(bid)[off];
725 break;
726 case DateTimeField :
727 rv = TimeStamp(mDColsP[sk]->GetCstSegment(bid)[off]);
728 break;
729 default:
730 rv = " ";
731 break;
732 }
733 return (string)rv ;
734}
735
736void BaseDataTable::GetMinMax(sa_size_t k, double& min, double& max) const
737{
738 min = 9E39 ; max = -9E39 ;
739 if ((k < 0) || (k >= NVar()))
740 throw RangeCheckError("BaseDataTable::GetCell() out of range column index k");
741 if (mMinMaxNEnt.size() < NVar()) {
742 mMin.clear();
743 mMax.clear();
744 mMinMaxNEnt.clear();
745 for(size_t kk=0; kk<NVar(); kk++) {
746 mMin.push_back(0.);
747 mMax.push_back(0.);
748 mMinMaxNEnt.push_back(0);
749 }
750 }
751 if (mMinMaxNEnt[k] == mNEnt) {
752 min = mMin[k];
753 max = mMax[k];
754 return;
755 }
756 sa_size_t sk = mNames[k].ser;
757
758 sa_size_t cnt = 0;
759 switch (mNames[k].type) {
760 case IntegerField :
761 for(size_t is=0; is<mIColsP[sk]->NbSegments(); is++) {
762 const int_4* sp = mIColsP[sk]->GetCstSegment(is);
763 for(size_t n=0; n<mIColsP[sk]->SegmentSize(); n++) {
764 if (cnt >= NEntry()) break;
765 if (sp[n] > max) max = sp[n];
766 if (sp[n] < min) min = sp[n];
767 cnt++;
768 }
769 }
770
771 break;
772 case LongField :
773 for(size_t is=0; is<mLColsP[sk]->NbSegments(); is++) {
774 const int_8* sp = mLColsP[sk]->GetCstSegment(is);
775 for(size_t n=0; n<mLColsP[sk]->SegmentSize(); n++) {
776 if (cnt >= NEntry()) break;
777 if (sp[n] > max) max = sp[n];
778 if (sp[n] < min) min = sp[n];
779 cnt++;
780 }
781 }
782 break;
783 case FloatField :
784 for(size_t is=0; is<mFColsP[sk]->NbSegments(); is++) {
785 const r_4* sp = mFColsP[sk]->GetCstSegment(is);
786 for(size_t n=0; n<mFColsP[sk]->SegmentSize(); n++) {
787 if (cnt >= NEntry()) break;
788 if (sp[n] > max) max = sp[n];
789 if (sp[n] < min) min = sp[n];
790 cnt++;
791 }
792 }
793 break;
794 case DoubleField :
795 case DateTimeField :
796 for(size_t is=0; is<mDColsP[sk]->NbSegments(); is++) {
797 const r_8* sp = mDColsP[sk]->GetCstSegment(is);
798 for(size_t n=0; n<mDColsP[sk]->SegmentSize(); n++) {
799 if (cnt >= NEntry()) break;
800 if (sp[n] > max) max = sp[n];
801 if (sp[n] < min) min = sp[n];
802 cnt++;
803 }
804 }
805 break;
806 case ComplexField :
807 for(size_t is=0; is<mYColsP[sk]->NbSegments(); is++) {
808 const complex<r_4> * sp = mYColsP[sk]->GetCstSegment(is);
809 for(size_t n=0; n<mYColsP[sk]->SegmentSize(); n++) {
810 if (cnt >= NEntry()) break;
811 if (sp[n].real() > max) max = sp[n].real();
812 if (sp[n].real() < min) min = sp[n].real();
813 cnt++;
814 }
815 }
816 break;
817 case DoubleComplexField :
818 for(size_t is=0; is<mZColsP[sk]->NbSegments(); is++) {
819 const complex<r_8> * sp = mZColsP[sk]->GetCstSegment(is);
820 for(size_t n=0; n<mZColsP[sk]->SegmentSize(); n++) {
821 if (cnt >= NEntry()) break;
822 if (sp[n].real() > max) max = sp[n].real();
823 if (sp[n].real() < min) min = sp[n].real();
824 cnt++;
825 }
826 }
827 break;
828 case StringField :
829 return;
830 break;
831 default:
832 return;
833 break;
834 }
835
836 mMinMaxNEnt[k] = cnt;
837 mMin[k] = min;
838 mMax[k] = max;
839 return ;
840}
841
842
843void BaseDataTable::GetMinMax(string const & nom, double& min, double& max) const
844{
845 GetMinMax(IndexNom(nom), min, max) ;
846}
847
848
849sa_size_t BaseDataTable::ColumnIndex(string const& nom) const
850{
851 return IndexNom(nom) ;
852}
853
854
855string BaseDataTable::ColumnName(sa_size_t k) const
856{
857 return NomIndex(k) ;
858}
859
860
861string BaseDataTable::VarList_C(const char* nomx) const
862{
863 string rets="";
864 sa_size_t i;
865 for(i=0; i<NVar(); i++) {
866 if ( (i%5 == 0) && (i > 0) ) rets += ";";
867 if (i%5 == 0) rets += "\ndouble ";
868 else rets += ",";
869 rets += mNames[i].nom;
870 }
871 rets += "; \n";
872 if (nomx) {
873 char buff[256];
874 for(i=0; i<NVar(); i++) {
875 rets += mNames[i].nom;
876 rets += '=';
877
878 sprintf(buff,"%s[%ld]; ", nomx, (long)i);
879 rets += buff;
880 if ( (i%3 == 0) && (i > 0) ) rets += "\n";
881 }
882 }
883 return(rets);
884}
885
886
887string BaseDataTable::LineHeaderToString() const
888{
889 string rets,s;
890
891 for(int i=0; i<NVar(); i++) {
892 s = mNames[i].nom;
893 size_t l = s.length();
894 for(size_t ii=l; ii<12; ii++) s += ' ';
895 if (i > 0) rets += ' ';
896 rets += s;
897 }
898 return(rets);
899}
900
901/*!
902 Return a table row (line) as a string
903 \sa TableRowToString()
904*/
905string BaseDataTable::LineToString(sa_size_t n) const
906{
907 return TableRowToString(n, false);
908}
909
910/*!
911 \param n : table row index ( 0 ... NEntry()-1)
912 \param qstr : if true , enclose strings in quotes ''
913 \param sep : separates fields using \b sep
914 \param fw : minimum field width
915 */
916string BaseDataTable::TableRowToString(sa_size_t n, bool qstr,
917 const char* sep, int fw) const
918{
919 if ((n < 0) || (n >= NEntry()))
920 throw RangeCheckError("BaseDataTable::GetCell() out of range line index n");
921 string rs;
922 MuTyV rv;;
923 sa_size_t bid = n/mSegSz;
924 sa_size_t off = n%mSegSz;
925 for(sa_size_t k=0; k<NVar(); k++) {
926 sa_size_t sk = mNames[k].ser;
927 switch (mNames[k].type) {
928 case IntegerField :
929 rv = mIColsP[sk]->GetCstSegment(bid)[off];
930 break;
931 case LongField :
932 rv = mLColsP[sk]->GetCstSegment(bid)[off];
933 break;
934 case FloatField :
935 rv = mFColsP[sk]->GetCstSegment(bid)[off];
936 break;
937 case DoubleField :
938 rv = mDColsP[sk]->GetCstSegment(bid)[off];
939 break;
940 case ComplexField :
941 rv = mYColsP[sk]->GetCstSegment(bid)[off];
942 break;
943 case DoubleComplexField :
944 rv = mZColsP[sk]->GetCstSegment(bid)[off];
945 break;
946 case StringField :
947 rv = mSColsP[sk]->GetCstSegment(bid)[off];
948 break;
949 case DateTimeField :
950 rv = TimeStamp(mDColsP[sk]->GetCstSegment(bid)[off]);
951 break;
952 default:
953 rv = " ";
954 break;
955 }
956 string s;
957 if ( (mNames[k].type == StringField) && (qstr) ) {
958 s = '\''; s += (string)rv; s += '\'';
959 }
960 else s= (string)rv;
961 size_t l = s.length();
962 for(size_t ii=l; ii<fw; ii++) s += ' ';
963 if (k > 0) rs += sep;
964 rs += s;
965 }
966 return rs;
967}
968
Note: See TracBrowser for help on using the repository browser.