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

Last change on this file since 2850 was 2615, checked in by cmv, 21 years ago

using namespace sophya enleve de machdefs.h, nouveau sopnamsp.h cmv 10/09/2004

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