#include "machdefs.h" #include #include #include #include #include #include #include #if defined(__KCC__) using std::string ; #endif #include "nbtri.h" #include "generalfit.h" #include "generaldata.h" #include "pexceptions.h" #include "objfio.h" using namespace PlanckDPC; //================================================================ // GeneralFitData //================================================================ //++ // Class GeneralFitData // Lib Outils++ // include generaldata.h // // Classe de stoquage de donnees a plusieurs variables avec erreur // sur l'ordonnee et sur les abscisses (options). //| {x0(i),Ex0(i), x1(i),Ex1(i), x2(i),Ex2(i) ... ; Y(i),EY(i)} //-- // Pour memoire, structure du rangement (n=mNVar): // - Valeur des abscisses mXP (idem pour mErrXP): // x0,x1,x2,...,xn x0,x1,x2,...,xn .... x0,x1,x2,....,xn // | 1er point | | 2sd point | .... | point mNData | // Donc abscisse J=[0,mNVar[ du point numero I=[0,mNData[: mXP[I*mNVar+J] // - Valeur de l'ordonnee mF (idem pour mErr et mOK): // f f f // | 1er point | | 2sd point | .... | point mNData | // Donc point numero I [0,mNData[ : mF[i] ////////////////////////////////////////////////////////////////////// //++ GeneralFitData::GeneralFitData(unsigned int nVar, unsigned int ndatalloc, uint_2 errx) // // Constructeur. ``nVar'' represente la dimension de l'espace des abscisses, // ``ndatalloc'' le nombre maximum de points et ``errx'' si non nul // indique que l'on fournit des erreurs sur les ``nVar'' variables en abscisse. //-- : mNVar(0), mNDataAlloc(0), mNData(0), mNDataGood(0), mOk_EXP(0) , mXP(NULL), mErrXP(NULL), mF(NULL), mErr(NULL), mOK(NULL) , BuffVar(NULL), BuffVarR4(NULL) { try { Alloc(nVar,ndatalloc,errx); } catch(PException e) { cout << "Exception : " << typeid(e).name() << " " << e.Msg() << endl; throw; } } //++ GeneralFitData::GeneralFitData(const GeneralFitData& data, bool clean) // // Constructeur par copie. Si ``clean'' est ``true'' // seules les donnees valides de ``data'' sont copiees. // Si ``clean'' est ``false'' (defaut) toutes les donnees // sont copiees et la taille totale de ``data'' est allouee // meme si elle est plus grande que la taille des donnees stoquees. //-- : mNVar(0), mNDataAlloc(0), mNData(0), mNDataGood(0), mOk_EXP(0) , mXP(NULL), mErrXP(NULL), mF(NULL), mErr(NULL), mOK(NULL) , BuffVar(NULL), BuffVarR4(NULL) { try { Alloc(data.mNVar,((clean)?data.mNDataGood:data.mNDataAlloc),((data.mErrXP)?1:0)); } catch(PException e) { cout << "Exception : " << typeid(e).name() << " " << e.Msg() << endl; throw; } // Remplissage if(data.mNData>0) { r_8* ret; for(int i=0;i0 && ndatalloc>0 ); Delete(); if(errx>=0) mOk_EXP = (uint_2) errx; mNVar = nVar; mNDataAlloc = ndatalloc; try { mXP = new r_8[nVar*ndatalloc]; if(mOk_EXP) mErrXP = new r_8[nVar*ndatalloc]; mF = new r_8[ndatalloc]; mErr = new r_8[ndatalloc]; mOK = new uint_2[ndatalloc]; BuffVar = new r_8[2*nVar+3]; BuffVarR4 = (r_4 *) BuffVar; } catch(PException e) { throw(AllocationError("GeneralFitData::Alloc allocation error\n")); } } ////////////////////////////////////////////////////////////////////// void GeneralFitData::Delete() { mNVar = mNDataAlloc = mNData = mNDataGood = 0; if( mXP != NULL ) {delete [] mXP; mXP = NULL;} if( mErrXP != NULL ) {delete [] mErrXP; mErrXP = NULL;} if( mF != NULL ) {delete [] mF; mF = NULL;} if( mErr != NULL ) {delete [] mErr; mErr = NULL;} if( mOK != NULL ) {delete [] mOK; mOK = NULL;} if( BuffVar != NULL ) {delete [] BuffVar; BuffVar = NULL; BuffVarR4 = NULL;} } ////////////////////////////////////////////////////////////////////// //++ void GeneralFitData::SetDataPtr(int ptr) // // Remise a zero de la structure pour nouveau remplissage (pas d'arg) // ou remise a la position ``ptr'' (si arg). Les donnees apres ``ptr'' // sont sur-ecrites. //-- { DBASSERT(ptr >= 0 && ptr < mNDataAlloc); mNData = ptr; mNDataGood = 0; if(ptr==0) return; for(int i=0;i= 0 && i < mNData); if( ! mOK[i] ) return; mOK[i] = 0; mNDataGood--; } //++ void GeneralFitData::KillData(int i1,int i2) // // Pour tuer une serie de points //-- { DBASSERT(i1 >= 0 && i1 < mNData); DBASSERT(i2 >= 0 && i2 < mNData); DBASSERT(i1 <= i2 ); for(int i=i1;i<=i2;i++) KillData(i); } ////////////////////////////////////////////////////////////////////// //++ void GeneralFitData::ValidData(int i) // // Pour re-valider le point numero i ([0,NData]). //-- { DBASSERT(i >= 0 && i < mNData); if( mOK[i] ) return; if( mErr[i]<=0. ) return; if(mOk_EXP) { for(int j=0;j= 0 && i1 < mNData); DBASSERT(i2 >= 0 && i2 < mNData); DBASSERT(i1 <= i2 ); for(int i=i1;i<=i2;i++) ValidData(i); } //++ void GeneralFitData::ValidData() // // Pour re-valider tous les points. //-- { for(int i=0;i=0 && i0 && mNData+nData<=mNDataAlloc); for(int i=0;i0 && mNData+nData<=mNDataAlloc); for(int i=0;i0 && mNData+nData<=mNDataAlloc); for(int i=0;i0 && mNData+nData<=mNDataAlloc); for(int i=0;i0 && mNData+nData<=mNDataAlloc); if(mOk_EXP && !errxp) {for(int j=0;j0 && mNData+nData<=mNDataAlloc); if(mOk_EXP && !errxp) {for(int j=0;j=mNData) i1 = mNData-1; if(i2>=mNData) i2 = mNData-1; if(i1>i2) i2 = mNData-1; cout<<"GeneralFitData::PrintData[NData=" <0); PrintData(0,mNData-1); } ////////////////////////////////////////////////////////////////////// //++ int GeneralFitData::GetMinMax(int var,int& imin,int& imax) // // Retourne les numeros des points de valeurs minimum et maximum // de la variable ``var'': //| La variable "var" est de la forme : var = AB avec //| B = 0 : variable d'ordonnee Y (valeur de A indifferente) //| B = 1 : erreur variable d'ordonnee EY (valeur de A indifferente) //| B = 2 : variable d'abscisse X numero A #[0,NVar[ //| B = 3 : erreur variable d'abscisse EX numero A #[0,NVar[ //| - Return NData checked si ok, -1 si probleme. //-- { imin = imax = -1; int ix = var/10; var = var%10; if(var<0 || var>3) return -1; if(var>=2 && (ix<0 || ix>=mNVar) ) return -1; double min, max; int ntest = 0; for(int i=0;imax) {max = v; imax = i;} ntest++; } return ntest; } //++ int GeneralFitData::GetMinMax(int var,double& min,double& max) // // Retourne le minimum et le maximum de la variable ``var'' // (cf commentaires GetMinMax). //-- { min = 1.; max = -1.; int imin,imax; int ntest = GetMinMax(var,imin,imax); if(ntest<=0) return ntest; int ix = var/10; var = var%10; if(var==0) { if(imin>=0) min = Val(imin); if(imax>=0) max = Val(imax); } else if(var==1) { if(imin>=0) min = EVal(imin); if(imax>=0) max = EVal(imax); } else if(var==2) { if(imin>=0) min = Absc(ix,imin); if(imax>=0) max = Absc(ix,imax); } else if(var==3) { if(imin>=0) min = EAbsc(ix,imin); if(imax>=0) max = EAbsc(ix,imax); } return ntest; } ////////////////////////////////////////////////////////////////////// //++ int GeneralFitData::GetMeanSigma(int var,double& mean,double& sigma,double min,double max) // // Retourne la moyenne et le sigma de la variable ``var'' // (cf commentaires GetMinMax). //| - Return : nombre de donnees utilisees, -1 si pb, -2 si sigma<0. //| - Seuls les points valides de valeur entre min,max sont utilises. //| Si min>=max pas de coupures sur les valeurs. //-- { mean = sigma = 0.; int ix = var/10; var = var%10; if(var<0 || var>3) return -1; if(var>=2 && (ix<0 || ix>=mNVar) ) return -1; int ntest = 0; for(int i=0;i0.) sigma = sqrt(sigma); } return ntest; } //++ int GeneralFitData::GetMoMeMed(int var,double& mode,double& mean,double& median, double min,double max,double coeff) // // Retourne le mode de la variable ``var'' // (cf commentaires GetMinMax). //| - Return : nombre de donnees utilisees, -1 si pb. //| - Seuls les points valides de valeur entre min,max sont utilises. //| Si min>=max pas de coupures sur les valeurs. //| - Le calcul du mode est approximee par la formule: //| Mode = Median - coeff*(Mean-Median) (def: coeff=0.8) //| - Kendall and Stuart donne coeff=2., mais coeff peut etre regle. //-- { mode = mean = median = 0.; if(mNData<=0) return -1; int ix = var/10; var = var%10; if(var<0 || var>3) return -1; if(var>=2 && (ix<0 || ix>=mNVar) ) return -1; double* buff = new double[mNData]; int ntest = 0; for(int i=0;i=mNVar) return -2.; if(mNDataGood<=0) return -4.; Vector x(mNDataGood); Vector y(mNDataGood); Vector ey2(1); if(ey) ey2.Realloc(mNDataGood,true); int ntest = 0; for(int i=0;i=mNDataGood) return -5.; x(ntest) = Absc(varx,i); y(ntest) = Val(i); if(ey) ey2(ntest) = EVal(i)*EVal(i); ntest++; } double res = 0.; if(ey) { Vector errcoef(1); res = pol.Fit(x,y,ey2,degre,errcoef); } else { res = pol.Fit(x,y,degre); } return res; } //++ double GeneralFitData::PolFit(int varx,int vary,Poly2& pol,int degre1,int degre2,bool ez) // // // Pour fiter un polynome de degre ``degre1''. On fite // Z=f(X,Y) ou Z=Val et X=Absc(varx) et Y=Absc(vary). // Si ``ey'' est ``true'' le fit prend en compte les erreurs // stoquees dans EVal, sinon fit sans erreurs. Si ``degre2'' // negatif, le fit determine un polynome en X,Y de degre // total ``degre`''. Si ``degre2'' positif ou nul, le fit // demande un fit de ``degre1'' pour la variable X et de degre // ``degre2'' sur la variable Y. Le resultat du fit est retourne // dans le polynome ``pol''. //| Return: //| - Res = le residu du fit //| - -1 si degre<0 //| - -2 si probleme sur numero de variable X //| - -3 si probleme sur numero de variable Y //| - -4 si NDataGood<0 //| - -5 si nombre de data trouves different de NDataGood //-- { if(degre1<0) return -1.; if(varx<0 || varx>=mNVar) return -2.; if(vary<0 || vary>=mNVar || vary==varx) return -3.; if(mNDataGood<=0) return -4.; Vector x(mNDataGood); Vector y(mNDataGood); Vector z(mNDataGood); Vector ez2(1); if(ez) ez2.Realloc(mNDataGood,true); int ntest = 0; for(int i=0;i=mNDataGood) return -5.; x(ntest) = Absc(varx,i); y(ntest) = Absc(vary,i); z(ntest) = Val(i); if(ez) ez2(ntest) = EVal(i)*EVal(i); ntest++; } double res = 0.; if(ez) { Vector errcoef(1); if(degre2>0) res = pol.Fit(x,y,z,ez2,degre1,degre2,errcoef); else res = pol.Fit(x,y,z,ez2,degre1,errcoef); } else { if(degre2>0) res = pol.Fit(x,y,z,degre1,degre2); else res = pol.Fit(x,y,z,degre1); } return res; } ////////////////////////////////////////////////////////////////////// //++ GeneralFitData GeneralFitData::FitResidus(GeneralFit& gfit) // // Retourne une classe contenant les residus du fit ``gfit''. //-- { if(gfit.GetNVar()!=mNVar) throw(SzMismatchError("GeneralFitData::FitResidus: size mismatch\n")); return gfit.DataResidus(true); } //++ GeneralFitData GeneralFitData::FitFunction(GeneralFit& gfit) // // Retourne une classe contenant la function du fit ``gfit''. //-- { if(gfit.GetNVar()!=mNVar) throw(SzMismatchError("GeneralFitData::FitFunction: size mismatch\n")); return gfit.DataFunction(true); } ////////////////////////////////////////////////////////////////////// //++ r_8* GeneralFitData::GetVec(int n, r_8* ret) const // // Retourne la donnee `n' dans le vecteur de double `ret'. //| Par defaut, ret=NULL et le buffer interne de la classe est retourne //| - Les donnees sont rangees dans l'ordre: //| x0,x1,x2,... ; ex0,ex1,ex2,... ; y ; ey ; ok(0/1) //| |<- NVar ->| + |<- NVar ->| + 1 + 1 + 1 //| Le vecteur ret a la taille 2*NVar+2+1 //-- { int i; if (ret == NULL) ret = BuffVar; for(i=0; i<2*mNVar+3; i++) ret[i] = 0.; if (n >= mNData) return(ret); memcpy(ret, mXP+n*mNVar, mNVar*sizeof(r_8)); if(mErrXP) memcpy(ret+mNVar, mErrXP+n*mNVar, mNVar*sizeof(r_8)); ret[2*mNVar] = mF[n]; ret[2*mNVar+1] = mErr[n]; ret[2*mNVar+2] = (double) mOK[n]; return(ret); } //++ r_4* GeneralFitData::GetVecR4(int n, r_4* ret) const // // Retourne la donnee `n' dans le vecteur de float `ret' // (meme commentaires que pour GetVec). //-- { if (ret == NULL) ret = BuffVarR4; double *buff = new double[2*mNVar+3]; GetVec(n,buff); for(int i=0;i<2*mNVar+3;i++) ret[i] = (float) buff[i]; delete [] buff; return ret; } ////////////////////////////////////////////////////////////////////// //++ string GeneralFitData::VarList_C(const char* nomx) const // // Retourne une chaine de caracteres avec la declaration des noms de // variables. si "nomx!=NULL" , des instructions d'affectation // a partir d'un tableau "nomx[i]" sont ajoutees. //-- { char buff[256]; string rets; int i; rets = "\ndouble"; for(i=0; iDelete(); // Lecture entete is.GetLine(strg, 255); // Ecriture des valeurs de definitions int_4 nvar,ndatalloc,ndata,ndatagood; is.Get(nvar); is.Get(ndatalloc); is.Get(ndata); is.Get(ndatagood); is.Get(dobj->mOk_EXP); if(nvar<=0 || ndatalloc<=0 || ndata<=0 || ndatagood<0 || ndatallocAlloc(nvar,ndatalloc,-1); dobj->mNData = ndata; dobj->mNDataGood = ndatagood; // Lecture des datas is.GetLine(strg, 255); int blen = dobj->mNVar + 3; if(dobj->mOk_EXP) blen += dobj->mNVar; double *buff = new double[blen]; for(int i=0;imNData;i++) { is.Get(buff, blen); int ip = i*dobj->mNVar; {for(int j=0;jmNVar;j++) dobj->mXP[ip+j] = buff[j];} dobj->mF[i] = buff[dobj->mNVar]; dobj->mErr[i] = buff[dobj->mNVar+1]; dobj->mOK[i] = (uint_2)(buff[dobj->mNVar+2]+0.01); if(dobj->mOk_EXP) {for(int j=0;jmNVar;j++) dobj->mErrXP[ip+j] = buff[dobj->mNVar+3+j];} } delete [] buff; return; } void FIO_GeneralFitData::WriteSelf(POutPersist& os) const { if (dobj == NULL) return; char strg[256]; // Ecriture entete pour identifier facilement sprintf(strg,"GeneralFitData: NVar=%d NDataAlloc=%d NData=%d NDataGood=%d Ok_EXP=%d" ,dobj->mNVar,dobj->mNDataAlloc,dobj->mNData,dobj->mNDataGood,dobj->mOk_EXP); os.PutLine(strg); // Ecriture des valeurs de definitions os.Put(dobj->mNVar); os.Put(dobj->mNDataAlloc); os.Put(dobj->mNData); os.Put(dobj->mNDataGood); os.Put(dobj->mOk_EXP); if(dobj->mNVar<=0 || dobj->mNDataAlloc<=0 || dobj->mNData<=0 || dobj->mNDataGood<0) return; // Ecriture des datas (on n'ecrit que mNData / mNDataAlloc) sprintf(strg ,"GeneralFitData: Abscisses, Ordonnee, Erreur Ordonnee, Flag, Erreur Abscisses"); os.PutLine(strg); int blen = dobj->mNVar + 3; if(dobj->mOk_EXP) blen += dobj->mNVar; double *buff = new double[blen]; for(int i=0;imNData;i++) { {for(int j=0;jmNVar;j++) buff[j] = dobj->Absc(j,i);} buff[dobj->mNVar] = dobj->Val(i); buff[dobj->mNVar+1] = dobj->EVal(i); buff[dobj->mNVar+2] = (double) dobj->IsValid(i); if(dobj->mOk_EXP) {for(int j=0;jmNVar;j++) buff[dobj->mNVar+3+j] = dobj->EAbsc(j,i);} os.Put(buff, blen); } delete [] buff; return; }