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

Last change on this file since 3534 was 3236, checked in by ansari, 18 years ago

Ajout namespace SOPHYA ds les fichiers .cc au lieu de include sopnamsp.h en presence de DECL_TEMP_SPEC , cmv+reza 27/04/2007

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