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

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

correc bug HistoErr::operator=() + remise en forme createur/destructeur Histos cmv 15/9/04

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