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

Last change on this file since 2507 was 2507, checked in by ansari, 22 years ago

Remplacement THROW par throw et suppression END_CONSTRUCTOR - Reza 15/03/2004

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