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

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

on vire FitResidus/Function -> cf objfitter cmv 28/7/00

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