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

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

cmv 7/7/2000

hisprof.cc,h:

fonction IsOk()
GetMean -> GetValue (mauvais nom)
float Error2() -> double Error2()
nouveau: GetError(TVector<r_8>& v)
HProf::PrintF() sur-ecriture de Histo::PrintF
protection dans createur par copie dans alloc

SumY... pour le cas ou H.bins==0

protection dans UpdateHisto pour HProf cree par defaut (bins==0)
Dans WriteSelf UpdateHisto appele que si necessaire (IsOk()?)

histos2.cc : le Print() dit si les erreurs ont ete demandees
histos.cc,h:

protection dans createur par copie dans alloc

pour le cas ou H.bins==0

protection dans Zero() pour Histo cree par defaut (bins==0)
protection dans operator=() pour Histo cree par defaut (bins==0)
le Print() dit si les erreurs ont ete demandees

cmv 7/7/2000

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