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

Last change on this file since 3678 was 3236, checked in by ansari, 18 years ago

Ajout namespace SOPHYA ds les fichiers .cc au lieu de include sopnamsp.h en presence de DECL_TEMP_SPEC , cmv+reza 27/04/2007

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