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

Last change on this file since 914 was 914, checked in by ansari, 25 years ago

documentation cmv 13/4/00

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