source: Sophya/trunk/SophyaLib/HiStats/histos.cc@ 2827

Last change on this file since 2827 was 2628, checked in by cmv, 21 years ago

NEntries goes from int_4 to uint_8 cmv 13/10/04

File size: 35.4 KB
Line 
1//
2// $Id: histos.cc,v 1.20 2004-10-13 16:41:33 cmv Exp $
3//
4
5#include "sopnamsp.h"
6#include "machdefs.h"
7#include <string.h>
8#include <stdio.h>
9#include <math.h>
10#include "histos.h"
11#include "perrors.h"
12#include "poly.h"
13#include "strutil.h"
14
15/*!
16 \class SOPHYA::Histo
17 \ingroup HiStats
18 Classe d'histogrammes 1D
19*/
20
21/********* Methode *********/
22/*! Constructeur par defaut */
23Histo::Histo()
24: mData(NULL), mErr2(NULL),
25 mUnder(0), mOver(0), nHist(0), nEntries(0),
26 mBins(0), mMin(0), mMax(0),
27 binWidth(0)
28{
29}
30
31/********* Methode *********/
32/*! Constructeur d'un histo de nBin bins allant de xMin a xMax */
33Histo::Histo(r_8 xMin, r_8 xMax, int_4 nBin)
34: mData((nBin>0) ? new r_8[nBin] : NULL),
35 mErr2(NULL),
36 mUnder(0), mOver(0), nHist(0), nEntries(0),
37 mBins(nBin), mMin(xMin), mMax(xMax),
38 binWidth((nBin>0) ? (mMax-mMin)/nBin : 0)
39{
40 Zero();
41}
42
43/********* Methode *********/
44/*! Constructeur d'un histo de nBin bins allant de xMin a xMax */
45Histo::Histo(r_4 xMin, r_4 xMax, int_4 nBin)
46: mData((nBin>0) ? new r_8[nBin] : NULL),
47 mErr2(NULL),
48 mUnder(0), mOver(0), nHist(0), nEntries(0),
49 mBins(nBin), mMin((r_8)xMin), mMax((r_8)xMax),
50 binWidth((nBin>0) ? (mMax-mMin)/nBin : 0)
51{
52 Zero();
53}
54
55/********* Methode *********/
56/*! Constructeur par copie */
57Histo::Histo(const Histo& H)
58: mData((H.mBins>0)? new r_8[H.mBins] : NULL),
59 mErr2((H.mBins>0 && H.mErr2!=NULL)? new r_8[H.mBins]: NULL),
60 mUnder(H.mUnder), mOver(H.mOver), nHist(H.nHist), nEntries(H.nEntries),
61 mBins(H.mBins), mMin(H.mMin), mMax(H.mMax),
62 binWidth(H.binWidth)
63{
64 if(mBins<=0) return;
65 memcpy(mData,H.mData,mBins*sizeof(r_8));
66 if(H.mErr2) memcpy(mErr2, H.mErr2, mBins*sizeof(r_8));
67}
68
69/********* Methode *********/
70/*! Gestion de la des-allocation */
71void Histo::Delete()
72{
73 if( mData != NULL ) { delete[] mData; mData = NULL;}
74 if( mErr2 != NULL ) { delete[] mErr2; mErr2 = NULL;}
75 mUnder = mOver = mMin = mMax = binWidth= 0.;
76 nHist = 0.;
77 mBins = 0;
78 nEntries = 0;
79}
80
81/********* Methode *********/
82/*! Destructeur */
83Histo::~Histo()
84{
85Delete();
86}
87
88/********* Methode *********/
89/*!
90 Remise a zero
91*/
92void Histo::Zero()
93{
94 if(mBins<=0 || mData==NULL) return;
95 memset(mData,0,mBins*sizeof(r_8));
96 mUnder = mOver = 0;
97 nHist = 0;
98 nEntries = 0;
99 if(mErr2) memset(mErr2, 0, mBins*sizeof(r_8));
100}
101
102/********* Methode *********/
103/*!
104 Pour avoir le calcul des erreurs
105*/
106void Histo::Errors()
107{
108 if(mBins<=0) return;
109 if(mErr2==NULL) mErr2 = new r_8[mBins];
110 memset(mErr2,0,mBins*sizeof(r_8));
111}
112
113/********* Methode *********/
114/*!
115 Operateur egal Histo = Histo
116*/
117Histo& Histo::operator = (const Histo& h)
118{
119 if(this == &h) return *this;
120 Delete();
121 if(h.mBins<=0 || h.mData==NULL) return *this;
122
123 mData = new r_8[h.mBins];
124 if(h.mErr2) mErr2 = new r_8[h.mBins];
125 mUnder = h.mUnder;
126 mOver = h.mOver;
127 nHist = h.nHist;
128 nEntries = h.nEntries;
129 mBins = h.mBins;
130 mMin = h.mMin;
131 mMax = h.mMax;
132 binWidth = h.binWidth;
133
134 memcpy(mData,h.mData,mBins*sizeof(r_8));
135 if(mErr2) memcpy(mErr2,h.mErr2,mBins*sizeof(r_8));
136
137 return *this;
138}
139
140/********* Methode *********/
141/*!
142 Operateur de multiplication par une constante
143*/
144Histo& Histo::operator *= (r_8 b)
145{
146r_8 b2 = b*b;
147for(int_4 i=0;i<mBins;i++) {
148 mData[i] *= b;
149 if(mErr2) mErr2[i] *= b2;
150}
151mUnder *= b;
152mOver *= b;
153nHist *= b;
154
155return *this;
156}
157
158/*!
159 Operateur de division par une constante
160*/
161Histo& Histo::operator /= (r_8 b)
162{
163if (b==0.) throw ParmError(PExcLongMessage(""));
164r_8 b2 = b*b;
165for(int_4 i=0;i<mBins;i++) {
166 mData[i] /= b;
167 if(mErr2) mErr2[i] /= b2;
168}
169mUnder /= b;
170mOver /= b;
171nHist /= b;
172
173return *this;
174}
175
176/*!
177 Operateur d'addition d'une constante
178*/
179Histo& Histo::operator += (r_8 b)
180{
181for(int_4 i=0;i<mBins;i++) mData[i] += b;
182mUnder += b;
183mOver += b;
184nHist += mBins*b;
185
186return *this;
187}
188
189/*!
190 Operateur de soustraction d'une constante
191*/
192Histo& Histo::operator -= (r_8 b)
193{
194for(int_4 i=0;i<mBins;i++) mData[i] -= b;
195mUnder -= b;
196mOver -= b;
197nHist -= mBins*b;
198
199return *this;
200}
201
202/********* Methode *********/
203/*!
204 Operateur H += H1
205*/
206Histo& Histo::operator += (const Histo& a)
207{
208if(mBins!=a.mBins) throw SzMismatchError(PExcLongMessage(""));
209for(int_4 i=0;i<mBins;i++) {
210 mData[i] += a(i);
211 if(mErr2 && a.mErr2) mErr2[i] += a.Error2(i);
212}
213mUnder += a.mUnder;
214mOver += a.mOver;
215nHist += a.nHist;
216nEntries += a.nEntries;
217
218return *this;
219}
220
221/*!
222 Operateur H -= H1
223*/
224Histo& Histo::operator -= (const Histo& a)
225{
226if(mBins!=a.mBins) throw SzMismatchError(PExcLongMessage(""));
227for(int_4 i=0;i<mBins;i++) {
228 mData[i] -= a(i);
229 if(mErr2 && a.mErr2) mErr2[i] += a.Error2(i);
230}
231mUnder -= a.mUnder;
232mOver -= a.mOver;
233nHist -= a.nHist;
234nEntries += a.nEntries;
235
236return *this;
237}
238
239/*!
240 Operateur H *= H1
241*/
242Histo& Histo::operator *= (const Histo& a)
243{
244if(mBins!=a.mBins) throw SzMismatchError(PExcLongMessage(""));
245nHist = 0.;
246for(int_4 i=0;i<mBins;i++) {
247 if(mErr2 && a.mErr2)
248 mErr2[i] = a(i)*a(i)*mErr2[i] + mData[i]*mData[i]*a.Error2(i);
249 mData[i] *= a(i);
250 nHist += mData[i];
251}
252mUnder *= a.mUnder;
253mOver *= a.mOver;
254nEntries += a.nEntries;
255
256return *this;
257}
258
259/*!
260 Operateur H /= H1
261*/
262Histo& Histo::operator /= (const Histo& a)
263{
264if(mBins!=a.mBins) throw SzMismatchError(PExcLongMessage(""));
265nHist = 0.;
266for(int_4 i=0;i<mBins;i++) {
267 if(a(i)==0.) {
268 mData[i]=0.;
269 if(mErr2) mErr2[i]=0.;
270 continue;
271 }
272 if(mErr2 && a.mErr2)
273 mErr2[i] = (mErr2[i] + mData[i]/a(i)*mData[i]/a(i)*a.Error2(i))
274 /(a(i)*a(i));
275 mData[i] /= a(i);
276 nHist += mData[i];
277}
278if(a.mUnder!=0.) mUnder /= a.mUnder; else mUnder = 0.;
279if(a.mOver!=0.) mOver /= a.mOver; else mOver = 0.;
280nEntries += a.nEntries;
281
282return *this;
283}
284
285/********* Methode *********/
286/*!
287 Remplissage d'un tableau avec la valeur des abscisses
288*/
289void Histo::GetAbsc(TVector<r_8> &v) const
290{
291v.Realloc(mBins);
292for(int_4 i=0;i<mBins;i++) v(i) = BinLowEdge(i);
293return;
294}
295
296/*!
297 Remplissage d'un tableau avec la valeur du contenu
298*/
299void Histo::GetValue(TVector<r_8> &v) const
300{
301v.Realloc(mBins);
302for(int_4 i=0;i<mBins;i++) v(i) = mData[i];
303return;
304}
305
306/*!
307 Remplissage d'un tableau avec la valeur des erreurs au carre
308*/
309void Histo::GetError2(TVector<r_8> &v) const
310{
311v.Realloc(mBins);
312if(!mErr2) {for(int_4 i=0;i<mBins;i++) v(i) = 0.; return;}
313for(int_4 i=0;i<mBins;i++) v(i) = mErr2[i];
314return;
315}
316
317/*!
318 Remplissage d'un tableau avec la valeur des erreurs
319*/
320void Histo::GetError(TVector<r_8> &v) const
321{
322v.Realloc(mBins);
323if(!mErr2) {for(int_4 i=0;i<mBins;i++) v(i) = 0.; return;}
324for(int_4 i=0;i<mBins;i++) v(i) = Error(i);
325return;
326}
327
328/********* Methode *********/
329/*!
330 Remplissage du contenu de l'histo avec les valeurs d'un vecteur
331*/
332void Histo::PutValue(TVector<r_8> &v, int_4 ierr)
333{
334//if(v.NElts()<(uint_4) mBins) throw SzMismatchError(PExcLongMessage(""));
335uint_4 n = (v.NElts()<(uint_4) mBins) ? v.NElts(): (uint_4) mBins;
336if(n>0) for(uint_4 i=0;i<n;i++) {
337 mData[i] = v(i);
338 if(mErr2&&ierr) mErr2[i] = fabs(v(i));
339}
340return;
341}
342
343/*!
344 Addition du contenu de l'histo avec les valeurs d'un vecteur
345*/
346void Histo::PutValueAdd(TVector<r_8> &v, int_4 ierr)
347{
348//if(v.NElts()<(uint_4) mBins) throw SzMismatchError(PExcLongMessage(""));
349uint_4 n = (v.NElts()<(uint_4) mBins) ? v.NElts(): (uint_4) mBins;
350if(n>0) for(uint_4 i=0;i<n;i++) {
351 mData[i] += v(i);
352 if(mErr2 && ierr) mErr2[i] += fabs(v(i));
353}
354return;
355}
356
357/*!
358 Remplissage des erreurs au carre de l'histo avec les valeurs d'un vecteur
359*/
360void Histo::PutError2(TVector<r_8> &v)
361{
362//if(v.NElts()<(uint_4) mBins) throw SzMismatchError(PExcLongMessage(""));
363uint_4 n = (v.NElts()<(uint_4) mBins) ? v.NElts(): (uint_4) mBins;
364if(n>0) {
365 if(!mErr2) Errors();
366 for(uint_4 i=0;i<n;i++) mErr2[i] = v(i);
367}
368return;
369}
370
371/*!
372 Addition des erreurs au carre de l'histo avec les valeurs d'un vecteur
373*/
374void Histo::PutError2Add(TVector<r_8> &v)
375{
376//if(v.NElts()<(uint_4) mBins) throw SzMismatchError(PExcLongMessage(""));
377uint_4 n = (v.NElts()<(uint_4) mBins) ? v.NElts(): (uint_4) mBins;
378if(n>0) {
379 if(!mErr2) Errors();
380 for(uint_4 i=0;i<n;i++) if(v(i)>0.) mErr2[i] += v(i);
381}
382return;
383}
384
385/*!
386 Remplissage des erreurs de l'histo avec les valeurs d'un vecteur
387*/
388void Histo::PutError(TVector<r_8> &v)
389{
390//if(v.NElts()<(uint_4) mBins) throw SzMismatchError(PExcLongMessage(""));
391uint_4 n = (v.NElts()<(uint_4) mBins) ? v.NElts(): (uint_4) mBins;
392if(n>0) {
393 if(!mErr2) Errors();
394 for(uint_4 i=0;i<n;i++)
395 if(v(i)>0.) mErr2[i]=v(i)*v(i); else mErr2[i]=-v(i)*v(i);
396}
397return;
398}
399
400/********* Methode *********/
401/*!
402 Addition du contenu de l'histo pour abscisse x poids w
403*/
404void Histo::Add(r_8 x, r_8 w)
405{
406 int_4 numBin = FindBin(x);
407 if (numBin<0) mUnder += w;
408 else if (numBin>=mBins) mOver += w;
409 else {
410 mData[numBin] += w;
411 if(mErr2!=NULL) mErr2[numBin] += w*w;
412 nHist += w;
413 nEntries++;
414 }
415}
416
417/********* Methode *********/
418/*!
419 Addition du contenu de l'histo bin numBin poids w
420*/
421void Histo::AddBin(int_4 numBin, r_8 w)
422{
423 if (numBin<0) mUnder += w;
424 else if (numBin>=mBins) mOver += w;
425 else {
426 mData[numBin] += w;
427 if(mErr2!=NULL) mErr2[numBin] += w*w;
428 nHist += w;
429 nEntries++;
430 }
431}
432
433/********* Methode *********/
434/*!
435 Remplissage du contenu de l'histo pour abscisse x poids w
436*/
437void Histo::SetBin(r_8 x, r_8 w)
438{
439 int_4 numBin = FindBin(x);
440 SetBin(numBin,w);
441}
442
443/********* Methode *********/
444/*!
445 Remplissage du contenu de l'histo pour numBin poids w
446*/
447void Histo::SetBin(int_4 numBin, r_8 w)
448{
449 if (numBin<0) mUnder = w;
450 else if (numBin>=mBins) mOver = w;
451 else {
452 nHist -= mData[numBin];
453 mData[numBin] = w;
454 nHist += w;
455 }
456}
457
458/********* Methode *********/
459/*!
460 Remplissage des erreurs au carre pour abscisse x
461*/
462void Histo::SetErr2(r_8 x, r_8 e2)
463{
464 int_4 numBin = FindBin(x);
465 SetErr2(numBin,e2);
466}
467
468/********* Methode *********/
469/*!
470 Remplissage des erreurs au carre pour numBin poids
471*/
472void Histo::SetErr2(int_4 numBin, r_8 e2)
473{
474 if( mErr2==NULL) return;
475 if ( numBin<0 || numBin>=mBins ) return;
476 mErr2[numBin] = e2;
477}
478
479/********* Methode *********/
480/*!
481 Remplissage des erreurs pour abscisse x
482*/
483void Histo::SetErr(r_8 x, r_8 e)
484{
485SetErr2(x, e*e);
486}
487
488/********* Methode *********/
489/*!
490 Remplissage des erreurs pour numBin
491*/
492void Histo::SetErr(int_4 numBin, r_8 e)
493{
494SetErr2(numBin, e*e);
495}
496
497/********* Methode *********/
498/*!
499 Methode virtuelle de mise a jour - Ne fait rien pour Histo - Voir HProf
500*/
501void Histo::UpdateHisto(bool force) const
502{
503 return;
504}
505
506/********* Methode *********/
507/*!
508 Numero du bin ayant le contenu maximum
509*/
510int_4 Histo::IMax() const
511{
512 int_4 imx=0;
513 if(mBins==1) return imx;
514 r_8 mx=mData[0];
515 for (int_4 i=1; i<mBins; i++)
516 if (mData[i]>mx) {imx = i; mx=mData[i];}
517 return imx;
518}
519
520/********* Methode *********/
521/*!
522 Numero du bin ayant le contenu minimum
523*/
524int_4 Histo::IMin() const
525{
526 int_4 imx=0;
527 if(mBins==1) return imx;
528 r_8 mx=mData[0];
529 for (int_4 i=1; i<mBins; i++)
530 if (mData[i]<mx) {imx = i; mx=mData[i];}
531 return imx;
532}
533
534/********* Methode *********/
535/*!
536 Valeur le contenu maximum
537*/
538r_8 Histo::VMax() const
539{
540 r_8 mx=mData[0];
541 if(mBins==1) return mx;
542 for (int_4 i=1;i<mBins;i++) if(mData[i]>mx) mx=mData[i];
543 return mx;
544}
545
546/********* Methode *********/
547/*!
548 Valeur le contenu minimum
549*/
550r_8 Histo::VMin() const
551{
552 r_8 mx=mData[0];
553 if(mBins==1) return mx;
554 for (int_4 i=1;i<mBins;i++) if(mData[i]<mx) mx=mData[i];
555 return mx;
556}
557
558/********* Methode *********/
559/*!
560 Valeur moyenne
561*/
562r_8 Histo::Mean() const
563{
564 r_8 n = 0;
565 r_8 sx = 0;
566 for (int_4 i=0; i<mBins; i++) {
567 r_8 v = (mData[i]>=0.) ? mData[i] : -mData[i];
568 n += v;
569 sx += BinCenter(i)*v;
570 }
571 if(n>0.) return sx/n; else return mMin;
572}
573
574/********* Methode *********/
575/*!
576 Valeur du sigma
577*/
578r_8 Histo::Sigma() const
579{
580 r_8 n = 0;
581 r_8 sx = 0;
582 r_8 sx2= 0;
583 for (int_4 i=0; i<mBins; i++) {
584 r_8 v = (mData[i]>=0.) ? mData[i] : -mData[i];
585 n += v;
586 sx += BinCenter(i)*v;
587 sx2+= BinCenter(i)*BinCenter(i)*v;
588 }
589 // attention a l'erreur d'arrondi si un seul bin rempli!!
590 if( n == 0 ) return 0.;
591 sx2 = sx2/n - (sx/n)*(sx/n);
592 if( sx2>0. ) return sqrt( sx2 );
593 else return 0.;
594}
595
596/********* Methode *********/
597/*!
598 Valeur de la moyenne calculee entre les bin il et ih
599*/
600r_8 Histo::MeanLH(int_4 il,int_4 ih) const
601{
602 if( ih < il ) { il = 0; ih = mBins-1; }
603 if( il < 0 ) il = 0;
604 if( ih >= mBins ) ih = mBins-1;
605 r_8 n = 0;
606 r_8 sx = 0;
607 for (int_4 i=il; i<=ih; i++) {
608 r_8 v = (mData[i]>=0.) ? mData[i] : -mData[i];
609 n += v;
610 sx += BinCenter(i)*v;
611 }
612 if(n>0.) return sx/n; else return BinLowEdge(il);
613}
614
615/********* Methode *********/
616/*!
617 Valeur de la moyenne calculee entre les bin il et ih
618*/
619r_8 Histo::SigmaLH(int_4 il,int_4 ih) const
620{
621 if( ih < il ) { il = 0; ih = mBins - 1; }
622 if( il < 0 ) il = 0;
623 if( ih >= mBins ) ih = mBins - 1;
624 r_8 n = 0;
625 r_8 sx = 0;
626 r_8 sx2= 0;
627 for (int_4 i=il; i<=ih; i++) {
628 r_8 v = (mData[i]>=0.) ? mData[i] : -mData[i];
629 n += v;
630 sx += BinCenter(i)*v;
631 sx2+= BinCenter(i)*BinCenter(i)*v;
632 }
633 if( n == 0 ) return 0.;
634 sx2 = sx2/n - (sx/n)*(sx/n);
635 if( sx2>0. ) return sqrt( sx2 );
636 else return 0.;
637}
638
639/********* Methode *********/
640/*!
641 Valeur de la moyenne calculee entre x0-dx et x0+dx
642*/
643r_8 Histo::Mean(r_8 x0, r_8 dx) const
644{
645 r_8 sdata = 0;
646 r_8 sx = 0;
647 int_4 iMin = FindBin(x0-dx);
648 if (iMin<0) iMin = 0;
649 int_4 iMax = FindBin(x0+dx);
650 if (iMax>mBins) iMax=mBins;
651 for (int_4 i=iMin; i<iMax; i++) {
652 r_8 v = (mData[i]>=0.) ? mData[i] : -mData[i];
653 sx += BinCenter(i)*v;
654 sdata += v;
655 }
656 if(sdata>0.) return sx/sdata; else return mMin;
657}
658
659/********* Methode *********/
660/*!
661 Valeur du sigma calcule entre x0-dx et x0+dx
662*/
663r_8 Histo::Sigma(r_8 x0, r_8 dx) const
664{
665 r_8 sx = 0;
666 r_8 sx2= 0;
667 r_8 sdata = 0;
668 int_4 iMin = FindBin(x0-dx);
669 if (iMin<0) iMin = 0;
670 int_4 iMax = FindBin(x0+dx);
671 if (iMax>mBins) iMax=mBins;
672 for (int_4 i=iMin; i<iMax; i++) {
673 r_8 v = (mData[i]>=0.) ? mData[i] : -mData[i];
674 sx += BinCenter(i)*v;
675 sx2+= BinCenter(i)*BinCenter(i)*v;
676 sdata += v;
677 }
678 if(sdata>0.) return sqrt( sx2/sdata - (sx/sdata)*(sx/sdata) );
679 else return 0.;
680}
681
682/********* Methode *********/
683/*!
684 Valeur de la moyenne et du sigma nettoyes
685*/
686r_8 Histo::CleanedMean(r_8& sigma) const
687{
688 if (!nHist) return 0;
689 // on fait ca de facon bete, on pourra raffiner apres...
690 r_8 x0 = Mean();
691 r_8 s = Sigma()+binWidth;
692
693 for (int_4 i=0; i<3; i++) {
694 r_8 xx0 = Mean(x0,5*s);
695 s = Sigma(x0,5*s)+binWidth;
696 x0 = xx0;
697 }
698 sigma = s;
699 return x0;
700}
701
702/********* Methode *********/
703/*!
704 Valeur de la moyenne nettoyee
705*/
706r_8 Histo::CleanedMean() const
707{
708 if (!nHist) return 0;
709 r_8 s=0;
710 return CleanedMean(s);
711}
712
713/********* Methode *********/
714/*!
715 Retourne le nombre de bins non-nul
716*/
717int_4 Histo::BinNonNul() const
718{
719int_4 non=0;
720for (int_4 i=0;i<mBins;i++) if( mData[i] != 0. ) non++;
721return non;
722}
723
724/********* Methode *********/
725/*!
726 Retourne le nombre de bins ayant une erreur non-nulle
727*/
728int_4 Histo::ErrNonNul() const
729{
730if(mErr2==NULL) return -1;
731int_4 non=0;
732for (int_4 i=0;i<mBins;i++) if( mErr2[i] != 0. ) non++;
733return non;
734}
735
736/********* Methode *********/
737/*!
738 Renvoie le numero de bin tel que il y ait "per" pourcent entrees
739 entre le bin 0 et ce bin (y compris le contenu de ce bin).
740*/
741int_4 Histo::BinPercent(r_8 per) const
742{
743r_8 n = nHist*per;
744r_8 s = 0.;
745int_4 i;
746for(i=0; i<mBins; i++ ) {
747 s += mData[i];
748 if( s >= n ) break;
749}
750if( i == mBins ) i = mBins-1;
751return i;
752}
753
754/********* Methode *********/
755/*!
756 Renvoie les numeros de bins imin,imax (0=<i<bins) tels que:
757 \verbatim
758 notons I = bin contenant l'abscisse x
759 N1 = nombre d'entrees entre bin 0 et I compris
760 N2 = nombre d'entrees entre bin I et bins-1 compris
761 imin = bin tel que nombre d'entrees entre imin et I = N1 * per
762 imax = bin tel que nombre d'entrees entre I et imax = N2 * per
763 Return: <0 si echec
764 mMin(I-imin,imax-I) si ok
765 \endverbatim
766*/
767int_4 Histo::BinPercent(r_8 x,r_8 per,int_4& imin,int_4& imax) const
768{
769imin = imax = -1;
770if( per <= 0. ) return -1;
771
772int_4 I = FindBin(x);
773if( I<0 || I>=mBins ) return -2;
774
775r_8 N1 = 0.; for(int_4 i=0; i<=I; i++) N1 += mData[i]; N1 *= per;
776r_8 N2 = 0.; {for(int_4 i=I; i<mBins; i++) N2 += mData[i]; N2 *= per;}
777
778r_8 n = 0.;
779for(imin=I; imin>=0; imin--) { n += mData[imin]; if(n>=N1) break; }
780if( imin<0 ) imin = 0;
781// cout<<"I="<<I<<" imin="<<imin<<" n="<<n<<" N1="<<N1<<endl;
782
783n = 0.;
784for(imax=I; imax<mBins; imax++) { n += mData[imax]; if(n>=N2) break; }
785if( imax>=mBins ) imax = mBins-1;
786// cout<<"I="<<I<<" imax="<<imax<<" n="<<n<<" N2="<<N2<<endl;
787
788return ( imax-I > I-imin ) ? I-imin : imax-I ;
789}
790
791/********* Methode *********/
792/*!
793 Idem precedent mais renvoie xmin et xmax
794*/
795int_4 Histo::BinPercent(r_8 x,r_8 per,r_8& xmin,r_8& xmax) const
796{
797xmin = xmax = 0.;
798int_4 imin,imax;
799int_4 rc = BinPercent(x,per,imin,imax);
800if( rc >= 0 ) { xmin = BinLowEdge(imin); xmax = BinHighEdge(imax); }
801return rc;
802}
803
804/********* Methode *********/
805/*!
806 Remplace l'histogramme par son integrale normalise a norm:
807 si norm <= 0 : pas de normalisation, integration seule
808*/
809void Histo::HInteg(r_8 norm)
810{
811if( mBins <= 0 ) return; // createur par default
812if(mBins>1)
813 for(int_4 i=1; i<mBins; i++) {
814 mData[i] += mData[i-1];
815 if(mErr2!=NULL) mErr2[i] += mErr2[i-1];
816 }
817if( norm <= 0. ) return;
818norm /= mData[mBins-1];
819for(int_4 i=0; i<mBins; i++) {
820 mData[i] *= norm;
821 if(mErr2!=NULL) mErr2[i] *= norm*norm;
822}
823}
824
825/********* Methode *********/
826/*!
827 Remplace l'histogramme par sa derivee
828*/
829void Histo::HDeriv()
830{
831if( mBins <= 0 ) return; // createur par default
832if( mBins <= 1 ) return;
833r_8 *temp = new r_8[mBins];
834memcpy(temp, mData, mBins*sizeof(r_8));
835if(mBins>=3) for(int_4 i=1; i<mBins-1; i++)
836 temp[i] = (mData[i+1]-mData[i-1])/(2.*binWidth);
837temp[0] = (mData[1]-mData[0])/binWidth;
838temp[mBins-1] = (mData[mBins-1]-mData[mBins-2])/binWidth;
839memcpy(mData, temp, mBins*sizeof(r_8));
840delete [] temp;
841}
842
843/********* Methode *********/
844/*!
845 Pour rebinner l'histogramme sur nbinew bins
846*/
847void Histo::HRebin(int_4 nbinew)
848{
849 if( mBins <= 0 ) return; // createur par default
850 if( nbinew <= 0 ) return;
851
852 // memorisation de l'histogramme original
853 Histo H(*this);
854
855 // Le nombre de bins est il plus grand ??
856 if( nbinew > mBins ) {
857 delete [] mData; mData = NULL;
858 mData = new r_8[nbinew];
859 if( mErr2 != NULL ) {
860 delete [] mErr2; mErr2 = NULL;
861 mErr2 = new r_8[nbinew];
862 }
863 }
864
865 // remise en forme de this
866 mBins = nbinew;
867 this->Zero();
868 binWidth = (mMax-mMin)/mBins;
869 // On recopie les parametres qui n'ont pas changes
870 mUnder = H.mUnder;
871 mOver = H.mOver;
872
873
874 // Remplissage
875 for(int_4 i=0;i<mBins;i++) {
876 r_8 xmi = BinLowEdge(i);
877 r_8 xma = BinHighEdge(i);
878 int_4 imi = H.FindBin(xmi);
879 if( imi < 0 ) imi = 0;
880 int_4 ima = H.FindBin(xma);
881 if( ima >= H.mBins ) ima = H.mBins-1;
882 r_8 w = 0.;
883 if( ima == imi ) {
884 w = H(imi) * binWidth/H.binWidth;
885 } else {
886 w += H(imi) * (H.BinHighEdge(imi)-xmi)/H.binWidth;
887 w += H(ima) * (xma -H.BinLowEdge(ima))/H.binWidth;
888 if( ima > imi+1 )
889 for(int_4 ii=imi+1;ii<ima;ii++) w += H(ii);
890 }
891 AddBin(i, w);
892 }
893
894}
895
896/********* Methode *********/
897/*!
898 Retourne le nombre de maxima locaux, la valeur du maximum (maxi)
899 et sa position (imax), ainsi que la valeur du second maximum
900 local (maxn) et sa position (imaxn).
901 Attention: si un maximum a la meme valeur sur plusieurs bins
902 consecutifs, le bin le plus a droite est pris.
903*/
904int_4 Histo::MaxiLocal(r_8& maxi,int_4& imax,r_8& maxn,int_4& imaxn) const
905{
906int_4 nml = 0;
907imax = imaxn = -1;
908maxi = maxn = -1.;
909
910bool up = true;
911bool down = false;
912for(int_4 i=0;i<mBins;i++) {
913 if( !up ) if( mData[i] > mData[i-1] ) up = true;
914 if( up && !down ) {
915 if( i == mBins-1 ) down=true;
916 else if( mData[i] > mData[i+1] ) down=true;
917 }
918
919 if( up && down ) {
920 nml++;
921 up = down = false;
922 if( imax < 0 ) {
923 imax = i; maxi = mData[i];
924 } else if( mData[i] >= maxi ) {
925 imaxn = imax; maxn = maxi;
926 imax = i; maxi = mData[i];
927 } else {
928 if( imaxn < 0 || mData[i] >= maxn ) { imaxn = i; maxn = mData[i]; }
929 }
930 }
931
932}
933return nml;
934}
935
936/********* Methode *********/
937/*!
938 Fit de la position du maximum de l'histo par un polynome
939 de degre `degree' a `frac' pourcent du maximum.
940 L'histo est suppose etre remplit de valeurs positives
941*/
942r_8 Histo::FitMax(int_4 degree, r_8 frac, int_4 debug) const
943{
944 if (degree < 2 || degree > 3) degree = 3;
945 if (frac <= 0. || frac >= 1.) frac = 0.5;
946
947 if (debug > 1)
948 cout<<"Histo::FitMax : Nb Entrees histo ="<<NEntries()<<endl;
949
950 if (NEntries() < 1) throw ParmError(PExcLongMessage(""));
951
952 int_4 iMax = IMax();
953 r_8 hmax = (*this)(iMax);
954 r_8 xCenter = BinCenter(iMax);
955
956 if(debug>1)
957 cout<<"Max histo i="<<iMax<<" x="<<xCenter<<" v="<<hmax<<endl;
958
959 /* find limits at frac*hmax */
960
961 r_8 limit = frac*hmax;
962
963 volatile int_4 iLow = iMax;
964 while (iLow>0 && (*this)(iLow)>limit) iLow--;
965
966 volatile int_4 iHigh = iMax;
967 while (iHigh<NBins()-1 && (*this)(iHigh)>limit) iHigh++;
968
969 int_4 nLowHigh;
970 for(;;) {
971 nLowHigh = 0;
972 for (int_4 i=iLow; i<=iHigh; i++) if((*this)(i)>0) {
973 if(!mErr2) nLowHigh++;
974 else if(Error2(i)>0.) nLowHigh++;
975 }
976 if (debug > 1) cout <<"Limites histo "<<iLow<<" - "<<iHigh
977 <<" ("<<nLowHigh<<" non nuls)"<<endl;
978 if( nLowHigh >= degree+1 ) break;
979 iLow--; iHigh++;
980 if(iLow<0 && iHigh>=NBins()) {
981 if (debug>1)
982 cout<<"Mode histogramme = "<<xCenter
983 <<" BinCenter("<<iMax<<")"<<endl;
984 return xCenter;
985 }
986 if(iLow < 0 ) iLow = 0;
987 if(iHigh >= NBins()) iHigh = NBins()-1;
988 }
989
990 TVector<r_8> xFit(nLowHigh);
991 TVector<r_8> yFit(nLowHigh);
992 TVector<r_8> e2Fit(nLowHigh);
993 TVector<r_8> errcoef(1);
994 int_4 ii = 0;
995 for (int_4 j=iLow; j<=iHigh; j++) {
996 if ((*this)(j)>0) {
997 if(!mErr2) {
998 xFit(ii) = BinCenter(j)-xCenter;
999 yFit(ii) = (*this)(j);
1000 e2Fit(ii) = yFit(ii);
1001 ii++;
1002 } else if(Error2(j)>0.) {
1003 xFit(ii) = BinCenter(j)-xCenter;
1004 yFit(ii) = (*this)(j);
1005 e2Fit(ii) = Error2(j);
1006 ii++;
1007 }
1008 }
1009 }
1010 if(debug>4) {
1011 int_4 k;
1012 for(k=0;k<nLowHigh;k++) cout<<" "<<xFit(k); cout<<endl;
1013 for(k=0;k<nLowHigh;k++) cout<<" "<<yFit(k); cout<<endl;
1014 for(k=0;k<nLowHigh;k++) cout<<" "<<e2Fit(k); cout<<endl;
1015 }
1016 if( ii != nLowHigh ) throw ParmError(PExcLongMessage(""));
1017 Poly pol(degree);
1018 TRY {
1019 pol.Fit(xFit, yFit, e2Fit, degree, errcoef);
1020 if (debug>1) cout << "resultat fit = " << pol << endl;
1021 pol.Derivate();
1022 } CATCHALL {
1023 THROW_SAME;
1024 } ENDTRY
1025
1026 int_4 DPolDeg = pol.Degre();
1027 r_8 fd = 0.;
1028
1029 if (DPolDeg == 0) {
1030 // on est dans le cas d'un fit de droite
1031 if( pol[0] > 0. ) {
1032 // on a fitte une droite de pente >0.
1033 fd = xFit(nLowHigh-1) + binWidth/2. + xCenter;
1034 } else if( pol[0] < 0. ) {
1035 // on a fitte une droite de pente <0.
1036 fd = xFit(0) - binWidth/2. + xCenter;
1037 } else {
1038 // on a fitte une droite de pente =0. (creneau)
1039 fd = (xFit(0)+xFit(nLowHigh-1))/2. + xCenter;
1040 }
1041 } else if (DPolDeg == 1) {
1042 // on est dans le cas d'un fit de parabole
1043 r_8 r=0;
1044 if (pol.Root1(r)==0) throw ParmError(PExcLongMessage(""));
1045 fd = r + xCenter;
1046 } else if (DPolDeg == 2) {
1047 // on est dans le cas d'un fit de cubique
1048 r_8 r1=0;
1049 r_8 r2=0;
1050 if (pol.Root2(r1,r2) == 0) throw ParmError(PExcLongMessage(""));
1051 pol.Derivate();
1052 fd = (pol(r1)<0) ? r1 + xCenter : r2 + xCenter;
1053 } else {
1054 // on est dans un cas non prevu
1055 throw ParmError(PExcLongMessage(""));
1056 }
1057
1058 if(fd>mMax) fd = mMax;
1059 if(fd<mMin) fd = mMin;
1060
1061 if (debug>1)
1062 cout << "Mode histogramme = " << fd
1063 << " (DerPol.degre =" << DPolDeg
1064 << " pol.coeff[0] =" << pol[0]
1065 << ")" << endl;
1066
1067 return fd;
1068}
1069
1070
1071/********* Methode *********/
1072/*!
1073 Calcul de la largeur a frac pourcent du maximum
1074 autour du bin du maximum.
1075 L'histo est suppose etre remplit de valeurs positives
1076*/
1077r_8 Histo::FindWidth(r_8 frac, int_4 debug) const
1078{
1079 r_8 xmax = BinCenter( IMax() );
1080 return FindWidth(xmax,frac,debug);
1081}
1082
1083/********* Methode *********/
1084/*!
1085 Calcul de la largeur a frac pourcent de la valeur du bin xmax.
1086 L'histo est suppose etre remplit de valeurs positives
1087*/
1088r_8 Histo::FindWidth(r_8 xmax,r_8 frac, int_4 debug) const
1089{
1090 if (frac <= 0 || frac >= 1.) frac = 0.5;
1091
1092 if (debug > 1)
1093 cout << "Histo::FindWidth a " << frac
1094 << " de xmax= " << xmax
1095 << " , ndata= " << NData()
1096 << " , nent= " << NEntries()
1097 << " , nbin= " << NBins() << endl;
1098
1099 if (NEntries() < 1) throw ParmError(PExcLongMessage(""));
1100 if (NBins() < 3) throw ParmError(PExcLongMessage(""));
1101
1102 int_4 iMax = FindBin(xmax);
1103 if (iMax<0 || iMax>=NBins()) throw ParmError(PExcLongMessage(""));
1104 r_8 hmax = mData[iMax];
1105 r_8 limit = frac*hmax;
1106 if (debug > 1)
1107 cout << " Max histo[" << iMax << "] = " << hmax
1108 << ", limite " << limit << endl;
1109
1110 int_4 iLow = iMax;
1111 while (iLow>=0 && mData[iLow]>limit) iLow--;
1112 if( iLow < 0 ) iLow = 0;
1113
1114 int_4 iHigh = iMax;
1115 while (iHigh<NBins() && mData[iHigh]>limit) iHigh++;
1116 if( iHigh >=NBins() ) iHigh = NBins()-1;
1117
1118 r_8 xlow = BinCenter(iLow);
1119 r_8 ylow = mData[iLow];
1120
1121 r_8 xlow1=xlow, ylow1=ylow;
1122 if(iLow+1<NBins()) {
1123 xlow1 = BinCenter(iLow+1);
1124 ylow1 = mData[iLow+1];
1125 }
1126
1127 r_8 xhigh = BinCenter(iHigh);
1128 r_8 yhigh = mData[iHigh];
1129
1130 r_8 xhigh1=xhigh, yhigh1=yhigh;
1131 if(iHigh-1>=0) {
1132 xhigh1 = BinCenter(iHigh-1);
1133 yhigh1 = mData[iHigh-1];
1134 }
1135
1136 r_8 xlpred,xhpred,wd;
1137
1138 if(ylow1>ylow) {
1139 xlpred = xlow + (xlow1-xlow)/(ylow1-ylow)*(limit-ylow);
1140 if(xlpred < xlow) xlpred = xlow;
1141 } else xlpred = xlow;
1142
1143 if(yhigh1>yhigh) {
1144 xhpred = xhigh + (xhigh1-xhigh)/(yhigh1-yhigh)*(limit-yhigh);
1145 if(xhpred > xhigh) xhpred = xhigh;
1146 } else xhpred = xhigh;
1147
1148 wd = xhpred - xlpred;
1149
1150 if (debug > 1) {
1151 cout << "Limites histo: " << " Width " << wd << endl;
1152 cout << " Low: [" << iLow << "]=" << ylow << " pred-> " << xlpred
1153 << " - High: [" << iHigh << "]=" << yhigh << " pred-> " << xhpred
1154 << endl;
1155 }
1156
1157 return wd;
1158}
1159
1160
1161/********* Methode *********/
1162/*!
1163 Cf suivant mais im est le bin du maximum de l'histo
1164*/
1165int_4 Histo::EstimeMax(r_8& xm,int_4 SzPav) const
1166{
1167int_4 im = IMax();
1168return EstimeMax(im,xm,SzPav);
1169}
1170
1171/********* Methode *********/
1172/*!
1173 Determine l'abscisses du maximum donne par im
1174 en moyennant dans un pave SzPav autour du maximum
1175 \verbatim
1176 Return:
1177 0 = si fit maximum reussi avec SzPav pixels
1178 1 = si fit maximum reussi avec moins que SzPav pixels
1179 2 = si fit maximum echoue et renvoit BinCenter()
1180 -1 = si echec: SzPav <= 0 ou im hors limites
1181 \endverbatim
1182*/
1183int_4 Histo::EstimeMax(int_4& im,r_8& xm,int_4 SzPav) const
1184{
1185xm = 0;
1186if( SzPav <= 0 ) return -1;
1187if( im < 0 || im >= mBins ) return -1;
1188
1189if( SzPav%2 == 0 ) SzPav++;
1190SzPav = (SzPav-1)/2;
1191
1192int_4 rc = 0;
1193r_8 dxm = 0, wx = 0;
1194for(int_4 i=im-SzPav;i<=im+SzPav;i++) {
1195 if( i<0 || i>= mBins ) {rc=1; continue;}
1196 dxm += BinCenter(i) * (*this)(i);
1197 wx += (*this)(i);
1198}
1199
1200if( wx > 0. ) {
1201 xm = dxm/wx;
1202 return rc;
1203} else {
1204 xm = BinCenter(im);
1205 return 2;
1206}
1207
1208}
1209
1210/********* Methode *********/
1211/*!
1212 Determine la largeur a frac% du maximum a gauche (widthG)
1213 et a droite (widthD)
1214*/
1215void Histo::EstimeWidthS(r_8 frac,r_8& widthG,r_8& widthD) const
1216{
1217int_4 i;
1218widthG = widthD = -1.;
1219if( mBins<=1 || frac<=0. || frac>=1. ) return;
1220
1221int_4 imax = 0;
1222r_8 maxi = mData[0];
1223for(i=1;i<mBins;i++) if(mData[i]>maxi) {imax=i; maxi=mData[i];}
1224r_8 xmax = BinCenter(imax);
1225r_8 maxf = maxi * frac;
1226
1227// recherche du sigma a gauche
1228widthG = 0.;
1229for(i=imax;i>=0;i--) if( mData[i] <= maxf ) break;
1230if(i<0) i=0;
1231if(i<imax) {
1232 if( mData[i+1] != mData[i] ) {
1233 widthG = BinCenter(i) + binWidth
1234 * (maxf-mData[i])/(mData[i+1]-mData[i]);
1235 widthG = xmax - widthG;
1236 } else widthG = xmax - BinCenter(i);
1237}
1238
1239// recherche du sigma a droite
1240widthD = 0.;
1241for(i=imax;i<mBins;i++) if( mData[i] <= maxf ) break;
1242if(i>=mBins) i=mBins-1;
1243if(i>imax) {
1244 if( mData[i] != mData[i-1] ) {
1245 widthD = BinCenter(i) - binWidth
1246 * (maxf-mData[i])/(mData[i-1]-mData[i]);
1247 widthD -= xmax;
1248 } else widthD = BinCenter(i) - xmax;
1249}
1250
1251}
1252
1253/********* Methode *********/
1254/*!
1255 Impression de l'histogramme
1256 \verbatim
1257 hdyn = nombre de colonnes pour imprimer les etoiles
1258 si =0 alors defaut(100),
1259 si <0 pas de print histo seulement infos
1260 hmin = minimum de la dynamique
1261 hmax = maximum de la dynamique
1262 si hmax<=hmin : hmin=VMin() hmax=VMax()
1263 si hmax<=hmin et hmin=0 : hmin=0 hmax=VMax()
1264 sinon : hmin hmax
1265 pflag < 0 : on imprime les informations (nbin,min,...) sans l'histogramme
1266 = 0 : on imprime "BinCenter(i) mData[i]" (note "... ...")
1267 bit 0 on : (v=1): numero_bin "... ..."
1268 bit 1 on : (v=2): "... ..." erreur
1269 \endverbatim
1270*/
1271
1272void Histo::Show(ostream & os) const
1273{
1274 os << " Histo::Show "
1275 << " nHist=" << nHist << " nEntries=" << nEntries
1276 << " mUnder=" << mUnder << " mOver=" << mOver << endl;
1277 os << " mBins=" << mBins
1278 << " min=" << mMin << " mMax=" << mMax
1279 << " binWidth=" << binWidth << endl;
1280 os << " mean=" << Mean() << " r.m.s=" << Sigma()
1281 << " Errors="<<HasErrors()<< endl;
1282}
1283
1284void Histo::Print(int_4 hdyn,r_8 hmin, r_8 hmax,int_4 pflag,
1285 int_4 il, int_4 ih) const
1286{
1287
1288 if( il > ih ) { il = 0; ih = mBins-1; }
1289 if( il < 0 ) il = 0;
1290 if( ih >= mBins ) ih = mBins-1;
1291
1292 r_8 dhmin = hmin;
1293 r_8 dhmax = hmax;
1294 r_8 hb,hbmn,hbmx;
1295
1296 if(hdyn==0) hdyn = 100;
1297
1298 Show(cout);
1299
1300 if(hdyn<0 || pflag<0 ) return;
1301
1302 if(dhmax<=dhmin) { if(hmin != 0.) dhmin = VMin(); else dhmin=0.;
1303 dhmax = VMax(); }
1304 if(dhmin>dhmax) return;
1305 if(dhmin==dhmax) {dhmin -= 1.; dhmax += 1.;}
1306 r_8 wb = (dhmax-dhmin) / hdyn;
1307
1308 // determination de la position de la valeur zero
1309 int_4 i0 = (int_4)(-dhmin/wb);
1310
1311 // si le zero est dans la dynamique,
1312 // il doit imperativement etre une limite de bin
1313 if( 0 <= i0 && i0 < hdyn ) {
1314 hbmn = dhmin + i0*wb;
1315 hbmx = hbmn + wb;
1316 if( hbmn != 0. ) {
1317 hbmn *= -1.;
1318 if( hbmn < hbmx ) {
1319 // le zero est + pres du bord negatif du bin
1320 dhmin += hbmn;
1321 dhmax += hbmn;
1322 } else {
1323 // le zero est + pres du bord positif du bin
1324 dhmin -= hbmx;
1325 dhmax -= hbmx;
1326 }
1327 wb = (dhmax-dhmin) / hdyn;
1328 i0 = (int_4)(-dhmin/wb);
1329 }
1330 }
1331
1332 cout <<" bin minimum="<<dhmin<<" bin maximum="<<dhmax
1333 <<" binw="<<wb<< endl;
1334
1335 char* s = new char[hdyn+1];
1336 s[hdyn] = '\0';
1337
1338 // premiere ligne
1339 {for(int_4 i=0;i<hdyn;i++) s[i] = '=';}
1340 if( 0 <= i0 && i0 < hdyn ) s[i0] = '0';
1341 if(pflag&1) printf("====");
1342 printf("======================");
1343 if(pflag&2 && mErr2!=NULL) printf("===========");
1344 printf("==%s\n",s);
1345
1346 // histogramme
1347 {for(int_4 i=il;i<=ih;i++) {
1348 for(int_4 k=0;k<hdyn;k++) s[k] = ' ';
1349 hb = (*this)(i);
1350
1351 //choix du bin (hdyn bin entre [dhmin,dhmax[
1352 int_4 ii = (int_4)( (hb-dhmin)/wb );
1353 if(ii<0) ii = 0; else if(ii>=hdyn) ii = hdyn-1;
1354
1355 // limite du bin
1356 hbmn = dhmin + ii*wb;
1357 hbmx = hbmn + wb;
1358
1359 // remplissage de s[] en tenant compte des courbes +/-
1360 if(i0<0) {
1361 // courbe entierement positive
1362 for(int_4 k=0;k<=ii;k++) s[k] = 'X';
1363 } else if(i0>=hdyn) {
1364 // courbe entierement negative
1365 for(int_4 k=hdyn-1;k>=ii;k--) s[k] = 'X';
1366 } else {
1367 // courbe positive et negative
1368 s[i0] = '|';
1369 if(ii>i0) for(int_4 k=i0+1;k<=ii;k++) s[k] = 'X';
1370 else if(ii<i0) for(int_4 k=ii;k<i0;k++) s[k] = 'X';
1371 else s[ii] = 'X';
1372 }
1373
1374 // valeur a mettre dans le bin le plus haut/bas
1375 int_4 ib;
1376 if(hb>0.) ib = (int_4)( 10.*(hb-hbmn)/(hbmx-hbmn) );
1377 else if(hb<0.) ib = (int_4)( 10.*(hbmx-hb)/(hbmx-hbmn) );
1378 else ib = -1;
1379 if(ib==-1) s[ii] = '|';
1380 else if(ib==0) s[ii] = '.';
1381 else if(ib>0 && ib<10) s[ii] = (char)((int_4) '0' + ib);
1382
1383 // traitement des saturations +/-
1384 if( hb < dhmin ) s[0] = '*';
1385 else if( hb > dhmax ) s[hdyn-1] = '*';
1386
1387 if(pflag&1) printf("%3d ",i);
1388 printf("%10.4g %10.4g ",BinCenter(i),hb);
1389 if(pflag&2 && mErr2!=NULL) printf("%10.4g ",Error(i));
1390 printf("= %s\n",s);
1391 }}
1392
1393 // derniere ligne
1394 for(int_4 i=0;i<hdyn;i++) s[i] = '=';
1395 if( 0 <= i0 && i0 < hdyn ) s[i0] = '0';
1396 if(pflag&1) printf("====");
1397 printf("======================");
1398 if(pflag&2 && mErr2!=NULL) printf("===========");
1399 printf("==%s\n",s);
1400
1401 // valeur basse des bins (sur ["ndig-1" digits + signe] = ndig char (>=3))
1402 const int_4 ndig = 7;
1403 char sn[2*ndig+10];
1404 hb = ( fabs(dhmin) > fabs(dhmax) ) ? fabs(dhmin) : fabs(dhmax);
1405 int_4 n;
1406 if( hb > 0. ) n = (int_4)(log10(hb*1.00000001)); else n = 1;
1407 r_8 scaledig = pow(10.,(r_8) ndig-2);
1408 r_8 expo = scaledig/pow(10.,(r_8) n);
1409 // cout <<"n="<<n<<" hb="<<hb<<" scaledig="<<scaledig<<" expo="<<expo<<endl;
1410 for(int_4 k=0;k<ndig;k++) {
1411 for(int_4 i=0;i<hdyn;i++) s[i] = ' ';
1412 {for(int_4 i=0;i<hdyn;i++) {
1413 n = (int_4)( (dhmin + i*wb)*expo );
1414 for(int_4 j=0;j<2*ndig+10;j++) sn[j] = ' ';
1415 sprintf(sn,"%d%c",n,'\0');
1416 strip(sn,'B',' ');
1417 // cout <<"n="<<n<<" sn=("<<sn<<") l="<<strlen(sn)<<" k="<<k;
1418 if( (int_4) strlen(sn) > k ) s[i] = sn[k];
1419 // cout <<" s=("<<s<<")"<<endl;
1420 }}
1421 if(pflag&1) printf(" ");
1422 printf(" ");
1423 if(pflag&2 && mErr2!=NULL) printf(" ");
1424 printf(" %s\n",s);
1425 }
1426 printf(" (valeurs a multiplier par %.0e)\n",1./expo);
1427
1428 delete[] s;
1429}
1430
1431
1432///////////////////////////////////////////////////////////
1433// --------------------------------------------------------
1434// Les objets delegues pour la gestion de persistance
1435// --------------------------------------------------------
1436///////////////////////////////////////////////////////////
1437
1438
1439DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
1440void ObjFileIO<Histo>::ReadSelf(PInPersist& is)
1441{
1442char strg[256];
1443
1444if(dobj==NULL) dobj=new Histo;
1445 else dobj->Delete();
1446
1447// Lecture entete
1448is.GetLine(strg, 255);
1449bool nentries_en_8_bytes=false;
1450if(strg[0]=='V' && strg[1]=='_' && strg[2]=='2') nentries_en_8_bytes=true;
1451is.GetLine(strg, 255);
1452is.GetLine(strg, 255);
1453
1454// Lecture des valeurs
1455is.Get(dobj->mBins);
1456if(nentries_en_8_bytes) is.Get(dobj->nEntries);
1457 else {int_4 dum; is.Get(dum); dobj->nEntries=(uint_8)dum;}
1458int_4 errok;
1459is.Get(errok);
1460
1461is.Get(dobj->binWidth);
1462is.Get(dobj->mMin);
1463is.Get(dobj->mMax);
1464is.Get(dobj->mUnder);
1465is.Get(dobj->mOver);
1466
1467is.Get(dobj->nHist);
1468
1469// Lecture des donnees Histo 1D
1470dobj->mData = new r_8[dobj->mBins];
1471is.GetLine(strg, 255);
1472is.Get(dobj->mData, dobj->mBins);
1473
1474// Lecture des erreurs
1475if(errok) {
1476 is.GetLine(strg, 255);
1477 dobj->mErr2 = new r_8[dobj->mBins];
1478 is.Get(dobj->mErr2, dobj->mBins);
1479}
1480
1481return;
1482}
1483
1484DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
1485void ObjFileIO<Histo>::WriteSelf(POutPersist& os) const
1486{
1487if (dobj == NULL) return;
1488char strg[256];
1489
1490// Que faut-il ecrire?
1491int_4 errok = (dobj->mErr2) ? 1 : 0;
1492
1493// Ecriture entete pour identifier facilement
1494sprintf(strg,"V_2 mBins=%6d NEnt=%15d errok=%1d",dobj->mBins,dobj->nEntries,errok);
1495os.PutLine(strg);
1496sprintf(strg,"binw=%g mMin=%g mMax=%g",dobj->binWidth,dobj->mMin,dobj->mMax);
1497os.PutLine(strg);
1498sprintf(strg, "mUnder=%g mOver=%g nHist=%g",dobj->mUnder,dobj->mOver,dobj->nHist);
1499os.PutLine(strg);
1500
1501// Ecriture des valeurs
1502os.Put(dobj->mBins);
1503os.Put(dobj->nEntries);
1504os.Put(errok);
1505
1506os.Put(dobj->binWidth);
1507os.Put(dobj->mMin);
1508os.Put(dobj->mMax);
1509os.Put(dobj->mUnder);
1510os.Put(dobj->mOver);
1511
1512os.Put(dobj->nHist);
1513
1514// Ecriture des donnees Histo 1D
1515sprintf(strg,"Histo: Tableau des donnees %d",dobj->mBins);
1516os.PutLine(strg);
1517os.Put(dobj->mData, dobj->mBins);
1518
1519// Ecriture des erreurs
1520if(errok) {
1521 sprintf(strg,"Histo: Tableau des erreurs %d",dobj->mBins);
1522 os.PutLine(strg);
1523 os.Put(dobj->mErr2, dobj->mBins);
1524}
1525
1526return;
1527}
1528
1529#ifdef __CXX_PRAGMA_TEMPLATES__
1530#pragma define_template ObjFileIO<Histo>
1531#endif
1532
1533#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
1534template class ObjFileIO<Histo>;
1535#endif
Note: See TracBrowser for help on using the repository browser.