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

Last change on this file since 3110 was 3057, checked in by cmv, 19 years ago
  • changement nom variables internes Histo...Histo2D
  • re-arrangement CreateOrResize et operator=
  • protection dans methodes (VMIN etc..) pour Histo 1d+2d vides

cmv 13/8/2006

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