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

Last change on this file since 4035 was 3951, checked in by cmv, 15 years ago

choix non logique au niveau des degres de fit par defaut, cmv 22/02/2011

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