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

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

Histos/Hprof/Histo2D en r_8 cmv 26/7/00

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