source: Sophya/trunk/SophyaLib/HiStats/ntuple.cc@ 1447

Last change on this file since 1447 was 1405, checked in by ansari, 25 years ago

Ajout documentation - Reza 15/2/2001

File size: 14.1 KB
Line 
1#include <stdio.h>
2#include <string.h>
3
4#include "strutil.h"
5#include "perrors.h"
6#include "ntuple.h"
7
8
9#define BADVAL -1.e19
10#define LENNAME 8
11#define LENNAME1 (LENNAME+1)
12
13/*!
14 \class SOPHYA::NTuple
15 \ingroup HiStats
16 Simple NTuple class (a Table or 2-D data set) with floating value
17 columns.
18 \sa SOPHYA::ObjFileIO<NTuple>
19
20 \code
21 #include "ntuple.h"
22 // ...
23 char * names[3] = {"XPos", "YPos", "Val"};
24 // NTuple (Table) creation with 3 columns
25 NTuple nt(3, names);
26 // Filling the NTuple
27 r_4 x[3];
28 for(int i=0; i<63; i++) {
29 x[0] = (i%9)-4.; x[1] = (i/9)-3.; x[2] = x[0]*x[0]+x[1]*x[1];
30 nt.Fill(x);
31 }
32 // Printing table info
33 cout << nt ;
34 // Saving object into a PPF file
35 POutPersist po("nt.ppf");
36 po << nt ;
37 \endcode
38*/
39
40//++
41// Class NTuple
42// Lib Outils++
43// include ntuple.h
44//
45// Classe de ntuples
46//--
47//++
48// Links Parents
49// PPersist
50// NTupleInterface
51//--
52
53/* --Methode-- */
54//! Default constructor
55//++
56NTuple::NTuple()
57//
58// Createur par defaut
59//--
60{
61mNVar = mNEnt = mBlk = mNBlk = 0;
62mVar = NULL;
63mVarD = NULL;
64mNames = NULL;
65mInfo = NULL;
66}
67
68
69//! Constructor with specification of number of columns and column name
70/*!
71 \param nvar : Number of columns in the table
72 \param noms : Array of column names (length(name) < 8 characters)
73 \param blk : Optional argument specifying number of table lines
74 in a given data block
75 */
76//++
77NTuple::NTuple(int nvar, char** noms, int blk)
78//
79// Createur d'un ntuple de `nvar' variables dont les
80// noms sont dans le tableau de cahines de caracteres `noms'
81// avec `blk' d'evenements par blocks.
82//--
83{
84mNVar = mNEnt = mBlk = mNBlk = 0;
85mVar = NULL;
86mVarD = NULL;
87mNames = NULL;
88mInfo = NULL;
89if (nvar <= 0) THROW(sizeMismatchErr);
90mNVar = nvar;
91mVar = new r_4[nvar];
92mVarD = new r_8[nvar];
93if (blk < 10) blk = 10;
94mBlk = blk;
95// On prend des noms de LENNAME char pour le moment
96mNames = new char[nvar*LENNAME1];
97r_4* pt = new r_4[nvar*blk];
98mNBlk = 1;
99mPtr.push_back(pt);
100int i;
101for(i=0; i<nvar; i++)
102 { strncpy(mNames+i*LENNAME1, noms[i], LENNAME);
103 mNames[i*LENNAME1+LENNAME] = '\0'; }
104return;
105}
106
107//! Copy constructor - Copies the table definition and associated data
108// cmv 8/10/99
109//++
110NTuple::NTuple(const NTuple& NT)
111//
112// Createur par copie (clone).
113//--
114: mNVar(0), mNEnt(0), mBlk(0), mNBlk(0)
115, mVar(NULL), mVarD(NULL), mNames(NULL), mInfo(NULL)
116{
117if(NT.mNVar<=0) return; // cas ou NT est cree par defaut
118mNVar = NT.mNVar;
119mBlk = NT.mBlk;
120mVar = new r_4[NT.mNVar];
121mVarD = new r_8[NT.mNVar];
122mNames = new char[NT.mNVar*LENNAME1];
123
124int i;
125r_4* pt = new r_4[mNVar*mBlk];
126mNBlk = 1; mPtr.push_back(pt);
127
128for(i=0;i<mNVar;i++) strcpy(mNames+i*LENNAME1,NT.NomIndex(i));
129
130if(NT.mInfo!=NULL) {mInfo = new DVList; *mInfo = *(NT.mInfo);}
131
132if(NT.mNEnt<=0) return;
133for(i=0;i<NT.mNEnt;i++) {r_4* x=NT.GetVec(i,NULL); Fill(x);}
134
135return;
136}
137
138/* --Methode-- */
139//! Constructor with table initialized from a PPF file
140//++
141NTuple::NTuple(char *flnm)
142//
143// Createur lecture fichier ppersist.
144//--
145{
146mNVar = mNEnt = mBlk = mNBlk = 0;
147mVar = NULL;
148mVarD = NULL;
149mNames = NULL;
150mInfo = NULL;
151PInPersist s(flnm);
152ObjFileIO<NTuple> fiont(this);
153fiont.Read(s);
154}
155
156/* --Methode-- */
157NTuple::~NTuple()
158{
159Clean();
160}
161
162/* --Methode-- */
163//! Clear the data table definition and deletes the associated data
164void NTuple::Clean()
165{
166if (mVar) delete[] mVar;
167if (mVarD) delete[] mVarD;
168if (mNames) delete[] mNames;
169if (mInfo) delete mInfo;
170int i;
171if(mNBlk>0) for(i=0; i<mNBlk; i++) delete[] mPtr[i];
172mPtr.erase(mPtr.begin(), mPtr.end());
173mNVar = mNEnt = mBlk = mNBlk = 0;
174mVar = NULL;
175mVarD = NULL;
176mNames = NULL;
177mInfo = NULL;
178return;
179}
180
181/* --Methode-- cmv 08/10/99 */
182//! = operator, copies the data table definition and its contents
183//++
184NTuple& NTuple::operator = (const NTuple& NT)
185//
186// Operateur egal (clone).
187//--
188{
189if(this == &NT) return *this;
190Clean();
191if(NT.mNVar<=0) return *this; // cas ou NT est cree par defaut
192mNVar = NT.mNVar;
193mBlk = NT.mBlk;
194mVar = new r_4[NT.mNVar];
195mVarD = new r_8[NT.mNVar];
196mNames = new char[NT.mNVar*LENNAME1];
197
198int i;
199r_4* pt = new r_4[mNVar*mBlk];
200mNBlk = 1; mPtr.push_back(pt);
201
202for(i=0;i<mNVar;i++) strcpy(mNames+i*LENNAME1,NT.NomIndex(i));
203
204if(NT.mInfo!=NULL) {mInfo = new DVList; *mInfo = *(NT.mInfo);}
205
206if(NT.mNEnt<=0) return *this;
207for(i=0;i<NT.mNEnt;i++) {r_4* x=NT.GetVec(i,NULL); Fill(x);}
208
209// En fait il faudrait un createur par copie qui partage les donnees
210// quand l'objet est temporaire... trop complique A FAIRE ! cmv.
211return *this;
212}
213
214/* --Methode-- */
215//! Adds an entry (a line) to the table
216/*!
217 \param x : content of the line to be appended to the table
218 */
219//++
220void NTuple::Fill(r_4* x)
221//
222// Remplit le ntuple avec le tableau cd reels `x'.
223//--
224{
225int numb = mNEnt/mBlk;
226if (numb >= mNBlk) {
227 r_4* pt = new r_4[mNVar*mBlk];
228 mNBlk++;
229 mPtr.push_back(pt);
230}
231int offb = mNEnt-numb*mBlk;
232memcpy((mPtr[numb]+offb*mNVar), x, mNVar*sizeof(r_4));
233mNEnt++;
234return;
235}
236
237
238/* --Methode-- */
239//++
240float NTuple::GetVal(int n, int k) const
241//
242// Retourne la valeur de la variable `k' de l'evenement `n'.
243//--
244{
245if (n >= mNEnt) return(BADVAL);
246if ( (k < 0) || (k >= mNVar) ) return(BADVAL);
247int numb = n/mBlk;
248int offb = n-numb*mBlk;
249return(*(mPtr[numb]+offb*mNVar+k));
250}
251
252
253/* --Methode-- */
254//++
255int NTuple::IndexNom(const char* nom) const
256//
257// Retourne le numero de la variable de nom `nom'.
258//--
259{
260int i;
261for(i=0; i<mNVar; i++)
262 if ( strcmp(nom, mNames+i*LENNAME1) == 0) return(i);
263return(-1);
264}
265
266
267static char nomretour[2*LENNAME1];
268/* --Methode-- */
269//++
270char* NTuple::NomIndex(int k) const
271//
272// Retourne le nom de la variable numero 'k'
273//--
274{
275nomretour[0] = '\0';
276if ((k >= 0) && (k < mNVar)) strcpy(nomretour, mNames+k*LENNAME1);
277return(nomretour);
278}
279
280
281/* --Methode-- */
282//++
283r_4* NTuple::GetVec(int n, r_4* ret) const
284//
285// Retourne l'evenement `n' dans le vecteur `ret'.
286//--
287{
288int i;
289if (ret == NULL) ret = mVar;
290if (n >= mNEnt) {
291 for(i=0; i<mNVar; i++) ret[i] = BADVAL;
292 return(ret);
293}
294
295int numb = n/mBlk;
296int offb = n-numb*mBlk;
297memcpy(ret, (mPtr[numb]+offb*mNVar), mNVar*sizeof(r_4));
298return(ret);
299}
300
301/* --Methode-- */
302//++
303r_8* NTuple::GetVecD(int n, r_8* ret) const
304//
305// Retourne l'evenement `n' dans le vecteur `ret'.
306//--
307{
308int i;
309if (ret == NULL) ret = mVarD;
310float * fr = GetVec(n);
311for(i=0; i<mNVar; i++) ret[i] = fr[i];
312return(ret);
313}
314
315
316
317/* --Methode-- */
318//++
319DVList& NTuple::Info()
320//
321// Renvoie une référence sur l'objet DVList Associé
322//--
323{
324if (mInfo == NULL) mInfo = new DVList;
325return(*mInfo);
326}
327
328/* --Methode-- */
329//++
330void NTuple::Print(int num, int nmax) const
331//
332// Imprime `nmax' evenements a partir du numero `num'.
333//--
334{
335int i,j;
336
337printf("Num ");
338for(i=0; i<mNVar; i++) printf("%8s ", mNames+i*LENNAME1);
339putchar('\n');
340
341if (nmax <= 0) nmax = 1;
342if (num < 0) num = 0;
343nmax += num;
344if (nmax > mNEnt) nmax = mNEnt;
345for(i=num; i<nmax; i++) {
346 GetVec(i, NULL);
347 printf("%6d ", i);
348 for(j=0; j<mNVar; j++) printf("%8g ", (float)mVar[j]);
349 putchar('\n');
350}
351return;
352}
353
354/* --Methode-- */
355//! Prints table definition and number of entries
356//++
357void NTuple::Show(ostream& os) const
358//
359// Imprime l'information generale sur le ntuple.
360//--
361{
362os << "NTuple: NVar= " << mNVar << " NEnt=" << mNEnt
363 << " (Blk Sz,Nb= " << mBlk << " ," << mNBlk << ")\n";
364os << " Variables Min Max \n";
365int i;
366double min, max;
367char buff[128];
368for(i=0; i<mNVar; i++) {
369 GetMinMax(i, min, max);
370 sprintf(buff, "%3d %16s %10g %10g \n", i, mNames+i*LENNAME1, min, max);
371 os << (string)buff ;
372 }
373os << endl;
374}
375
376
377/* --Methode-- */
378//! Fills the table, reading lines from an ascii file
379/*!
380 \param fn : file name
381 \param defval : default value for empty cells in the ascii file
382 */
383//++
384int NTuple::FillFromASCIIFile(string const& fn, float defval)
385//
386// Remplit le ntuple a partir d'un fichier ASCII.
387// Renvoie le nombre de lignes ajoutees.
388//--
389{
390if (NbColumns() < 1) {
391 cout << "NTuple::FillFromASCIIFile() Ntuple has " << NbColumns() << " columns" << endl;
392 return(-1);
393 }
394FILE * fip = fopen(fn.c_str(), "r");
395if (fip == NULL) {
396 cout << "NTuple::FillFromASCIIFile() Error opening file " << fn << endl;
397 return(-2);
398 }
399
400char lineb[4096];
401char *line;
402char* ccp;
403int j,kk;
404int postab, posb;
405float* xv = new float[NbColumns()];
406
407int nlread = 0;
408int nvar = NbColumns();
409// On boucle sur toutes les lignes
410while (fgets(lineb,4096,fip) != NULL) {
411 lineb[4095] = '\0';
412 j = 0; line = lineb;
413// On enleve les espaces et tab de debut
414 while ( (line[j] != '\0') && ((line[j] == ' ') || (line[j] == '\t')) ) j++;
415 line = lineb+j;
416// Il faut que le premier caractere non-espace soit un digit, ou + ou - ou .
417 if (!( isdigit(line[0]) || (line[0] == '+') || (line[0] == '-') || (line[0] == '.') )) continue;
418 ccp = line;
419 for(kk=0; kk<nvar; kk++) xv[kk] = defval;
420 for(kk=0; kk<nvar; kk++) {
421// Les mots sont separes par des espaces ou des tab
422 postab = posc(ccp, '\t' );
423 posb = posc(ccp, ' ' );
424 if (postab >= 0) {
425 if (posb < 0) posb = postab;
426 else if (postab < posb) posb = postab;
427 }
428 if (posb >= 0) ccp[posb] = '\0';
429 if ( isdigit(line[0]) || (line[0] == '+') || (line[0] == '-') || (line[0] == '.') )
430 xv[kk] = atof(ccp);
431 if (posb < 0) break;
432 ccp += posb+1; j = 0;
433 while ( (ccp[j] != '\0') && ((ccp[j] == ' ') || (ccp[j] == '\t')) ) j++;
434 ccp += j;
435 }
436 Fill(xv);
437 nlread++;
438 }
439
440delete[] xv;
441cout << "NTuple::FillFromASCIIFile( " << fn << ") " << nlread << " fill from file " << endl;
442return(nlread);
443}
444
445
446// ------- Implementation de l interface NTuple ---------
447
448/* --Methode-- */
449uint_4 NTuple::NbLines() const
450{
451return(NEntry());
452}
453/* --Methode-- */
454uint_4 NTuple::NbColumns() const
455{
456return(NVar());
457}
458
459/* --Methode-- */
460r_8 * NTuple::GetLineD(int n) const
461{
462return(GetVecD(n));
463}
464
465/* --Methode-- */
466r_8 NTuple::GetCell(int n, int k) const
467{
468return(GetVal(n, k));
469}
470
471/* --Methode-- */
472r_8 NTuple::GetCell(int n, string const & nom) const
473{
474return(GetVal(n, nom.c_str()));
475}
476
477/* --Methode-- */
478//++
479void NTuple::GetMinMax(int k, double& min, double& max) const
480//
481// Retourne le minimum et le maximum de la variable `k'.
482//--
483{
484min = 9.e19; max = -9.e19;
485if ( (k < 0) || (k >= mNVar) ) return;
486int jb,ib,i;
487double x;
488i=0;
489for(jb=0; jb< mNBlk; jb++)
490 for(ib=0; ib< mBlk; ib++) {
491 if (i >= mNEnt) break;
492 i++;
493 x = *(mPtr[jb]+ib*mNVar+k);
494 if(i==1) {min = x; max = x;}
495 if (x < min) min = x;
496 if (x > max) max = x;
497 }
498return;
499}
500
501/* --Methode-- */
502void NTuple::GetMinMax(string const & nom, double& min, double& max) const
503{
504GetMinMax(IndexNom(nom.c_str()), min, max);
505}
506
507/* --Methode-- */
508int NTuple::ColumnIndex(string const & nom) const
509{
510return(IndexNom(nom.c_str()));
511}
512
513/* --Methode-- */
514string NTuple::ColumnName(int k) const
515{
516return(NomIndex(k));
517}
518
519/* --Methode-- */
520//++
521string NTuple::VarList_C(const char* nomx) const
522//
523// Retourne une chaine de caracteres avec la declaration des noms de
524// variables. si "nomx!=NULL" , des instructions d'affectation
525// a partir d'un tableau "nomx[i]" sont ajoutees.
526//--
527{
528string rets="";
529int i;
530for(i=0; i<mNVar; i++) {
531 if ( (i%5 == 0) && (i > 0) ) rets += ";";
532 if (i%5 == 0) rets += "\ndouble ";
533 else rets += ",";
534 rets += mNames+i*LENNAME1;
535 }
536rets += "; \n";
537if (nomx) {
538 char buff[256];
539 for(i=0; i<mNVar; i++) {
540 sprintf(buff,"%s=%s[%d]; ", mNames+i*LENNAME1, nomx, i);
541 rets += buff;
542 if ( (i%3 == 0) && (i > 0) ) rets += "\n";
543 }
544 }
545
546return(rets);
547}
548
549
550/* --Methode-- */
551//++
552string NTuple::LineHeaderToString() const
553// Retourne une chaine de caracteres avec la liste des noms de
554// variables, utilisables pour une impression
555//--
556{
557char buff[32];
558string rets=" Num ";
559for(int i=0; i<mNVar; i++) {
560 sprintf(buff, "%8s ", mNames+i*LENNAME1);
561 rets += buff;
562 }
563rets += '\n';
564return(rets);
565}
566
567/* --Methode-- */
568//++
569string NTuple::LineToString(int n) const
570// Retourne une chaine de caracteres avec le contenu de la ligne "n"
571// utilisable pour une impression
572//--
573{
574char buff[32];
575double* val;
576val = GetLineD(n);
577sprintf(buff,"%6d: ",n);
578string rets=buff;
579int i;
580for(i=0; i<mNVar; i++) {
581 sprintf(buff, "%8.3g ", val[i]);
582 rets += buff;
583 }
584rets += '\n';
585return(rets);
586}
587
588/*!
589 \class SOPHYA::ObjFileIO<NTuple>
590 \ingroup HiStats
591 Persistence (serialisation) handler for class NTuple
592*/
593
594/* --Methode-- */
595//++
596void ObjFileIO<NTuple>::WriteSelf(POutPersist& s) const
597//
598// Ecriture ppersist du ntuple.
599//--
600{
601if (dobj == NULL) return;
602
603// On ecrit cette chaine pour compatibilite avec l'ancienne version
604string strg = "NTuple";
605s.Put(strg);
606
607// On ecrit 3 uint_4 ....
608// 0: Numero de version, 1 : non nul -> has info, 2 : reserve
609uint_4 itab[3];
610itab[0] = 2; // Numero de version a 1
611itab[1] = itab[2] = 0;
612if (dobj->mInfo) itab[1] = 1;
613s.Put(itab, 3);
614
615s.Put(dobj->mNVar);
616s.PutBytes(dobj->mNames, dobj->mNVar*LENNAME1);
617s.Put(dobj->mNEnt);
618s.Put(dobj->mBlk);
619s.Put(dobj->mNBlk);
620if (dobj->mInfo) s << (*(dobj->mInfo));
621int jb;
622for(jb=0; jb<dobj->mNBlk; jb++)
623 s.Put(dobj->mPtr[jb], dobj->mNVar*dobj->mBlk);
624return;
625}
626
627/* --Methode-- */
628//++
629void ObjFileIO<NTuple>::ReadSelf(PInPersist& s)
630//
631// Lecture ppersist du ntuple.
632//--
633{
634
635if (dobj == NULL) dobj = new NTuple;
636else dobj->Clean();
637
638bool hadinfo = false;
639string strg;
640s.Get(strg);
641if (strg == "NTuple") {
642 uint_4 itab[3];
643 s.Get(itab, 3);
644 if (itab[1] != 0) hadinfo = true;
645}
646else {
647// Ancienne version de PPF NTuple - Pour savoir s'il y avait un DVList Info associe
648 char buff[256];
649 strcpy(buff, strg.c_str());
650 if (strncmp(buff+strlen(buff)-7, "HasInfo", 7) == 0) hadinfo = true;
651}
652s.Get(dobj->mNVar);
653dobj->mNames = new char[dobj->mNVar*LENNAME1];
654dobj->mVar = new r_4[dobj->mNVar];
655dobj->mVarD = new r_8[dobj->mNVar];
656s.GetBytes(dobj->mNames, dobj->mNVar*LENNAME1);
657s.Get(dobj->mNEnt);
658s.Get(dobj->mBlk);
659s.Get(dobj->mNBlk);
660
661if (hadinfo) { // Lecture eventuelle du DVList Info
662 if (dobj->mInfo == NULL) dobj->mInfo = new DVList;
663 s >> (*(dobj->mInfo));
664 }
665
666int jb;
667for(jb=0; jb<dobj->mNBlk; jb++) {
668 r_4* pt = new r_4[dobj->mNVar*dobj->mBlk];
669 dobj->mPtr.push_back(pt);
670 s.Get(dobj->mPtr[jb], dobj->mNVar*dobj->mBlk);
671}
672
673}
674
675
676#ifdef __CXX_PRAGMA_TEMPLATES__
677#pragma define_template ObjFileIO<NTuple>
678#endif
679
680#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
681template class ObjFileIO<NTuple>;
682#endif
Note: See TracBrowser for help on using the repository browser.