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

Last change on this file since 2822 was 2808, checked in by ansari, 20 years ago

MAJ documentation - Reza 14/6/2005

File size: 16.3 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
13string BaseDataTable::ColTypeToString(FieldType ft, bool fgl)
14{
15 string rs;
16 switch (ft) {
17 case IntegerField :
18 if (fgl) rs = "Integer";
19 else rs = "I";
20 break;
21 case LongField :
22 if (fgl) rs = "Long Integer";
23 else rs = "L";
24 break;
25 case FloatField :
26 if (fgl) rs = "Float";
27 else rs = "F";
28 break;
29 case DoubleField :
30 if (fgl) rs = "Double";
31 else rs = "D";
32 break;
33 case ComplexField :
34 if (fgl) rs = "Complex";
35 else rs = "Zx4";
36 break;
37 case DoubleComplexField :
38 if (fgl) rs = "DoubleComplex";
39 else rs = "Zx8";
40 break;
41 case StringField :
42 if (fgl) rs = "String";
43 else rs = "S";
44 break;
45 case DateField :
46 if (fgl) rs = "Date";
47 else rs = "Date";
48 break;
49 default:
50 rs = "??";
51 break;
52 }
53 return rs;
54}
55
56/* Constructeur */
57BaseDataTable::BaseDataTable(sa_size_t segsz)
58{
59 mNEnt = 0;
60 mSegSz = (segsz > 0) ? segsz : 16;
61 mNSeg = 0;
62 mVarD = NULL;
63 mVarMTV = NULL;
64 mInfo = NULL;
65}
66
67BaseDataTable::~BaseDataTable()
68{
69 if (mVarD) delete[] mVarD;
70 if (mVarMTV) delete[] mVarMTV;
71 if (mInfo) delete mInfo;
72}
73
74sa_size_t BaseDataTable::CopyStructure(BaseDataTable const & a)
75{
76 if (NVar() > 0)
77 throw ParmError("BaseDataTable::CopyStructure() Table already has columns");
78 if (a.NVar() == 0) {
79 cout << "BaseDataTable::CopyStructure(a)/Warning Table a is not initialized" << endl;
80 return 0;
81 }
82 for (size_t kk=0; kk<a.mNames.size(); kk++)
83 AddColumn(a.mNames[kk].type, a.mNames[kk].nom);
84 return NVar();
85}
86
87//! return true is same structure
88bool BaseDataTable::CompareStructure(BaseDataTable const & a)
89{
90 if (NVar() != a.NVar()) return false;
91 for (size_t kk=0; kk<mNames.size(); kk++)
92 if ( (mNames[kk].type != a.mNames[kk].type) ||
93 (mNames[kk].nom != a.mNames[kk].nom) ) return false;
94 return true;
95}
96
97bool BaseDataTable::CheckColName(string const & cnom)
98{
99 size_t l,k;
100 l = cnom.length();
101 if (l < 1)
102 throw ParmError("BaseDataTable::CheckColName() zero length column name");
103 if (!isalpha(cnom[0]))
104 throw ParmError("BaseDataTable::CheckColName() first character not alphabetical");
105 for(k=1; k<l; k++)
106 if ((!isalnum(cnom[k])) && (cnom[k] != '_'))
107 throw ParmError("BaseDataTable::CheckColName() Non alphanumeric char in name");
108 for(k=0; k<mNames.size(); k++)
109 if (cnom == mNames[k].nom)
110 throw ParmError("BaseDataTable::CheckColName() already existing name");
111 return true;
112}
113
114//
115// A quel index correspond mon nom ?
116//
117sa_size_t BaseDataTable::IndexNom(char const* nom) const
118{
119 for(sa_size_t k=0; k<NVar(); k++)
120 if ( mNames[k].nom == nom ) return k;
121 return -1;
122 // Reza:Avril 2005 : PINtuple se base sur le renvoi de -1 et pas d'une exception
123 // throw NotFoundExc("BaseDataTable::IndexNom() : column name not found ");
124}
125
126string BaseDataTable::NomIndex(sa_size_t k) const
127{
128 if ((k < 0) || (k >= NVar()))
129 throw RangeCheckError("BaseDataTable::NomIndex() out of range column index k");
130 return mNames[k].nom ;
131}
132
133//! Adds a line (or row to the table) with r_8* inout data
134/*!
135 The data to be added is provided as an array (vector) of double (r_8).
136 The necessary data conversion is performed, depending on each
137 column's data typeconverted to the data type.
138 Return the new number of table rows (lines / entries)
139 \param data : Data for each cell of the row to be appended
140 (data[k] k=0..NbColumns())
141*/
142sa_size_t BaseDataTable::AddLine(const r_8* data)
143{
144 if (NVar() == 0)
145 throw ParmError("BaseDataTable::AddLine(const r_8*) Table has no column !");
146 if (NEntry() == SegmentSize()*NbSegments()) Extend();
147 sa_size_t n = NEntry();
148 sa_size_t bid = n/mSegSz;
149 sa_size_t off = n%mSegSz;
150 for(sa_size_t k=0; k<mIColsP.size(); k++)
151 mIColsP[k]->GetSegment(bid)[off] = (int_4)data[mIColIdx[k]];
152 for(sa_size_t k=0; k<mLColsP.size(); k++)
153 mLColsP[k]->GetSegment(bid)[off] = (int_8)data[mLColIdx[k]];
154 for(sa_size_t k=0; k<mFColsP.size(); k++)
155 mFColsP[k]->GetSegment(bid)[off] = (r_4)data[mFColIdx[k]];
156 for(sa_size_t k=0; k<mDColsP.size(); k++)
157 mDColsP[k]->GetSegment(bid)[off] = data[mDColIdx[k]];
158 for(sa_size_t k=0; k<mSColsP.size(); k++)
159 mSColsP[k]->GetSegment(bid)[off] = (string)MuTyV(data[mSColIdx[k]]);
160
161 mNEnt++;
162 return mNEnt;
163}
164
165//! Adds a line (or row to the table) with input data as an array of MuTyV
166/*!
167 The data to be added is provided as an array (vector) of MuTyV.
168 The MuTyV class conversion operators are used to match against each
169 cell data type.
170 Return the new number of table rows (lines / entries)
171 \param data : Data (MuTyV*) for each cell of the row to be appended
172 (data[k] k=0..NbColumns())
173*/
174sa_size_t BaseDataTable::AddLine(const MuTyV* data)
175{
176 if (NVar() == 0)
177 throw ParmError("BaseDataTable::AddLine(const MuTyV*) Table has no column !");
178 if (NEntry() == SegmentSize()*NbSegments()) Extend();
179 sa_size_t n = NEntry();
180 sa_size_t bid = n/mSegSz;
181 sa_size_t off = n%mSegSz;
182 for(sa_size_t k=0; k<mIColsP.size(); k++)
183 mIColsP[k]->GetSegment(bid)[off] = (int_4)data[mIColIdx[k]];
184 for(sa_size_t k=0; k<mLColsP.size(); k++)
185 mLColsP[k]->GetSegment(bid)[off] = (int_8)data[mLColIdx[k]];
186 for(sa_size_t k=0; k<mSColsP.size(); k++)
187 mSColsP[k]->GetSegment(bid)[off] = (string)data[mSColIdx[k]];
188 for(sa_size_t k=0; k<mFColsP.size(); k++)
189 mFColsP[k]->GetSegment(bid)[off] = (r_4)data[mFColIdx[k]];
190 for(sa_size_t k=0; k<mDColsP.size(); k++)
191 mDColsP[k]->GetSegment(bid)[off] = (r_8)data[mDColIdx[k]];
192
193 mNEnt++;
194 return mNEnt;
195}
196
197sa_size_t BaseDataTable::Extend()
198{
199 for(sa_size_t k=0; k<mIColsP.size(); k++)
200 mIColsP[k]->Extend();
201 for(sa_size_t k=0; k<mLColsP.size(); k++)
202 mLColsP[k]->Extend();
203 for(sa_size_t k=0; k<mFColsP.size(); k++)
204 mFColsP[k]->Extend();
205 for(sa_size_t k=0; k<mDColsP.size(); k++)
206 mDColsP[k]->Extend();
207 for(sa_size_t k=0; k<mSColsP.size(); k++)
208 mSColsP[k]->Extend();
209 mNSeg++;
210 return mNSeg;
211}
212
213
214MuTyV* BaseDataTable::GetLine(sa_size_t n) const
215{
216 if ((n < 0) || (n >= NEntry()))
217 throw RangeCheckError("BaseDataTable::GetLine() out of range line index n");
218 if (mVarMTV == NULL) mVarMTV = new MuTyV[NVar()];
219
220 sa_size_t bid = n/mSegSz;
221 sa_size_t off = n%mSegSz;
222 for(sa_size_t k=0; k<mIColsP.size(); k++)
223 mVarMTV[mIColIdx[k]] = mIColsP[k]->GetCstSegment(bid)[off];
224 for(sa_size_t k=0; k<mLColsP.size(); k++)
225 mVarMTV[mLColIdx[k]] = mLColsP[k]->GetCstSegment(bid)[off];
226 for(sa_size_t k=0; k<mFColsP.size(); k++)
227 mVarMTV[mFColIdx[k]] = mFColsP[k]->GetCstSegment(bid)[off];
228 for(sa_size_t k=0; k<mDColsP.size(); k++)
229 mVarMTV[mDColIdx[k]] = mDColsP[k]->GetCstSegment(bid)[off];
230 for(sa_size_t k=0; k<mSColsP.size(); k++)
231 mVarMTV[mSColIdx[k]] = atof(mSColsP[k]->GetCstSegment(bid)[off].c_str());
232
233 return mVarMTV;
234}
235
236void BaseDataTable::CopyMerge(BaseDataTable const& a, bool cp)
237{
238 if (cp && (NEntry() > 0) )
239 throw ParmError("BaseDataTable::CopyMerge(a) Table has entries already");
240 if (a.NVar() == 0) throw ParmError("BaseDataTable::CopyMerge(a) Table a has no column");
241 if (NVar() == 0) CopyStructure(a);
242 else if (!CompareStructure(a))
243 throw SzMismatchError("BaseDataTable::CopyMerge(a) (this,a) have different table structure");
244 if (a.NEntry() == 0) {
245 cout << " BaseDataTable::CopyMerge(a)/Warning : table a has zero (0) entry ! " << endl;
246 return;
247 }
248 for(sa_size_t kk=0; kk<a.NEntry(); kk++)
249 AddLine(a.GetLine(kk));
250}
251
252
253//! Returns the associated DVList object
254DVList& BaseDataTable::Info() const
255{
256 if (mInfo == NULL) mInfo = new DVList;
257 return(*mInfo);
258}
259
260void BaseDataTable::Print(int num, int nmax) const
261{
262 // A faire
263 return;
264}
265
266/*! In addition to printing the number of entries and column names,
267 this method prints also minimum/maximum value for each column.
268 This information might be computed when the Show() method is called.
269 This may take some time for tables with large number of entries (>~ 10^6)
270*/
271void BaseDataTable::Show(ostream& os) const
272{
273 os << "BaseDataTable: NVar= " << NVar() << " NEnt= " << NEntry()
274 << " ( SegSize= " << SegmentSize() << " NbSegments= "
275 << NbSegments() << " )" << endl;
276 os << "--------------------------------------------------------------------" << endl;
277 os << setw(3) << "i" << ":" << setw(20) << " Name" << " ("
278 << setw(4) << "Type" << ") | "
279 << setw(15) << " Min " << " | " << setw(15) << " Max " << endl;
280 os << "--------------------------------------------------------------------" << endl;
281 r_8 min, max ;
282 for(sa_size_t i = 0 ; i < NVar() ; i++) {
283 GetMinMax(i, min, max) ;
284 string nom;
285 if (mNames[i].nom.length() > 20)
286 nom = mNames[i].nom.substr(20);
287 else nom = mNames[i].nom;
288 os << setw(3) << i << ":" << setw(20) << nom << " ("
289 << setw(4) << ColTypeToString(mNames[i].type) << ") | "
290 << setw(15) << min << " | " << setw(15) << max << endl;
291 }
292 os << "--------------------------------------------------------------------" << endl;
293 return;
294}
295
296//! NOT YET IMPLEMENTED ! - Fills table from an ascii file
297int BaseDataTable::FillFromASCIIFile(string const& fn)
298// Remplit le ntuple a partir d'un fichier ASCII.
299// Renvoie le nombre de lignes ajoutees.
300{
301// a faire
302return(0);
303}
304
305
306
307//
308// ------------------------------------
309// ------- Interface NTuple -----------
310// ------------------------------------
311//
312sa_size_t BaseDataTable::NbLines() const
313{
314 return(NEntry());
315}
316
317sa_size_t BaseDataTable::NbColumns() const
318{
319 return(NVar());
320}
321
322r_8* BaseDataTable::GetLineD(sa_size_t n) const
323{
324 if ((n < 0) || (n >= NEntry()))
325 throw RangeCheckError("BaseDataTable::GetLineD() out of range line index n");
326 if (mVarD == NULL) mVarD = new r_8[NVar()];
327
328 sa_size_t bid = n/mSegSz;
329 sa_size_t off = n%mSegSz;
330 for(sa_size_t k=0; k<mIColsP.size(); k++)
331 mVarD[mIColIdx[k]] = mIColsP[k]->GetCstSegment(bid)[off];
332 for(sa_size_t k=0; k<mLColsP.size(); k++)
333 mVarD[mLColIdx[k]] = mLColsP[k]->GetCstSegment(bid)[off];
334 for(sa_size_t k=0; k<mFColsP.size(); k++)
335 mVarD[mFColIdx[k]] = mFColsP[k]->GetCstSegment(bid)[off];
336 for(sa_size_t k=0; k<mDColsP.size(); k++)
337 mVarD[mDColIdx[k]] = mDColsP[k]->GetCstSegment(bid)[off];
338 for(sa_size_t k=0; k<mSColsP.size(); k++)
339 mVarD[mSColIdx[k]] = atof(mSColsP[k]->GetCstSegment(bid)[off].c_str());
340
341 return mVarD;
342}
343
344#define BADVAL -1.e39
345
346r_8 BaseDataTable::GetCell(sa_size_t n, sa_size_t k) const
347{
348 if ((n < 0) || (n >= NEntry()))
349 throw RangeCheckError("BaseDataTable::GetCell() out of range line index n");
350 if ((k < 0) || (k >= NVar()))
351 throw RangeCheckError("BaseDataTable::GetCell() out of range column index k");
352 double rv = BADVAL;
353 sa_size_t sk = mNames[k].ser;
354 sa_size_t bid = n/mSegSz;
355 sa_size_t off = n%mSegSz;
356
357 switch (mNames[k].type) {
358 case IntegerField :
359 rv = mIColsP[sk]->GetCstSegment(bid)[off];
360 break;
361 case LongField :
362 rv = mLColsP[sk]->GetCstSegment(bid)[off];
363 break;
364 case FloatField :
365 rv = mFColsP[sk]->GetCstSegment(bid)[off];
366 break;
367 case DoubleField :
368 rv = mDColsP[sk]->GetCstSegment(bid)[off];
369 break;
370 case StringField :
371 rv = atof(mSColsP[sk]->GetCstSegment(bid)[off].c_str());
372 break;
373 default:
374 rv = BADVAL;
375 break;
376 }
377 return rv ;
378}
379
380
381r_8 BaseDataTable::GetCell(sa_size_t n, string const& nom) const
382{
383 return GetCell(n, IndexNom(nom));
384}
385
386string BaseDataTable::GetCelltoString(sa_size_t n, sa_size_t k) const
387{
388 if ((n < 0) || (n >= NEntry()))
389 throw RangeCheckError("BaseDataTable::GetCell() out of range line index n");
390 if ((k < 0) || (k >= NVar()))
391 throw RangeCheckError("BaseDataTable::GetCell() out of range column index k");
392 MuTyV rv;;
393 sa_size_t sk = mNames[k].ser;
394 sa_size_t bid = n/mSegSz;
395 sa_size_t off = n%mSegSz;
396 switch (mNames[k].type) {
397 case IntegerField :
398 rv = mIColsP[sk]->GetCstSegment(bid)[off];
399 break;
400 case LongField :
401 rv = mLColsP[sk]->GetCstSegment(bid)[off];
402 break;
403 case FloatField :
404 rv = mFColsP[sk]->GetCstSegment(bid)[off];
405 break;
406 case DoubleField :
407 rv = mDColsP[sk]->GetCstSegment(bid)[off];
408 break;
409 case StringField :
410 rv = mSColsP[sk]->GetCstSegment(bid)[off];
411 break;
412 default:
413 rv = " ";
414 break;
415 }
416 return (string)rv ;
417}
418
419void BaseDataTable::GetMinMax(sa_size_t k, double& min, double& max) const
420{
421 min = 9E39 ; max = -9E39 ;
422 if ((k < 0) || (k >= NVar()))
423 throw RangeCheckError("BaseDataTable::GetCell() out of range column index k");
424 if (mMinMaxNEnt.size() < NVar()) {
425 mMin.clear();
426 mMax.clear();
427 mMinMaxNEnt.clear();
428 for(size_t kk=0; kk<NVar(); kk++) {
429 mMin.push_back(0.);
430 mMax.push_back(0.);
431 mMinMaxNEnt.push_back(0);
432 }
433 }
434 if (mMinMaxNEnt[k] == mNEnt) {
435 min = mMin[k];
436 max = mMax[k];
437 return;
438 }
439 sa_size_t sk = mNames[k].ser;
440
441 sa_size_t cnt = 0;
442 switch (mNames[k].type) {
443 case IntegerField :
444 for(size_t is=0; is<mIColsP[sk]->NbSegments(); is++) {
445 const int_4* sp = mIColsP[sk]->GetCstSegment(is);
446 for(size_t n=0; n<mIColsP[sk]->SegmentSize(); n++) {
447 if (cnt >= NEntry()) break;
448 if (sp[n] > max) max = sp[n];
449 if (sp[n] < min) min = sp[n];
450 cnt++;
451 }
452 }
453
454 break;
455 case LongField :
456 for(size_t is=0; is<mLColsP[sk]->NbSegments(); is++) {
457 const int_8* sp = mLColsP[sk]->GetCstSegment(is);
458 for(size_t n=0; n<mLColsP[sk]->SegmentSize(); n++) {
459 if (cnt >= NEntry()) break;
460 if (sp[n] > max) max = sp[n];
461 if (sp[n] < min) min = sp[n];
462 cnt++;
463 }
464 }
465 break;
466 case FloatField :
467 for(size_t is=0; is<mFColsP[sk]->NbSegments(); is++) {
468 const r_4* sp = mFColsP[sk]->GetCstSegment(is);
469 for(size_t n=0; n<mFColsP[sk]->SegmentSize(); n++) {
470 if (cnt >= NEntry()) break;
471 if (sp[n] > max) max = sp[n];
472 if (sp[n] < min) min = sp[n];
473 cnt++;
474 }
475 }
476 break;
477 case DoubleField :
478 for(size_t is=0; is<mDColsP[sk]->NbSegments(); is++) {
479 const r_8* sp = mDColsP[sk]->GetCstSegment(is);
480 for(size_t n=0; n<mDColsP[sk]->SegmentSize(); n++) {
481 if (cnt >= NEntry()) break;
482 if (sp[n] > max) max = sp[n];
483 if (sp[n] < min) min = sp[n];
484 cnt++;
485 }
486 }
487 break;
488 case StringField :
489 return;
490 break;
491 default:
492 return;
493 break;
494 }
495
496 mMinMaxNEnt[k] = cnt;
497 mMin[k] = min;
498 mMax[k] = max;
499 return ;
500}
501
502
503void BaseDataTable::GetMinMax(string const & nom, double& min, double& max) const
504{
505 GetMinMax(IndexNom(nom), min, max) ;
506}
507
508
509sa_size_t BaseDataTable::ColumnIndex(string const& nom) const
510{
511 return IndexNom(nom) ;
512}
513
514
515string BaseDataTable::ColumnName(sa_size_t k) const
516{
517 return NomIndex(k) ;
518}
519
520
521string BaseDataTable::VarList_C(const char* nomx) const
522{
523 string rets="";
524 sa_size_t i;
525 for(i=0; i<NVar(); i++) {
526 if ( (i%5 == 0) && (i > 0) ) rets += ";";
527 if (i%5 == 0) rets += "\ndouble ";
528 else rets += ",";
529 rets += mNames[i].nom;
530 }
531 rets += "; \n";
532 if (nomx) {
533 char buff[256];
534 for(i=0; i<NVar(); i++) {
535 rets += mNames[i].nom;
536 rets += '=';
537
538 sprintf(buff,"%s[%ld]; ", nomx, (long)i);
539 rets += buff;
540 if ( (i%3 == 0) && (i > 0) ) rets += "\n";
541 }
542 }
543 return(rets);
544}
545
546
547string BaseDataTable::LineHeaderToString() const
548{
549 string rets,s;
550
551 for(int i=0; i<NVar(); i++) {
552 s = mNames[i].nom;
553 s += ' ';
554 size_t l = s.length();
555 for(size_t ii=l; ii<10; ii++) s += ' ';
556 rets += s;
557 }
558 return(rets);
559}
560
561
562string BaseDataTable::LineToString(sa_size_t n) const
563{
564 if ((n < 0) || (n >= NEntry()))
565 throw RangeCheckError("BaseDataTable::GetCell() out of range line index n");
566 string rs;
567 MuTyV rv;;
568 sa_size_t bid = n/mSegSz;
569 sa_size_t off = n%mSegSz;
570 for(sa_size_t k=0; k<NVar(); k++) {
571 sa_size_t sk = mNames[k].ser;
572 switch (mNames[k].type) {
573 case IntegerField :
574 rv = mIColsP[sk]->GetCstSegment(bid)[off];
575 break;
576 case LongField :
577 rv = mLColsP[sk]->GetCstSegment(bid)[off];
578 break;
579 case FloatField :
580 rv = mFColsP[sk]->GetCstSegment(bid)[off];
581 break;
582 case DoubleField :
583 rv = mDColsP[sk]->GetCstSegment(bid)[off];
584 break;
585 case StringField :
586 rv = mSColsP[sk]->GetCstSegment(bid)[off];
587 break;
588 default:
589 rv = " ";
590 break;
591 }
592 string s = (string)rv;
593 s += ' ';
594 size_t l = s.length();
595 for(size_t ii=l; ii<10; ii++) s += ' ';
596 rs += s;
597 }
598 return rs;
599}
600
Note: See TracBrowser for help on using the repository browser.