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

Last change on this file since 2615 was 2615, checked in by cmv, 21 years ago

using namespace sophya enleve de machdefs.h, nouveau sopnamsp.h cmv 10/09/2004

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