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

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

doc + vire warning cmv 18/04/00

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