source: Sophya/trunk/SophyaLib/HiStats/hisprof.cc@ 1447

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

Methode Show et operateur << pour Histos - Reza 20/2/2001

File size: 9.7 KB
Line 
1#include "machdefs.h"
2#include <string.h>
3#include <stdio.h>
4#include <math.h>
5#include "hisprof.h"
6#include "perrors.h"
7
8/*!
9 \class SOPHYA::HProf
10 \ingroup HiStats
11 Classe de profil d'histogrammes.
12*/
13
14/********* Methode *********/
15/*!
16 Constructeur par defaut.
17*/
18HProf::HProf()
19: Histo()
20, SumY(NULL), SumY2(NULL), SumW(NULL), Ok(false), YMin(1.), YMax(-1.), Opt(0)
21{
22 END_CONSTRUCTOR
23}
24
25/********* Methode *********/
26/*!
27 Constructeur. Histogramme de profil de ``nBin'' bins entre ``xMin''
28 et ``xMax'' avec coupure d'acceptance sur y entre ``yMin'' et ``yMax''.
29 Si yMin>=yMax alors pas de coupure d'acceptance sur y.
30 Par defaut l'erreur du profil represente la dispersion dans le bin,
31 SetErrOpt(1) permet de demander de calculer l'erreur sur la moyenne.
32*/
33HProf::HProf(r_8 xMin, r_8 xMax, int_4 nBin, r_8 yMin, r_8 yMax)
34: Histo(xMin,xMax,nBin)
35, SumY( (nBin>0) ? new r_8[nBin] : NULL)
36, SumY2((nBin>0) ? new r_8[nBin] : NULL)
37, SumW( (nBin>0) ? new r_8[nBin] : NULL)
38, Ok(false), YMin(yMin), YMax(yMax), Opt(0)
39{
40 Histo::Errors();
41 Zero();
42 END_CONSTRUCTOR
43}
44
45/********* Methode *********/
46/*!
47 Constructeur.
48*/
49HProf::HProf(r_4 xMin, r_4 xMax, int_4 nBin, r_4 yMin, r_4 yMax)
50: Histo((r_8)xMin,(r_8)xMax,nBin)
51, SumY( (nBin>0) ? new r_8[nBin] : NULL)
52, SumY2((nBin>0) ? new r_8[nBin] : NULL)
53, SumW( (nBin>0) ? new r_8[nBin] : NULL)
54, Ok(false), YMin((r_8)yMin), YMax((r_8)yMax), Opt(0)
55{
56 Histo::Errors();
57 Zero();
58 END_CONSTRUCTOR
59}
60
61/********* Methode *********/
62/*!
63 Constructeur par copie.
64*/
65HProf::HProf(const HProf& H)
66: Histo(H)
67, SumY((H.mBins>0) ? new r_8[H.mBins] : NULL)
68, SumY2((H.mBins>0) ? new r_8[H.mBins] : NULL)
69, SumW((H.mBins>0) ? new r_8[H.mBins] : NULL)
70, Ok(H.Ok), YMin(H.YMin), YMax(H.YMax), Opt(H.Opt)
71{
72 if(mBins>0) {
73 memcpy(SumY, H.SumY, mBins*sizeof(r_8));
74 memcpy(SumY2, H.SumY2, mBins*sizeof(r_8));
75 memcpy(SumW, H.SumW, mBins*sizeof(r_8));
76 }
77 UpdateHisto();
78 END_CONSTRUCTOR
79}
80
81/********* Methode *********/
82/*!
83 Des-allocation
84*/
85void HProf::Delete()
86{
87 if( SumY != NULL ) { delete[] SumY; SumY = NULL;}
88 if( SumY2 != NULL ) { delete[] SumY2; SumY2 = NULL;}
89 if( SumW != NULL ) { delete[] SumW; SumW = NULL;}
90 Ok = false;
91}
92
93/********* Methode *********/
94/*!
95 Destructeur
96*/
97HProf::~HProf()
98{
99Delete();
100}
101
102/********* Methode *********/
103/*!
104Calcule la partie histogramme du profile si elle n'est pas a jour.
105*/
106void HProf::UpdateHisto(bool force) const
107{
108if(!Ok || force) updatehisto();
109}
110
111/********* Methode *********/
112/*!
113 Remise a zero
114*/
115void HProf::Zero()
116{
117 memset(SumY, 0, mBins*sizeof(r_8));
118 memset(SumY2, 0, mBins*sizeof(r_8));
119 memset(SumW, 0, mBins*sizeof(r_8));
120 Ok = false;
121 Histo::Zero();
122}
123
124
125/********* Methode *********/
126/*!
127 Pour changer l'option de calcul de l'erreur du profile.
128 Si ``spread'' = true alors l'erreur represente la dispersion
129 des donnees dans le bin, si = false elle represente l'erreur
130 sur la moyenne du bin.
131 \verbatim
132 - Pour le bin (j):
133 H(j) = sum(y), E(j) = sum(y^2), L(j) = sum(w)
134 -> s(j) = sqrt(E(j)/L(j) - (H(j)/L(j))^2) dispersion
135 -> e(j) = s(j)/sqrt(L(j)) erreur sur la moyenne
136 spread=true: opt=0 : dispersion des donnees dans le bin = s(j)
137 spread=false: opt=1 : erreur sur la moyenne du bin = e(j)
138 \endverbatim
139*/
140void HProf::SetErrOpt(bool spread)
141{
142uint_2 opt = (spread) ? 0 : 1;
143if(opt!=Opt) {Opt=opt; Ok=false;}
144}
145
146/********* Methode *********/
147/*!
148 Pour mettre a jour l'histogramme de profil.
149 Il est important d'appeler cette methode si on veut
150 utiliser les methodes de la classe Histo qui ne sont
151 pas redefinies dans la classe HProf.
152 En effet, pour des raisons de precision la classe
153 HProf travaille avec des tableaux en double precision
154 et seulement au moment ou l'on a besoin de l'histogramme
155 ce dernier est rempli avec les valeurs demandees (moyenne
156 et dispersion/erreur sur la moyenne).
157*/
158void HProf::updatehisto() const
159{
160r_8 m,e2;
161if(mBins>0) for(int_4 i=0;i<mBins;i++) {
162 if(SumW[i]<=0.) {
163 m = e2 = 0.;
164 } else {
165 m = SumY[i]/SumW[i];
166 e2 = SumY2[i]/SumW[i] - m*m;
167 if(Opt) e2 /= SumW[i];
168 }
169 mData[i] = m;
170 mErr2[i] = e2;
171}
172Ok = true;
173// Attention, a cause de "WriteSelf const" updatehisto doit etre "const".
174// Comme on veut modifier Ok, on est oblige de faire cette entourloupe:
175HProf *buff = (HProf *) this;
176buff->Ok = true;
177}
178
179/********* Methode *********/
180/*!
181 Addition au contenu de l'histo pour abscisse x de la valeur y et poids w
182*/
183void HProf::Add(r_8 x, r_8 y, r_8 w)
184{
185 if(YMax>YMin && (y<YMin || YMax<y)) return;
186 int_4 numBin = FindBin(x);
187 if (numBin<0) mUnder += w;
188 else if (numBin>=mBins) mOver += w;
189 else {
190 Ok = false;
191 SumY[numBin] += y;
192 SumY2[numBin] += y*y;
193 SumW[numBin] += w;
194 nHist += w;
195 nEntries++;
196 }
197}
198
199/********* Methode *********/
200/*!
201 Addition au contenu de l'histo bin numBin de la valeur y poids w
202*/
203void HProf::AddBin(int_4 numBin, r_8 y, r_8 w)
204{
205 if(YMax>YMin && (y<YMin || YMax<y)) return;
206 if (numBin<0) mUnder += w;
207 else if (numBin>=mBins) mOver += w;
208 else {
209 Ok = false;
210 SumY[numBin] += y;
211 SumY2[numBin] += y*y;
212 SumW[numBin] += w;
213 nHist += w;
214 nEntries++;
215 }
216}
217
218/********* Methode *********/
219/*!
220 Operateur HProf H = H1
221*/
222HProf& HProf::operator = (const HProf& h)
223{
224if(this == &h) return *this;
225if( h.mBins > mBins ) Delete();
226Histo *hthis = (Histo *) this;
227*hthis = (Histo) h;
228if(!SumY) SumY = new r_8[mBins];
229if(!SumY2) SumY2 = new r_8[mBins];
230if(!SumW) SumW = new r_8[mBins];
231memcpy(SumY, h.SumY, mBins*sizeof(r_8));
232memcpy(SumY2, h.SumY2, mBins*sizeof(r_8));
233memcpy(SumW, h.SumW, mBins*sizeof(r_8));
234Ok = h.Ok;
235YMin = h.YMin;
236YMax = h.YMax;
237Opt = h.Opt;
238
239return *this;
240}
241
242/********* Methode *********/
243/*!
244 Operateur HProf H += H1
245
246 Attention dans cette addition il n'y a pas de gestion
247 des YMin et YMax. L'addition est faite meme si les limites
248 en Y de ``a'' sont differentes de celles de ``this''.
249*/
250HProf& HProf::operator += (const HProf& a)
251{
252if(mBins!=a.mBins) THROW(sizeMismatchErr);
253Histo *hthis = (Histo *) this;
254*hthis += (Histo) a;
255if(mBins>0) for(int_4 i=0;i<mBins;i++) {
256 SumY[i] += a.SumY[i];
257 SumY2[i] += a.SumY2[i];
258 SumW[i] += a.SumW[i];
259}
260updatehisto();
261
262return *this;
263}
264
265/********* Methode *********/
266/*!
267 Pour rebinner l'histogramme de profile sur nbinew bins
268*/
269void HProf::HRebin(int_4 nbinew)
270{
271 if( mBins <= 0 ) return; // createur par default
272 if( nbinew <= 0 ) return;
273
274 // memorisation de l'HProf original
275 HProf H(*this);
276
277 // Rebin de la partie Histo
278 int_4 binold = mBins;
279 Histo::HRebin(nbinew);
280
281 // Le nombre de bins est il plus grand ??
282 if( mBins > binold ) {
283 delete [] SumY; SumY = new r_8[nbinew]; memset(SumY, 0,mBins*sizeof(r_8));
284 delete [] SumY2; SumY2 = new r_8[nbinew]; memset(SumY2,0,mBins*sizeof(r_8));
285 delete [] SumW; SumW = new r_8[nbinew]; memset(SumW, 0,mBins*sizeof(r_8));
286 }
287
288 // Remplissage des parties propres au HPprof
289 for(int_4 i=0;i<mBins;i++) {
290 r_8 xmi = BinLowEdge(i);
291 r_8 xma = BinHighEdge(i);
292 int_4 imi = H.FindBin(xmi);
293 if( imi < 0 ) imi = 0;
294 int_4 ima = H.FindBin(xma);
295 if( ima >= H.mBins ) ima = H.mBins-1;
296 r_8 wY = 0., wY2 = 0., wW = 0.;
297 if( ima == imi ) {
298 wY = H.SumY[imi] * binWidth/H.binWidth;
299 wY2 = H.SumY2[imi] * binWidth/H.binWidth;
300 wW = H.SumW[imi] * binWidth/H.binWidth;
301 } else {
302 wY += H.SumY[imi] * (H.BinHighEdge(imi)-xmi)/H.binWidth;
303 wY += H.SumY[ima] * (xma -H.BinLowEdge(ima))/H.binWidth;
304 wY2 += H.SumY2[imi] * (H.BinHighEdge(imi)-xmi)/H.binWidth;
305 wY2 += H.SumY2[ima] * (xma -H.BinLowEdge(ima))/H.binWidth;
306 wW += H.SumW[imi] * (H.BinHighEdge(imi)-xmi)/H.binWidth;
307 wW += H.SumW[ima] * (xma -H.BinLowEdge(ima))/H.binWidth;
308 if(ima>imi+1) for(int_4 ii=imi+1;ii<ima;ii++)
309 {wY += H.SumY[ii]; wY2 += H.SumY2[ii]; wW += H.SumW[ii];}
310 }
311 SumY[i] += wY; SumY2[i] += wY2; SumW[i] += wW;
312 }
313 // On synchronise les tableaux Sum?? et l'Histogramme
314 updatehisto();
315}
316
317void HProf::Show(ostream & os) const
318{
319 UpdateHisto();
320 Histo::Show(os);
321}
322
323///////////////////////////////////////////////////////////
324// --------------------------------------------------------
325// Les objets delegues pour la gestion de persistance
326// --------------------------------------------------------
327///////////////////////////////////////////////////////////
328
329
330void ObjFileIO<HProf>::ReadSelf(PInPersist& is)
331{
332char strg[256];
333
334if(dobj==NULL) dobj=new HProf;
335 else dobj->Delete();
336
337// Lecture entete
338is.GetLine(strg,255);
339
340// Lecture des valeurs
341is.Get(dobj->mBins);
342is.Get(dobj->YMin);
343is.Get(dobj->YMax);
344is.Get(dobj->Opt);
345dobj->Ok = true;
346
347// Lecture des donnees propres a l'histogramme de profil.
348is.GetLine(strg,255);
349dobj->SumY = new r_8[dobj->mBins];
350dobj->SumY2 = new r_8[dobj->mBins];
351dobj->SumW = new r_8[dobj->mBins];
352is.Get(dobj->SumY, dobj->mBins);
353is.Get(dobj->SumY2, dobj->mBins);
354is.Get(dobj->SumW, dobj->mBins);
355
356// Lecture de l'histogramme
357is >> (Histo&)(*dobj);
358return;
359}
360
361void ObjFileIO<HProf>::WriteSelf(POutPersist& os) const
362{
363if (dobj == NULL) return;
364char strg[256];
365
366dobj->UpdateHisto();
367
368// Ecriture entete pour identifier facilement
369sprintf(strg,"HProf: YMin=%f YMax=%f Opt=%1d",dobj->YMin,dobj->YMax,dobj->Opt);
370os.PutLine(strg);
371
372// Ecriture des valeurs
373os.Put(dobj->mBins);
374os.Put(dobj->YMin);
375os.Put(dobj->YMax);
376os.Put(dobj->Opt);
377
378// Ecriture des donnees propres a l'histogramme de profil.
379sprintf(strg,"HProf: SumY SumY2 SumW");
380os.PutLine(strg);
381os.Put(dobj->SumY, dobj->mBins);
382os.Put(dobj->SumY2, dobj->mBins);
383os.Put(dobj->SumW, dobj->mBins);
384
385// Ecriture de l'histogramme
386// FIO_Histo fio_h((Histo&)*dobj);
387// fio_h.Write(os);
388os << (Histo&)(*dobj);
389
390return;
391}
392
393#ifdef __CXX_PRAGMA_TEMPLATES__
394#pragma define_template ObjFileIO<HProf>
395#endif
396
397#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
398template class ObjFileIO<HProf>;
399#endif
Note: See TracBrowser for help on using the repository browser.