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

Last change on this file since 2604 was 2507, checked in by ansari, 22 years ago

Remplacement THROW par throw et suppression END_CONSTRUCTOR - Reza 15/03/2004

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