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

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

amelioration gestion allocations cmv 13/8/2006

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