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

Last change on this file since 2312 was 2312, checked in by cmv, 23 years ago

bugs sur calcul sigma et erreur sur moyenne cmv 21/01/2003

File size: 9.8 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*w), E(j) = sum(y^2*w), L(j) = sum(w)
134 -> h(j) = H(j)/L(j) moyenne dans le bin
135 -> s(j) = sqrt(E(j)/L(j) - (H(j)/L(j))^2) dispersion dans le bin
136 -> e(j) = s(j)/sqrt(L(j)) erreur sur la moyenne dans le bin
137 spread=true: opt=0 : dispersion des donnees dans le bin = s(j)
138 spread=false: opt=1 : erreur sur la moyenne du bin = e(j)
139 \endverbatim
140*/
141void HProf::SetErrOpt(bool spread)
142{
143uint_2 opt = (spread) ? 0 : 1;
144if(opt!=Opt) {Opt=opt; Ok=false;}
145}
146
147/********* Methode *********/
148/*!
149 Pour mettre a jour l'histogramme de profil.
150 Il est important d'appeler cette methode si on veut
151 utiliser les methodes de la classe Histo qui ne sont
152 pas redefinies dans la classe HProf.
153 En effet, pour des raisons de precision la classe
154 HProf travaille avec des tableaux en double precision
155 et seulement au moment ou l'on a besoin de l'histogramme
156 ce dernier est rempli avec les valeurs demandees (moyenne
157 et dispersion/erreur sur la moyenne).
158*/
159void HProf::updatehisto() const
160{
161r_8 m,e2;
162if(mBins>0) for(int_4 i=0;i<mBins;i++) {
163 if(SumW[i]<=0.) {
164 m = e2 = 0.;
165 } else {
166 m = SumY[i]/SumW[i];
167 e2 = SumY2[i]/SumW[i] - m*m;
168 if(Opt) e2 /= SumW[i];
169 }
170 mData[i] = m;
171 mErr2[i] = e2;
172}
173Ok = true;
174// Attention, a cause de "WriteSelf const" updatehisto doit etre "const".
175// Comme on veut modifier Ok, on est oblige de faire cette entourloupe:
176HProf *buff = (HProf *) this;
177buff->Ok = true;
178}
179
180/********* Methode *********/
181/*!
182 Addition au contenu de l'histo pour abscisse x de la valeur y et poids w
183*/
184void HProf::Add(r_8 x, r_8 y, r_8 w)
185{
186 if(YMax>YMin && (y<YMin || YMax<y)) return;
187 int_4 numBin = FindBin(x);
188 if (numBin<0) mUnder += w;
189 else if (numBin>=mBins) mOver += w;
190 else {
191 Ok = false;
192 SumY[numBin] += y*w;
193 SumY2[numBin] += y*y*w;
194 SumW[numBin] += w;
195 nHist += w;
196 nEntries++;
197 }
198}
199
200/********* Methode *********/
201/*!
202 Addition au contenu de l'histo bin numBin de la valeur y poids w
203*/
204void HProf::AddBin(int_4 numBin, r_8 y, r_8 w)
205{
206 if(YMax>YMin && (y<YMin || YMax<y)) return;
207 if (numBin<0) mUnder += w;
208 else if (numBin>=mBins) mOver += w;
209 else {
210 Ok = false;
211 SumY[numBin] += y*w;
212 SumY2[numBin] += y*y*w;
213 SumW[numBin] += w;
214 nHist += w;
215 nEntries++;
216 }
217}
218
219/********* Methode *********/
220/*!
221 Operateur HProf H = H1
222*/
223HProf& HProf::operator = (const HProf& h)
224{
225if(this == &h) return *this;
226if( h.mBins > mBins ) Delete();
227Histo *hthis = (Histo *) this;
228*hthis = (Histo) h;
229if(!SumY) SumY = new r_8[mBins];
230if(!SumY2) SumY2 = new r_8[mBins];
231if(!SumW) SumW = new r_8[mBins];
232memcpy(SumY, h.SumY, mBins*sizeof(r_8));
233memcpy(SumY2, h.SumY2, mBins*sizeof(r_8));
234memcpy(SumW, h.SumW, mBins*sizeof(r_8));
235Ok = h.Ok;
236YMin = h.YMin;
237YMax = h.YMax;
238Opt = h.Opt;
239
240return *this;
241}
242
243/********* Methode *********/
244/*!
245 Operateur HProf H += H1
246
247 Attention dans cette addition il n'y a pas de gestion
248 des YMin et YMax. L'addition est faite meme si les limites
249 en Y de ``a'' sont differentes de celles de ``this''.
250*/
251HProf& HProf::operator += (const HProf& a)
252{
253if(mBins!=a.mBins) THROW(sizeMismatchErr);
254Histo *hthis = (Histo *) this;
255*hthis += (Histo) a;
256if(mBins>0) for(int_4 i=0;i<mBins;i++) {
257 SumY[i] += a.SumY[i];
258 SumY2[i] += a.SumY2[i];
259 SumW[i] += a.SumW[i];
260}
261updatehisto();
262
263return *this;
264}
265
266/********* Methode *********/
267/*!
268 Pour rebinner l'histogramme de profile sur nbinew bins
269*/
270void HProf::HRebin(int_4 nbinew)
271{
272 if( mBins <= 0 ) return; // createur par default
273 if( nbinew <= 0 ) return;
274
275 // memorisation de l'HProf original
276 HProf H(*this);
277
278 // Rebin de la partie Histo
279 int_4 binold = mBins;
280 Histo::HRebin(nbinew);
281
282 // Le nombre de bins est il plus grand ??
283 if( mBins > binold ) {
284 delete [] SumY; SumY = new r_8[nbinew]; memset(SumY, 0,mBins*sizeof(r_8));
285 delete [] SumY2; SumY2 = new r_8[nbinew]; memset(SumY2,0,mBins*sizeof(r_8));
286 delete [] SumW; SumW = new r_8[nbinew]; memset(SumW, 0,mBins*sizeof(r_8));
287 }
288
289 // Remplissage des parties propres au HPprof
290 for(int_4 i=0;i<mBins;i++) {
291 r_8 xmi = BinLowEdge(i);
292 r_8 xma = BinHighEdge(i);
293 int_4 imi = H.FindBin(xmi);
294 if( imi < 0 ) imi = 0;
295 int_4 ima = H.FindBin(xma);
296 if( ima >= H.mBins ) ima = H.mBins-1;
297 r_8 wY = 0., wY2 = 0., wW = 0.;
298 if( ima == imi ) {
299 wY = H.SumY[imi] * binWidth/H.binWidth;
300 wY2 = H.SumY2[imi] * binWidth/H.binWidth;
301 wW = H.SumW[imi] * binWidth/H.binWidth;
302 } else {
303 wY += H.SumY[imi] * (H.BinHighEdge(imi)-xmi)/H.binWidth;
304 wY += H.SumY[ima] * (xma -H.BinLowEdge(ima))/H.binWidth;
305 wY2 += H.SumY2[imi] * (H.BinHighEdge(imi)-xmi)/H.binWidth;
306 wY2 += H.SumY2[ima] * (xma -H.BinLowEdge(ima))/H.binWidth;
307 wW += H.SumW[imi] * (H.BinHighEdge(imi)-xmi)/H.binWidth;
308 wW += H.SumW[ima] * (xma -H.BinLowEdge(ima))/H.binWidth;
309 if(ima>imi+1) for(int_4 ii=imi+1;ii<ima;ii++)
310 {wY += H.SumY[ii]; wY2 += H.SumY2[ii]; wW += H.SumW[ii];}
311 }
312 SumY[i] += wY; SumY2[i] += wY2; SumW[i] += wW;
313 }
314 // On synchronise les tableaux Sum?? et l'Histogramme
315 updatehisto();
316}
317
318void HProf::Show(ostream & os) const
319{
320 UpdateHisto();
321 Histo::Show(os);
322}
323
324///////////////////////////////////////////////////////////
325// --------------------------------------------------------
326// Les objets delegues pour la gestion de persistance
327// --------------------------------------------------------
328///////////////////////////////////////////////////////////
329
330
331void ObjFileIO<HProf>::ReadSelf(PInPersist& is)
332{
333char strg[256];
334
335if(dobj==NULL) dobj=new HProf;
336 else dobj->Delete();
337
338// Lecture entete
339is.GetLine(strg,255);
340
341// Lecture des valeurs
342is.Get(dobj->mBins);
343is.Get(dobj->YMin);
344is.Get(dobj->YMax);
345is.Get(dobj->Opt);
346dobj->Ok = true;
347
348// Lecture des donnees propres a l'histogramme de profil.
349is.GetLine(strg,255);
350dobj->SumY = new r_8[dobj->mBins];
351dobj->SumY2 = new r_8[dobj->mBins];
352dobj->SumW = new r_8[dobj->mBins];
353is.Get(dobj->SumY, dobj->mBins);
354is.Get(dobj->SumY2, dobj->mBins);
355is.Get(dobj->SumW, dobj->mBins);
356
357// Lecture de l'histogramme
358is >> (Histo&)(*dobj);
359return;
360}
361
362void ObjFileIO<HProf>::WriteSelf(POutPersist& os) const
363{
364if (dobj == NULL) return;
365char strg[256];
366
367dobj->UpdateHisto();
368
369// Ecriture entete pour identifier facilement
370sprintf(strg,"HProf: YMin=%f YMax=%f Opt=%1d",dobj->YMin,dobj->YMax,dobj->Opt);
371os.PutLine(strg);
372
373// Ecriture des valeurs
374os.Put(dobj->mBins);
375os.Put(dobj->YMin);
376os.Put(dobj->YMax);
377os.Put(dobj->Opt);
378
379// Ecriture des donnees propres a l'histogramme de profil.
380sprintf(strg,"HProf: SumY SumY2 SumW");
381os.PutLine(strg);
382os.Put(dobj->SumY, dobj->mBins);
383os.Put(dobj->SumY2, dobj->mBins);
384os.Put(dobj->SumW, dobj->mBins);
385
386// Ecriture de l'histogramme
387// FIO_Histo fio_h((Histo&)*dobj);
388// fio_h.Write(os);
389os << (Histo&)(*dobj);
390
391return;
392}
393
394#ifdef __CXX_PRAGMA_TEMPLATES__
395#pragma define_template ObjFileIO<HProf>
396#endif
397
398#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
399template class ObjFileIO<HProf>;
400#endif
Note: See TracBrowser for help on using the repository browser.