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

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

bug hprof vu par OP sumy+=y*w cmv 18/7/2002

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 y *= w;
192 SumY[numBin] += y;
193 SumY2[numBin] += y*y;
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 y *= w;
212 SumY[numBin] += y;
213 SumY2[numBin] += y*y;
214 SumW[numBin] += w;
215 nHist += w;
216 nEntries++;
217 }
218}
219
220/********* Methode *********/
221/*!
222 Operateur HProf H = H1
223*/
224HProf& HProf::operator = (const HProf& h)
225{
226if(this == &h) return *this;
227if( h.mBins > mBins ) Delete();
228Histo *hthis = (Histo *) this;
229*hthis = (Histo) h;
230if(!SumY) SumY = new r_8[mBins];
231if(!SumY2) SumY2 = new r_8[mBins];
232if(!SumW) SumW = new r_8[mBins];
233memcpy(SumY, h.SumY, mBins*sizeof(r_8));
234memcpy(SumY2, h.SumY2, mBins*sizeof(r_8));
235memcpy(SumW, h.SumW, mBins*sizeof(r_8));
236Ok = h.Ok;
237YMin = h.YMin;
238YMax = h.YMax;
239Opt = h.Opt;
240
241return *this;
242}
243
244/********* Methode *********/
245/*!
246 Operateur HProf H += H1
247
248 Attention dans cette addition il n'y a pas de gestion
249 des YMin et YMax. L'addition est faite meme si les limites
250 en Y de ``a'' sont differentes de celles de ``this''.
251*/
252HProf& HProf::operator += (const HProf& a)
253{
254if(mBins!=a.mBins) THROW(sizeMismatchErr);
255Histo *hthis = (Histo *) this;
256*hthis += (Histo) a;
257if(mBins>0) for(int_4 i=0;i<mBins;i++) {
258 SumY[i] += a.SumY[i];
259 SumY2[i] += a.SumY2[i];
260 SumW[i] += a.SumW[i];
261}
262updatehisto();
263
264return *this;
265}
266
267/********* Methode *********/
268/*!
269 Pour rebinner l'histogramme de profile sur nbinew bins
270*/
271void HProf::HRebin(int_4 nbinew)
272{
273 if( mBins <= 0 ) return; // createur par default
274 if( nbinew <= 0 ) return;
275
276 // memorisation de l'HProf original
277 HProf H(*this);
278
279 // Rebin de la partie Histo
280 int_4 binold = mBins;
281 Histo::HRebin(nbinew);
282
283 // Le nombre de bins est il plus grand ??
284 if( mBins > binold ) {
285 delete [] SumY; SumY = new r_8[nbinew]; memset(SumY, 0,mBins*sizeof(r_8));
286 delete [] SumY2; SumY2 = new r_8[nbinew]; memset(SumY2,0,mBins*sizeof(r_8));
287 delete [] SumW; SumW = new r_8[nbinew]; memset(SumW, 0,mBins*sizeof(r_8));
288 }
289
290 // Remplissage des parties propres au HPprof
291 for(int_4 i=0;i<mBins;i++) {
292 r_8 xmi = BinLowEdge(i);
293 r_8 xma = BinHighEdge(i);
294 int_4 imi = H.FindBin(xmi);
295 if( imi < 0 ) imi = 0;
296 int_4 ima = H.FindBin(xma);
297 if( ima >= H.mBins ) ima = H.mBins-1;
298 r_8 wY = 0., wY2 = 0., wW = 0.;
299 if( ima == imi ) {
300 wY = H.SumY[imi] * binWidth/H.binWidth;
301 wY2 = H.SumY2[imi] * binWidth/H.binWidth;
302 wW = H.SumW[imi] * binWidth/H.binWidth;
303 } else {
304 wY += H.SumY[imi] * (H.BinHighEdge(imi)-xmi)/H.binWidth;
305 wY += H.SumY[ima] * (xma -H.BinLowEdge(ima))/H.binWidth;
306 wY2 += H.SumY2[imi] * (H.BinHighEdge(imi)-xmi)/H.binWidth;
307 wY2 += H.SumY2[ima] * (xma -H.BinLowEdge(ima))/H.binWidth;
308 wW += H.SumW[imi] * (H.BinHighEdge(imi)-xmi)/H.binWidth;
309 wW += H.SumW[ima] * (xma -H.BinLowEdge(ima))/H.binWidth;
310 if(ima>imi+1) for(int_4 ii=imi+1;ii<ima;ii++)
311 {wY += H.SumY[ii]; wY2 += H.SumY2[ii]; wW += H.SumW[ii];}
312 }
313 SumY[i] += wY; SumY2[i] += wY2; SumW[i] += wW;
314 }
315 // On synchronise les tableaux Sum?? et l'Histogramme
316 updatehisto();
317}
318
319void HProf::Show(ostream & os) const
320{
321 UpdateHisto();
322 Histo::Show(os);
323}
324
325///////////////////////////////////////////////////////////
326// --------------------------------------------------------
327// Les objets delegues pour la gestion de persistance
328// --------------------------------------------------------
329///////////////////////////////////////////////////////////
330
331
332void ObjFileIO<HProf>::ReadSelf(PInPersist& is)
333{
334char strg[256];
335
336if(dobj==NULL) dobj=new HProf;
337 else dobj->Delete();
338
339// Lecture entete
340is.GetLine(strg,255);
341
342// Lecture des valeurs
343is.Get(dobj->mBins);
344is.Get(dobj->YMin);
345is.Get(dobj->YMax);
346is.Get(dobj->Opt);
347dobj->Ok = true;
348
349// Lecture des donnees propres a l'histogramme de profil.
350is.GetLine(strg,255);
351dobj->SumY = new r_8[dobj->mBins];
352dobj->SumY2 = new r_8[dobj->mBins];
353dobj->SumW = new r_8[dobj->mBins];
354is.Get(dobj->SumY, dobj->mBins);
355is.Get(dobj->SumY2, dobj->mBins);
356is.Get(dobj->SumW, dobj->mBins);
357
358// Lecture de l'histogramme
359is >> (Histo&)(*dobj);
360return;
361}
362
363void ObjFileIO<HProf>::WriteSelf(POutPersist& os) const
364{
365if (dobj == NULL) return;
366char strg[256];
367
368dobj->UpdateHisto();
369
370// Ecriture entete pour identifier facilement
371sprintf(strg,"HProf: YMin=%f YMax=%f Opt=%1d",dobj->YMin,dobj->YMax,dobj->Opt);
372os.PutLine(strg);
373
374// Ecriture des valeurs
375os.Put(dobj->mBins);
376os.Put(dobj->YMin);
377os.Put(dobj->YMax);
378os.Put(dobj->Opt);
379
380// Ecriture des donnees propres a l'histogramme de profil.
381sprintf(strg,"HProf: SumY SumY2 SumW");
382os.PutLine(strg);
383os.Put(dobj->SumY, dobj->mBins);
384os.Put(dobj->SumY2, dobj->mBins);
385os.Put(dobj->SumW, dobj->mBins);
386
387// Ecriture de l'histogramme
388// FIO_Histo fio_h((Histo&)*dobj);
389// fio_h.Write(os);
390os << (Histo&)(*dobj);
391
392return;
393}
394
395#ifdef __CXX_PRAGMA_TEMPLATES__
396#pragma define_template ObjFileIO<HProf>
397#endif
398
399#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
400template class ObjFileIO<HProf>;
401#endif
Note: See TracBrowser for help on using the repository browser.