#include "machdefs.h" #include #include #include #include "hisprof.h" #include "perrors.h" /*! \class SOPHYA::HProf \ingroup HiStats Classe de profil d'histogrammes. */ /********* Methode *********/ /*! Constructeur par defaut. */ HProf::HProf() : Histo() , SumY(NULL), SumY2(NULL), SumW(NULL), Ok(false), YMin(1.), YMax(-1.), Opt(0) { END_CONSTRUCTOR } /********* Methode *********/ /*! Constructeur. Histogramme de profil de ``nBin'' bins entre ``xMin'' et ``xMax'' avec coupure d'acceptance sur y entre ``yMin'' et ``yMax''. Si yMin>=yMax alors pas de coupure d'acceptance sur y. Par defaut l'erreur du profil represente la dispersion dans le bin, SetErrOpt(1) permet de demander de calculer l'erreur sur la moyenne. */ HProf::HProf(r_8 xMin, r_8 xMax, int_4 nBin, r_8 yMin, r_8 yMax) : Histo(xMin,xMax,nBin) , SumY( (nBin>0) ? new r_8[nBin] : NULL) , SumY2((nBin>0) ? new r_8[nBin] : NULL) , SumW( (nBin>0) ? new r_8[nBin] : NULL) , Ok(false), YMin(yMin), YMax(yMax), Opt(0) { Histo::Errors(); Zero(); END_CONSTRUCTOR } /********* Methode *********/ /*! Constructeur. */ HProf::HProf(r_4 xMin, r_4 xMax, int_4 nBin, r_4 yMin, r_4 yMax) : Histo((r_8)xMin,(r_8)xMax,nBin) , SumY( (nBin>0) ? new r_8[nBin] : NULL) , SumY2((nBin>0) ? new r_8[nBin] : NULL) , SumW( (nBin>0) ? new r_8[nBin] : NULL) , Ok(false), YMin((r_8)yMin), YMax((r_8)yMax), Opt(0) { Histo::Errors(); Zero(); END_CONSTRUCTOR } /********* Methode *********/ /*! Constructeur par copie. */ HProf::HProf(const HProf& H) : Histo(H) , SumY((H.mBins>0) ? new r_8[H.mBins] : NULL) , SumY2((H.mBins>0) ? new r_8[H.mBins] : NULL) , SumW((H.mBins>0) ? new r_8[H.mBins] : NULL) , Ok(H.Ok), YMin(H.YMin), YMax(H.YMax), Opt(H.Opt) { if(mBins>0) { memcpy(SumY, H.SumY, mBins*sizeof(r_8)); memcpy(SumY2, H.SumY2, mBins*sizeof(r_8)); memcpy(SumW, H.SumW, mBins*sizeof(r_8)); } UpdateHisto(); END_CONSTRUCTOR } /********* Methode *********/ /*! Des-allocation */ void HProf::Delete() { if( SumY != NULL ) { delete[] SumY; SumY = NULL;} if( SumY2 != NULL ) { delete[] SumY2; SumY2 = NULL;} if( SumW != NULL ) { delete[] SumW; SumW = NULL;} Ok = false; } /********* Methode *********/ /*! Destructeur */ HProf::~HProf() { Delete(); } /********* Methode *********/ /*! Calcule la partie histogramme du profile si elle n'est pas a jour. */ void HProf::UpdateHisto(bool force) const { if(!Ok || force) updatehisto(); } /********* Methode *********/ /*! Remise a zero */ void HProf::Zero() { memset(SumY, 0, mBins*sizeof(r_8)); memset(SumY2, 0, mBins*sizeof(r_8)); memset(SumW, 0, mBins*sizeof(r_8)); Ok = false; Histo::Zero(); } /********* Methode *********/ /*! Pour changer l'option de calcul de l'erreur du profile. Si ``spread'' = true alors l'erreur represente la dispersion des donnees dans le bin, si = false elle represente l'erreur sur la moyenne du bin. \verbatim - Pour le bin (j): H(j) = sum(y), E(j) = sum(y^2), L(j) = sum(w) -> s(j) = sqrt(E(j)/L(j) - (H(j)/L(j))^2) dispersion -> e(j) = s(j)/sqrt(L(j)) erreur sur la moyenne spread=true: opt=0 : dispersion des donnees dans le bin = s(j) spread=false: opt=1 : erreur sur la moyenne du bin = e(j) \endverbatim */ void HProf::SetErrOpt(bool spread) { uint_2 opt = (spread) ? 0 : 1; if(opt!=Opt) {Opt=opt; Ok=false;} } /********* Methode *********/ /*! Pour mettre a jour l'histogramme de profil. Il est important d'appeler cette methode si on veut utiliser les methodes de la classe Histo qui ne sont pas redefinies dans la classe HProf. En effet, pour des raisons de precision la classe HProf travaille avec des tableaux en double precision et seulement au moment ou l'on a besoin de l'histogramme ce dernier est rempli avec les valeurs demandees (moyenne et dispersion/erreur sur la moyenne). */ void HProf::updatehisto() const { r_8 m,e2; if(mBins>0) for(int_4 i=0;iOk = true; } /********* Methode *********/ /*! Addition au contenu de l'histo pour abscisse x de la valeur y et poids w */ void HProf::Add(r_8 x, r_8 y, r_8 w) { if(YMax>YMin && (y=mBins) mOver += w; else { Ok = false; SumY[numBin] += y; SumY2[numBin] += y*y; SumW[numBin] += w; nHist += w; nEntries++; } } /********* Methode *********/ /*! Addition au contenu de l'histo bin numBin de la valeur y poids w */ void HProf::AddBin(int_4 numBin, r_8 y, r_8 w) { if(YMax>YMin && (y=mBins) mOver += w; else { Ok = false; SumY[numBin] += y; SumY2[numBin] += y*y; SumW[numBin] += w; nHist += w; nEntries++; } } /********* Methode *********/ /*! Operateur HProf H = H1 */ HProf& HProf::operator = (const HProf& h) { if(this == &h) return *this; if( h.mBins > mBins ) Delete(); Histo *hthis = (Histo *) this; *hthis = (Histo) h; if(!SumY) SumY = new r_8[mBins]; if(!SumY2) SumY2 = new r_8[mBins]; if(!SumW) SumW = new r_8[mBins]; memcpy(SumY, h.SumY, mBins*sizeof(r_8)); memcpy(SumY2, h.SumY2, mBins*sizeof(r_8)); memcpy(SumW, h.SumW, mBins*sizeof(r_8)); Ok = h.Ok; YMin = h.YMin; YMax = h.YMax; Opt = h.Opt; return *this; } /********* Methode *********/ /*! Operateur HProf H += H1 Attention dans cette addition il n'y a pas de gestion des YMin et YMax. L'addition est faite meme si les limites en Y de ``a'' sont differentes de celles de ``this''. */ HProf& HProf::operator += (const HProf& a) { if(mBins!=a.mBins) THROW(sizeMismatchErr); Histo *hthis = (Histo *) this; *hthis += (Histo) a; if(mBins>0) for(int_4 i=0;i binold ) { delete [] SumY; SumY = new r_8[nbinew]; memset(SumY, 0,mBins*sizeof(r_8)); delete [] SumY2; SumY2 = new r_8[nbinew]; memset(SumY2,0,mBins*sizeof(r_8)); delete [] SumW; SumW = new r_8[nbinew]; memset(SumW, 0,mBins*sizeof(r_8)); } // Remplissage des parties propres au HPprof for(int_4 i=0;i= H.mBins ) ima = H.mBins-1; r_8 wY = 0., wY2 = 0., wW = 0.; if( ima == imi ) { wY = H.SumY[imi] * binWidth/H.binWidth; wY2 = H.SumY2[imi] * binWidth/H.binWidth; wW = H.SumW[imi] * binWidth/H.binWidth; } else { wY += H.SumY[imi] * (H.BinHighEdge(imi)-xmi)/H.binWidth; wY += H.SumY[ima] * (xma -H.BinLowEdge(ima))/H.binWidth; wY2 += H.SumY2[imi] * (H.BinHighEdge(imi)-xmi)/H.binWidth; wY2 += H.SumY2[ima] * (xma -H.BinLowEdge(ima))/H.binWidth; wW += H.SumW[imi] * (H.BinHighEdge(imi)-xmi)/H.binWidth; wW += H.SumW[ima] * (xma -H.BinLowEdge(ima))/H.binWidth; if(ima>imi+1) for(int_4 ii=imi+1;ii::ReadSelf(PInPersist& is) { char strg[256]; if(dobj==NULL) dobj=new HProf; else dobj->Delete(); // Lecture entete is.GetLine(strg,255); // Lecture des valeurs is.Get(dobj->mBins); is.Get(dobj->YMin); is.Get(dobj->YMax); is.Get(dobj->Opt); dobj->Ok = true; // Lecture des donnees propres a l'histogramme de profil. is.GetLine(strg,255); dobj->SumY = new r_8[dobj->mBins]; dobj->SumY2 = new r_8[dobj->mBins]; dobj->SumW = new r_8[dobj->mBins]; is.Get(dobj->SumY, dobj->mBins); is.Get(dobj->SumY2, dobj->mBins); is.Get(dobj->SumW, dobj->mBins); // Lecture de l'histogramme is >> (Histo&)(*dobj); return; } void ObjFileIO::WriteSelf(POutPersist& os) const { if (dobj == NULL) return; char strg[256]; dobj->UpdateHisto(); // Ecriture entete pour identifier facilement sprintf(strg,"HProf: YMin=%f YMax=%f Opt=%1d",dobj->YMin,dobj->YMax,dobj->Opt); os.PutLine(strg); // Ecriture des valeurs os.Put(dobj->mBins); os.Put(dobj->YMin); os.Put(dobj->YMax); os.Put(dobj->Opt); // Ecriture des donnees propres a l'histogramme de profil. sprintf(strg,"HProf: SumY SumY2 SumW"); os.PutLine(strg); os.Put(dobj->SumY, dobj->mBins); os.Put(dobj->SumY2, dobj->mBins); os.Put(dobj->SumW, dobj->mBins); // Ecriture de l'histogramme // FIO_Histo fio_h((Histo&)*dobj); // fio_h.Write(os); os << (Histo&)(*dobj); return; } #ifdef __CXX_PRAGMA_TEMPLATES__ #pragma define_template ObjFileIO #endif #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES) template class ObjFileIO; #endif