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

Last change on this file since 2626 was 2615, checked in by cmv, 21 years ago

using namespace sophya enleve de machdefs.h, nouveau sopnamsp.h cmv 10/09/2004

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