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

Last change on this file since 1089 was 1089, checked in by ansari, 25 years ago

updatehisto formalisation cmv 25/7/00

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