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

Last change on this file since 3950 was 3950, checked in by cmv, 15 years ago

ajout d'une methode ReSize publique, cmv 18/02/2011

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