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

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

ReCenterBin deplace methode Histo (was HistErr) cmv 7/8/2006

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