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

Last change on this file since 2847 was 2831, checked in by ansari, 20 years ago

1/ Prise en charge champ de type DateTimeField ds BaseDataTable , DataTable, SwPPFDataTable
2/ Methodes BaseDataTable completees - en particulier Print/WriteASCII, et
decodage de fichiers ASCII

Reza, 8 Nov 2005

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