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

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

correction bug + addaptation pour ecriture fits cmv 12/8/2006

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