#include "machdefs.h" #include #include #include #include #include #include #if defined(__KCC__) using std::string ; #endif #include "perrors.h" #include "nbtri.h" #include "generalfit.h" #include "generaldata.h" //================================================================ // 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); } CATCHALL { cout<<"GeneralFitData::GeneralFitData Impossible d'allouer l'espace"<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; } CATCHALL { THROW_SAME; } ENDTRY } ////////////////////////////////////////////////////////////////////// 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) return NULL; return gfit.DataResidus(true); } //++ GeneralFitData* GeneralFitData::FitFunction(GeneralFit& gfit) // // Retourne une classe contenant la function du fit ``gfit''. //-- { if(gfit.GetNVar()!=mNVar) return NULL; 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; i