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

Last change on this file since 3053 was 3053, checked in by cmv, 19 years ago

correction bug + addaptation pour ecriture fits cmv 12/8/2006

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