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

Last change on this file since 3181 was 3110, checked in by cmv, 19 years ago

ajout methodes Sum et Sum2 cmv 20/11/2006

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