#include #include #include #include #include "nbmath.h" #include "matxop.h" #include "nbinteg.h" #include "nbtri.h" #define ITMAX 256 #define EPS 3.0e-7 #define DEB_GausPiv 0 #define DEB_MeanSig 0 /* ++ Module Fonction mathematiques (C) Lib LibsUtil include nbmath.h Fonction mathematiques (C) -- */ void FitFun_MrqCof( double (*FunFit) (double ,double *,double *) ,int_4 type ,FLOATDOUBLE temps,FLOATDOUBLE mag,FLOATDOUBLE err ,int_4 *ndata,int_4 I1,int_4 I2 ,double *parcur,int_4 npar,int_4 *ind ,double *ATGA,double *BETA,double *ci2,int_4 deb); void nbgcf(double *gammcf,double a,double x,double *gln); void nbgser(double *gamser,double a,double x,double *gln); static int FITFUN_DPOL = -1; /*=========================================================================*/ /* Christophe 8/11/93 La Silla */ /* ++ double FitFun | ( double (*FunFit) (double ,double *,double *) ,int_4 type | ,FLOATDOUBLE temps,FLOATDOUBLE mag,FLOATDOUBLE err | ,int_4 *ndata,int_4 I1,int_4 I2 | ,double *par,double *epar,double *stepar | ,double *minpar,double *maxpar,int_4 npar | ,double stochi2,int_4 NstepMX,int_4 deb) Pour fitter une fonction parametrique sur des donnees. (Obsolete, utilisez GeneralFit en C++). -- */ /* ++ | Fonction de fit de la courbe FunFit sur les donnees | - Methode: fit des moindres carres dans le cas non lineaire | - Reference: Statistical and Computational Methods in Data Analysis | Siegmund Brandt, North-Holland 1970 p 204-206. | Introduction des limites pour la variation des parametres (cmv). | Increment des parametres selon la methode de Levenberg-Marquardt | (Numerical Receipes in C p 542) | - Remarques diverses: | Les points avec erreurs negatives ou nulles ne sont pas | utilises dans le fit. | Si le fit est hautement non lineaire, il faut donner de bonnes | approximations pour les parametres de depart. | Les limites minpar,maxpar sont des limites absolues mais possibles | - Memo personnel: | data = Ti, Fi ERRi i=0,n-1 | parametres Pj j=1,npar | fonction FunFit(t,P1,P2,..,Pnpar) | matrice A(n,4) = [Aij] = - [dg(T)/dPj] pour t=Ti | matrice G(n,n) = [Gij] = matrice diagonale 1/ERRj**2 | matrice C(n) = [Ci] = (Fi - FunFit(t,P1,P2,..,Pnpar)) | Pj(iteration n) = Pj(iteration n-1) + Zj -- */ /* ++ | ----------- | | ENTREES | | ----------- | - FunFit fonction a fiter | - type type des donnees a fiter (union temps,mag,err): | float=FITFUN_FLOAT / double=FITFUN_DOUBLE | - temps: union FLOATDOUBLE des tableaux des temps: | - mag: union FLOATDOUBLE des tableaux des magnitudes: | - err: union FLOATDOUBLE des tableaux des erreurs sur la magnitude | - ndata: nombre de donnees en entree, donc en c: | - I1: indice de depart pour le fit | - I2: indice de fin pour le fit | (si I2 <= I1 defaut: 1,*ndata) | - par: contient les valeurs d'initialisation des parametres | - stepar: si >0. on fit le parametre, sinon parametre fixe | - minpar: les valeurs minimum pouvant prendre les parametres | - maxpar: les valeurs minimum pouvant prendre les parametres | (si maxpar[i] <= minpar[i] pas de limitation sur le parametre i) | - stochi2:la valeur de variation du chi2 d'une iteration l'autre | en dessous de laquelle on arrete d'iterer: | (si <=0 le default est 0.01). | - npar: nombre de parametres du fit *par --> *(par+npar-1) | - NstepMX:nombre maximum d'iterations | - deb: niveau de print (0/1/2/3) -- */ /* ++ | ---------- | | SORTIES | | ---------- | - ndata: nombre de donnees utilisees dans le fit | - par: contient les valeurs fitees des parametres | - epar: contient les erreurs sur les valeurs fitees des parametres | - FitFun: la function elle meme retourne le Xi2 du fit si succes | -1. si l'inversion de la matrice des erreurs n'a pas ete possible | -2. si les parametres initiaux sont en desaccord avec les limites | -3. si le nombre de donnees est inferieur au nombre de parametres | -4. si le fit n'a pas converge (nstep>nNstepMX) -- */ /* ++ | -------------- | | MEMO PERSO | | -------------- | la structure FLOATDOUBLE: | union FloatDouble { | float *fx; | double *dx; | }; | - Si les tableaux temps,mag,emag sont des float alors | temps.fx doit contenir l'adresse du tableau des temps | (et idem pour mag.fx et err.fx) | - Si les tableaux temps,mag,emag sont des double alors | temps.dx doit contenir l'adresse du tableau des temps | (et idem pour mag.dx et err.dx) -- */ double FitFun( double (*FunFit) (double ,double *,double *) ,int_4 type ,FLOATDOUBLE temps,FLOATDOUBLE mag,FLOATDOUBLE err ,int_4 *ndata,int_4 I1,int_4 I2 ,double *par,double *epar,double *stepar ,double *minpar,double *maxpar,int_4 npar ,double stochi2,int_4 NstepMX,int_4 deb) { int_4 ind[NPAR_FITFUN], i, j, k, nstep, nparsave, nstop, nstopMX; double LimitC2,lambda,eps; double ATGA[NPAR_FITFUN][NPAR_FITFUN], COVAR[NPAR_FITFUN][NPAR_FITFUN] , ALPHA[NPAR_FITFUN][NPAR_FITFUN]; double DA[NPAR_FITFUN], BETA[NPAR_FITFUN]; double parcur[NPAR_FITFUN],partry[NPAR_FITFUN]; double ci2, ci20; /* initialisation */ if( type != FITFUN_FLOAT && type != FITFUN_DOUBLE) { printf("FitFun: Type de variable non prevue dans union FLOATDOUBLE %d\n",type); exit(-1); } if(npar>NPAR_FITFUN) { printf("FitFun: trop de parametres npar=%d > NPAR_FITFUN=%d\n",npar,NPAR_FITFUN); exit(-1); } nstopMX = 3; eps = 1.e-8; LimitC2=0.01; if ( stochi2 > 0. ) LimitC2 = stochi2; /* test des valeurs d'arret */ nstop = 0; /* fit du centre autour des valeurs estimees */ nparsave = npar; for (i=0;i 0. ) { ind[npar]=i; npar++; } } if ( I2 <= I1 ) { I1 = 0; I2 = *ndata-1;} if ( I2-I1+1 < npar ) { printf("le nombre de donnees %d est inferieur au nombre de parametres %d\n" ,I2-I1+1,npar); return(-3.); } for (j=0;j*(minpar+i) && (*(parcur+i)<=*(minpar+i) || *(parcur+i)>=*(maxpar+i))) { printf("Parametre %d initialise hors limites: %f # [%f,%f]\n" ,i,*(parcur+i),*(minpar+i),*(maxpar+i)); return(-2.); } } if ( deb >= 2 ) { printf("\n******************* ENTREE DANS FitFun "); printf("npar=%d LimitC2=%f\n",npar,LimitC2); printf("parametres"); for(i=0;i= 3 ) { printf(" ind"); for(i=0;i= 2 ) printf("Passage d'initialisation ci2= %e, lambda=%e\n",ci2,lambda); /* et maintenant les iterations */ nstep = 0; /************************ ITERATIONS *******************************************/ ITERATE: nstep++; if ( deb >= 2 ) printf("------------------------- pas %d\n",nstep); if(nstep > NstepMX) { printf("FitFun: Le fit n'a pas converge (trop d'iterations %d).\n",nstep); if (deb>0 ) { printf("== Parametres finals:"); for(k=0;k= 3 ) { printf("matrice 1/( At * G * A )\n"); for ( i=0; i= 2 ) { printf("Correction parametres proposee:"); for (i=0;i0 ) { printf("===============================================================\n"); printf("== ci2= %15.8e (%15.8e) ndata= %d nstep= %d\n",ci2,ci2/(*ndata-npar+1),*ndata,nstep); printf("== Parametres finals:"); for(k=0;k stepar[k] ) { partry[k] = parcur[k] + stepar[k] * DA[j] / fabs(DA[j]); } else { partry[k] = parcur[k] + DA[j]; } if(maxpar[k] > minpar[k] ) { if( partry[k] < minpar[k] ) { partry[k] = minpar[k]; if(deb>=2) printf("Parametre %3d limite au minimum %e\n",k,partry[k]); } if( partry[k] > maxpar[k] ) { partry[k] = maxpar[k]; if(deb>=2) printf("Parametre %3d limite au maximum %e\n",k,partry[k]); } } } if ( deb>=2) { printf("essai avec"); for(k=0;k=2) printf("Ci2: old=%e new=%e %e\n",ci20,ci2,ci2-ci20); /* test sur l'evolution du ci2 et la strategie a suivre */ if ( ci2 < ci20 ) { nstop = 0; for (j=0;j=2) { printf("lambda divided by 10. %e\n",lambda); printf("Nouveaux parametres"); for(k=0;k=nstopMX) lambda = 0.; ci2 = ci20; if(deb>=2) printf("Echec essai, lambda multiplied by 10. %e\n",lambda); } goto ITERATE; } /*=========================================================================*/ void FitFun_MrqCof(double (*FunFit) (double ,double *,double *) ,int_4 type ,FLOATDOUBLE temps,FLOATDOUBLE mag,FLOATDOUBLE err ,int_4 *ndata,int_4 I1,int_4 I2 ,double *parcur,int_4 npar,int_4 *ind ,double *ATGA,double *BETA,double *ci2,int_4 deb) { int_4 i, j, k; double deriv[NPAR_FITFUN], t, f, e, Gkk, Ck, funfit; for (i=0; i 0. ) { (*ndata)++; t = (type == FITFUN_FLOAT) ? *(temps.fx + k) : *(temps.dx + k); f = (type == FITFUN_FLOAT) ? *(mag.fx + k) : *(mag.dx + k); funfit = FunFit(t,parcur,deriv); Gkk = 1./e/e; Ck = f - funfit; *ci2 += Ck*Ck*Gkk; for ( j=0; j= 3 ) { printf("matrice ( At * G * A )\n"); for ( i=0; i=n][nca>=n] et B[?>=n][ncb>=m] | en sortie la matrice B contient le resultat X | Inv#0: inversion de la matrice A(n,n) | en entree matrice A | en sortie la matrice B contient le resultat 1/A | GausPiv: retourne le determinant (0. si non-inversible!) -- */ /* ++ |Remarque: |-matrice A[?>=n][nca>=n], | element Aij = "A'[i][j] de ss matrice A'[n][n]" = *(A+i*nca+j) | ou 0<=i=n][ncb>=m], | element Bij = "B'[i][j] de ss matrice B'[n][m]" = *(B+i*ncb+j) | ou 0<=i0 ) { printf("** Matrices de depart\n"); printf("Matrice A %d %d:\n",nca,n); for (i=0;i0 ) printf("-----> reduction ligne %d\n",k); amax=0.; /*recherche du plus grand coeff pour le pivot*/ j2=k; /* dans col k pour les lignes >= k */ for (j1=k;j10 ) printf("pivot sur la ligne %d max= %f\n",j2,amax); if ( j2 != k ) { /* echange des lignes k et j2 si necessaire*/ for (j=k;j0 ) { printf("Matrice A echange des lignes %d et %d :\n",k,j2); for (i=0;i0 ) printf("valeur du pivot %f\n",*(A+kk)); if ( *(A+kk) == 0. ) { /* printf("Matrice non-inversible: pivot %d nul\n",k); */ return(0.); } else { det *= *(A+kk); } for (i=k1;i0 ) { printf("Matrice A:\n"); for (i=0;i0 ) printf("Determinant de A= %e\n",det); /* ********************************************************** */ /* back substitution */ /* ********************************************************** */ nn=(n-1)*nca+(n-1); /* l'element (n,n) */ for (j=0;j= 0 ) { /* les lignes n-1 a 1 dans cet ordre*/ for(i1=1;i1<=i1max;i1++) { i=n-1-i1; /* ici i va de n-2 a 0 */ ij=i*ncb+j; ii=i*nca+i; i2=i+1; /* pour la ligne i on somme de i+1 a n */ for (l=i2;l0 ) { printf("-----> Matrice B resultat:\n"); for (i=0;i 1. || rho < -1. ) return(-1); /* sortie fit : [(x/SX)**2 - 2*RHO/(SX*SY)*x*y + (y/SY)**2]/(1-RHO**2) = 1 equation ellipse: A*x**2 + 2*B*x*y + C*y**2 = 1 */ sa = (1.-rho*rho); a = 1./sx/sx/sa; b = -rho/sx/sy/sa; c = 1./sy/sy/sa; /* cas des coniques degenerees (droites limites) */ if ( rho == 1. || rho == -1. ) return(-2); /* axes principaux OX OY pour : x = cos(ALPHA)*X - sin(APLHA)*Y (ALPHA = (ox,oX)) y = sin(ALPHA)*X + cos(APLHA)*Y soit ( A*cos**2 + C*sin**2 + 2*B*cos*sin )*X**2 + ( A*sin**2 + C*cos**2 - 2*B*cos*sin )*Y**2 + 2*( -A*cos*sin + C*cos*sin + B*(cos**2-sin**2) )*X*Y = (X/SA)**2 + (Y/SC)**2 = 1 et oX oY axes principaux pour : Tan ( 2*ALPHA ) = 2*B/(A-C) */ if ( a == c && rho == 0. ) { /* cas d'un cercle */ coscar = 0.5; sincar = coscar; cossin = coscar; alpha = 0.; } else { if ( a == c ) { /* cas SX=SY ellipse a +/-45 degres */ if ( rho > 0. ) { /* cas +45 degres */ alpha = Pi / 4.; } else { /* cas -45 degres */ alpha = -Pi / 4.; } } else { /* cas general */ alpha = atan(2.*b/(a-c)) /2.; } coscar = cos(alpha); sincar = sin(alpha); cossin = coscar*sincar; coscar *= coscar; sincar *= sincar; alpha *= 180./Pi; } sa = a*coscar+c*sincar+2.*b*cossin; sc = c*coscar+a*sincar-2.*b*cossin; sa = ( sa < 0. ) ? 1./sqrt(-sa) : 1./sqrt(sa); sc = ( sc < 0. ) ? 1./sqrt(-sc) : 1./sqrt(sc); if ( sa >= sc ) { *smax = sa; *axisrat = sc/sa; *tiltdeg = alpha; } else { *smax = sc; *axisrat = sa/sc; *tiltdeg = alpha+90.; if ( *tiltdeg > 90. ) *tiltdeg = *tiltdeg-180.; } return(0); } /*========================================================================*/ /* CMV 21/01/94 */ /* ++ int_4 gaparam - (float smax, float axisrat, float tiltdeg - , float *sxin, float *syin, float *rhoin) Pour transformer le sa,sc/sa,tiltdeg d'une gaussienne en sx,sy,rho Pour calculer les parametres d'une gaussienne -- */ /* ++ | - input : sa ]0,inf] ,axisrat ]0,1] ,tiltdeg ]-90,+90] | sa (longeur du grand axe), axisrat (rapport des axes ) | tiltdeg (angle entre le grand axe et l'axe ox en degre) | - output : sx ]0,inf] , sy ]0,inf] , rho ]-1,1[ | - Les fonctions sont: | exp[-0.5*{ (A/SA)**2 +(C/SC)**2 }] | exp[-0.5*{[(x/SX)**2-2*RHO/(SX*SY)*x*y+(y/SY)**2]/(1-RHO**2)}] | - Voir aussi la remarque de la fonction paramga. -- */ int_4 gaparam(float smax, float axisrat, float tiltdeg , float *sxin, float *syin, float *rhoin) { double sx,sy,rho,alpha,coscar,sincar,cossin,sa,sc,a,b,c; *sxin = 0.; *syin = 0.; *rhoin = 0.; /* cas des coniques degenerees ou erreurs dans les parametres*/ if ( smax <= 0. || axisrat <= 0. || axisrat > 1. ) return(-1); /* lecture des arguments */ sa = smax; sc = sa*axisrat; alpha = tiltdeg*Pi/180.; coscar = cos(alpha); sincar = sin(alpha); cossin = coscar*sincar; coscar *= coscar; sincar *= sincar; a = 1./(coscar/sa/sa + sincar/sc/sc); a = sqrt(a); /* = sqrt(1-ro**2)*sx */ b = 1./(sincar/sa/sa + coscar/sc/sc); b = sqrt(b); /* = sqrt(1-ro**2)*sy */ c = cossin*(-1./sa/sa + 1./sc/sc); rho = c*a*b; sx = a / sqrt(1.-rho*rho); sy = b / sqrt(1.-rho*rho); *sxin = sx; *syin = sy; *rhoin = rho; return(0); } /*===================================================================*/ /* ++ double nberfc(double x) Erreur fonction complementaire: -log10(erfc) Pratiquement pour avoir la proba que ]-inf,-x] U [x,+inf[ selon une loi gaussiene centree et normee il faut appeler nberfc(x/sqrt(2)) Le job tiens compte de la saturation machine pour x grand. La valeur est approximee au developpement limite de erfc ( see . Abramowitz p299 7.1.23 ) -- */ double nberfc(double x) { double v; if(x<0.) return(0.); if ( x < 10. ) { v = erfc(x); v = -log10(v); } else { v = 2.*x*x; v = 1./v - 3./(v*v) + 15./(v*v*v); v += LnPi/2. + log(x) + x*x; v /= Ln10; } return(v); } /*=========================================================================*/ /* ++ float probnb(float sci2,int_4 inddl,int_4 *ipass) Retourne -log10(p) ou p est la probabilte que le chi2 d'une fluctuation inddl points soit superieur a sci2. ipass est le type de calcul utilise. -- */ float probnb(float sci2,int_4 inddl,int_4 *ipass) { int_4 it; float nddl; double ci2,a1,a2,p,q,val,terme1,terme2,terme3,terme4,teradd,xnprim; *ipass = 0; val = 0.; nddl = inddl; ci2 = sci2; a1 = nddl/2.; a2 = ci2/2.; q = nbgammq(a1,a2); if(q>0. && q<1.) { val = -log10(q); /* moins le log10 de la proba que le chi2 soit > ci2 */ *ipass = 1; } else if ( q==1.) { p = nbgammp(a1,a2); val = p/Ln10; /* -log10(q) = -log(1-p)/Ln10 = -(p)/Ln10 = p/Ln10 */ *ipass = 2; } else { /* approximation de mimile */ xnprim = nddl / 2. - 1.; terme1 = nddl / 2. * Log2; /* 1/2**n */ terme2 = Hln2pi + (xnprim+0.5)*log(xnprim) - xnprim + 1./(12.*xnprim); terme2 /= Ln10; /* formule de stirling pour Gamma[nddl/2] */ terme3 = ci2/2. - xnprim*log(ci2); terme3 /= Ln10; /* exp(-ci2/2)*ci2**(n/2-1) */ terme4 = teradd = 1.; for ( it=1; it <= inddl-2; it +=2) { teradd *= ( (double) (nddl -1.) - (double) it ) / ci2; terme4 += teradd; if ( teradd < 1.e-4 ) break; } terme4 = -log10(2.*terme4); val = terme1 + terme2 + terme3 + terme4; *ipass = 3; } return ((float) val); } /*=========================================================================*/ /* ++ double nbgammln(double xx) Fonction log de la fonction Gamma -- */ double nbgammln(double xx) { double x,tmp,ser; static double cof[6]={76.18009173,-86.50532033,24.01409822, -1.231739516,0.120858003e-2,-0.536382e-5}; int_4 j; x=xx-1.0; tmp=x+5.5; tmp -= (x+0.5)*log(tmp); ser=1.0; for (j=0;j<=5;j++) { x += 1.0; ser += cof[j]/x; } return -tmp+log(2.50662827465*ser); } /*=========================================================================*/ /* ++ double nbgammq(double a,double x) Fonction GammaQ -- */ double nbgammq(double a,double x) { double gamser,gammcf,gln; if (x < 0.0 || a <= 0.0) { printf("Invalid arguments in routine NBGAMMQ (%f,%f)\n" ,a,x); exit(-1);} if (x < (a+1.0)) { nbgser(&gamser,a,x,&gln); return 1.0-gamser; } else { nbgcf(&gammcf,a,x,&gln); return gammcf; } } /*=========================================================================*/ /* ++ double nbgammp(double a,double x) Fonction GammaP -- */ double nbgammp(double a,double x) { double gamser,gammcf,gln; if (x < 0.0 || a <= 0.0) { printf("Invalid arguments in routine NBGAMMP (%f,%f)\n" ,a,x); exit(-1);} if (x < (a+1.0)) { nbgser(&gamser,a,x,&gln); return gamser; } else { nbgcf(&gammcf,a,x,&gln); return 1.0-gammcf; } } /*=========================================================================*/ void nbgcf(double *gammcf,double a,double x,double *gln) { int_4 n; double gold=0.0,g,fac=1.0,b1=1.0; double b0=0.0,anf,ana,an,a1,a0=1.0; *gln=nbgammln(a); a1=x; for (n=1;n<=ITMAX;n++) { an=(double) n; ana=an-a; a0=(a1+a0*ana)*fac; b0=(b1+b0*ana)*fac; anf=an*fac; a1=x*a0+anf*a1; b1=x*b0+anf*b1; if (a1) { fac=1.0/a1; g=b1*fac; if (fabs((g-gold)/g) < EPS) { *gammcf=exp(-x+a*log(x)-(*gln))*g; return; } gold=g; } } printf("a too large, ITMAX too small in routine NBGCF (%f,%f)\n",a,x); exit(-1); } /*=========================================================================*/ void nbgser(double *gamser,double a,double x,double *gln) { int_4 n; double sum,del,ap; *gln=nbgammln(a); if (x <= 0.0) { if (x < 0.0) { printf("x less than 0 in routine NBGSER (%f,%f)\n",a,x); exit(-1); } *gamser=0.0; return; } else { ap=a; del=sum=1.0/a; for (n=1;n<=ITMAX;n++) { ap += 1.0; del *= x/ap; sum += del; if (fabs(del) < fabs(sum)*EPS) { *gamser=sum*exp(-x+a*log(x)-(*gln)); return; } } printf("a too large, ITMAX too small in routine NBGSER (%f,%f)\n",a,x); exit(-1); return; } } /*==========================================================================*/ /* ++ void Set_Ihoq(int degre,int *mIhoqN,double *IhoqNX,double *IhoqNW) Set mIhoqN,IhoqNX,IhoqNW pour integration Gauss-Legendre -- */ void Set_Ihoq(int degre,int *mIhoqN,double *IhoqNX,double *IhoqNW) { switch (degre) { case 2: *mIhoqN = mIhoq2; IhoqNX = Ihoq2X; IhoqNW = Ihoq2W; break; case 3: *mIhoqN = mIhoq3; IhoqNX = Ihoq3X; IhoqNW = Ihoq3W; break; case 4: *mIhoqN = mIhoq4; IhoqNX = Ihoq4X; IhoqNW = Ihoq4W; break; case 5: *mIhoqN = mIhoq5; IhoqNX = Ihoq5X; IhoqNW = Ihoq5W; break; case 6: *mIhoqN = mIhoq6; IhoqNX = Ihoq6X; IhoqNW = Ihoq6W; break; case 7: *mIhoqN = mIhoq7; IhoqNX = Ihoq7X; IhoqNW = Ihoq7W; break; case 8: *mIhoqN = mIhoq8; IhoqNX = Ihoq8X; IhoqNW = Ihoq8W; break; case 9: *mIhoqN = mIhoq9; IhoqNX = Ihoq9X; IhoqNW = Ihoq9W; break; case 10: *mIhoqN = mIhoq10; IhoqNX = Ihoq10X; IhoqNW = Ihoq10W; break; case 16: *mIhoqN = mIhoq16; IhoqNX = Ihoq16X; IhoqNW = Ihoq16W; break; default: *mIhoqN = mIhoq8; IhoqNX = Ihoq8X; IhoqNW = Ihoq8W; break; } return; } /*==========================================================================*/ /* ++ int Get_Ihoq(int degre,double *ihoqnx,double *ihoqnw) Ecrit les positions et les poids pour l'integration de Gauss-Legendre dans les tableaux *ihoqnx,*ihoqnw. Retourne le nombre de points. Si *ihoqnx==NULL ou *ihoqnw==NULL retourne seulement le nombre de points (cad la taille minimale que doivent les tableaux *ihoqnx,*ihoqnw). -- */ int Get_Ihoq(int degre,double *ihoqnx,double *ihoqnw) { int mIhoqN, i; double *IhoqNX, *IhoqNW; switch (degre) { case 2: mIhoqN = mIhoq2; IhoqNX = Ihoq2X; IhoqNW = Ihoq2W; break; case 3: mIhoqN = mIhoq3; IhoqNX = Ihoq3X; IhoqNW = Ihoq3W; break; case 4: mIhoqN = mIhoq4; IhoqNX = Ihoq4X; IhoqNW = Ihoq4W; break; case 5: mIhoqN = mIhoq5; IhoqNX = Ihoq5X; IhoqNW = Ihoq5W; break; case 6: mIhoqN = mIhoq6; IhoqNX = Ihoq6X; IhoqNW = Ihoq6W; break; case 7: mIhoqN = mIhoq7; IhoqNX = Ihoq7X; IhoqNW = Ihoq7W; break; case 8: mIhoqN = mIhoq8; IhoqNX = Ihoq8X; IhoqNW = Ihoq8W; break; case 9: mIhoqN = mIhoq9; IhoqNX = Ihoq9X; IhoqNW = Ihoq9W; break; case 10: mIhoqN = mIhoq10; IhoqNX = Ihoq10X; IhoqNW = Ihoq10W; break; case 16: mIhoqN = mIhoq16; IhoqNX = Ihoq16X; IhoqNW = Ihoq16W; break; default: mIhoqN = mIhoq8; IhoqNX = Ihoq8X; IhoqNW = Ihoq8W; break; } if( ihoqnx!=NULL && ihoqnw!=NULL ) { for(i=0;i x1=-0.5 x2=0.5) | n = degre du developpement | OUTPUT: | x[] = valeur des abscisses ou l'on calcule (dim=n) | w[] = valeur des coefficients associes | REMARQUES: | - x et w doivent au moins etre dimensionner a n. | - l'integration est rigoureuse si sur l'intervalle d'integration | la fonction f(x) peut etre approximee par un polynome | de degre 2*m (monome le + haut x**(2*n-1) ) | - Voir la fonction Integ_Fun pour un calcul d'ordre 8 -- */ void nbgauleg(double x1,double x2,double *x,double *w,int n) { int m,j,i; double z1,z,xm,xl,pp,p3,p2,p1; m=(n+1)/2; xm=0.5*(x2+x1); xl=0.5*(x2-x1); for (i=1;i<=m;i++) { z=cos(3.141592654*(i-0.25)/(n+0.5)); do { p1=1.0; p2=0.0; for (j=1;j<=n;j++) { p3=p2; p2=p1; p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j; } pp=n*(z*p1-p2)/(z*z-1.0); z1=z; z=z1-p1/pp; } while (fabs(z-z1) > EPS_gauleg); x[i-1]=xm-xl*z; x[n-i]=xm+xl*z; w[i-1]=2.0*xl/((1.0-z*z)*pp*pp); w[n-i]=w[i-1]; } } #undef EPS_gauleg /*==========================================================================*/ /* ++ double Integ_Fun(double xmin,double xmax,double (*fonc)(double),int npas) Pour integrer la fonction fonc de xmin a xmax sur npas. On emploit une methode Higher-order-gaussienne d'ordre 8, ce qui fait un calcul equivalent de N*npas pas. -- */ double Integ_Fun(double xmin,double xmax,double (*fonc)(double),int npas) { int i,j; double dlim,sum,xc,xci; if( xmax <= xmin ) return(0.); if( npas <= 0 ) npas=1; sum = 0.; dlim = (xmax-xmin)/npas; for(i=0;i=0) { xpow = 1.; for(i=0;i<=FITFUN_DPOL;i++) { DgDpar[3+i] = xpow; f += Par[3+i]*xpow; xpow *= x; } } return (f); } /*==================================================================*/ /* Christophe 29/08/95 */ /* ++ double GaussI1DPol(double x,double *Par,double *DgDpar) Fonction de fit Gausienne integree+polynome. -- */ /* ++ | f(x) = par[0] / (sqrt(2*Pi)*par[2]) * exp[-0.5*( (x-par[1]) / par[2] )**2 ] | +par[3] + par[4]*x + .... + par[3+FITFUN_DPOL]*x**FITFUN_DPOL | FITFUN_DPOL peut etre definit avec la routine Set_FitFunDPol -- */ double GaussI1DPol(double x,double *Par,double *DgDpar) { double f,xc,xc2,e,xpow; int i; xc = (x-Par[1])/Par[2]; xc2 = xc*xc; e = exp(-0.5*xc2)/(S2Pi*Par[2]); f = Par[0]*e; DgDpar[0] = e; DgDpar[1] = xc / Par[2] *f; DgDpar[2] = (xc2-1.)/ Par[2] *f; if(FITFUN_DPOL>=0) { xpow = 1.; for(i=0;i<=FITFUN_DPOL;i++) { DgDpar[3+i] = xpow; f += Par[3+i]*xpow; xpow *= x; } } return (f); } /*====================================================================*/ /* Christophe 01/07/94 */ /* ++ double Polyn1D(double x,double *Par,double *DgDpar) Fonction de fit de polynome. -- */ /* ++ | f(x) = par[0] + par[1]*x + .... + par[FITFUN_DPOL]*x**FITFUN_DPOL | FITFUN_DPOL peut etre definit avec la routine Set_FitFunDPol -- */ double Polyn1D(double x,double *Par,double *DgDpar) { double f,xpow; int i,DPol; DPol = (FITFUN_DPOL<0) ? 0 : FITFUN_DPOL ; xpow = 1.; f = 0.; for(i=0;i<=DPol;i++) { DgDpar[i] = xpow; f += Par[i]*xpow; xpow *= x; } return (f); } /*=========================================================================*/ /* ++ double FitProp(double *x,double *y,double *ey,int *n,double *a1) Fit d'une proportion a1: y = a1 * x -- */ /* ++ | Input: | x = tableau des abscisses | y = tableau des ordonnees | ey = erreurs sur les y | n = nombre de donnees en entree | Output: | n = nombre de points utilises (point non utilise si ey<=0) | a1 coefficient | Return: | valeur du xi2 si fit reussi, | -1. si pas assez de points | -2. si determinant negatif -- */ double FitProp(double *x,double *y,double *ey,int *n,double *a1) { register int i,np; register double X2,XY,Y2,w; np=0; X2=XY=Y2=*a1=0.; for(i=0;i<*n;i++) { if(ey[i]<=0.) continue; np++; w = ey[i]*ey[i]; X2 += x[i]*x[i]/w; XY += x[i]*y[i]/w; Y2 += y[i]*y[i]/w; } *n = np; if(np<1) return(-1.); if(X2==0.) return(-2.); *a1 = XY/X2; w = Y2 + *a1**a1*X2 -2.**a1*XY; return(w); } /*=========================================================================*/ /* ++ double FitLin(double *x,double *y,double *ey,int *n,double *a0,double *a1) Fit d'une droite: y=a0+a1*x -- */ /* ++ | Input: | x = tableau des abscisses | y = tableau des ordonnees | ey = erreurs sur les y | n = nombre de donnees en entree | Output: | n = nombre de points utilises (point non utilise si ey<=0) | a0,a1 coefficients de la droite | Return: | valeur du xi2 si fit reussi, | -1. si pas assez de points | -2. si determinant negatif -- */ double FitLin(double *x,double *y,double *ey,int *n,double *a0,double *a1) { register int i,np; register double I,X,X2,Y,XY,Y2,w; np=0; Y2=I=X=X2=Y=XY=*a0=*a1=0.; for(i=0;i<*n;i++) { if(ey[i]<=0.) continue; np++; w = ey[i]*ey[i]; I += 1./w; X += x[i]/w; X2 += x[i]*x[i]/w; Y += y[i]/w; Y2 += y[i]*y[i]/w; XY += x[i]*y[i]/w; } *n = np; if(np<2) return(-1.); w = X*X-X2*I; if(w==0.) return(-2.); *a1 = (Y*X-XY*I)/w; *a0 = (X*XY-X2*Y)/w; w = Y2 + *a0**a0*I + *a1**a1*X2 + 2.*( - Y**a0 - *a1*XY + *a0**a1*X ); return(w); } /*=========================================================================*/ /* ++ double FitPar(double *x,double *y,double *ey,int *n,double *a0,double *a1,double *a2) Fit d'une parabole: y=a0+a1.x+a2.x^2 -- */ /* ++ | Input: | x = tableau des abscisses | y = tableau des ordonnees | ey = erreurs sur les y | n = nombre de donnees en entree | Output: | n = nombre de points utilises (point non utilise si ey<=0) | a0,a1 coefficients de la droite | Return: | valeur du xi2 si fit reussi, | -1. si pas assez de points | -2. si determinant negatif -- */ double FitPar(double *x,double *y,double *ey,int *n,double *a0,double *a1,double *a2) { register int i,np; register double I,X,X2,X3,X4,Y,Y2,XY,X2Y,w,x2; np=0; I=X=X2=X3=X4=Y=Y2=XY=X2Y=*a0=*a1=*a2=0.; for(i=0;i<*n;i++) { if(ey[i]<=0.) continue; np++; x2 = x[i]*x[i]; w = ey[i]*ey[i]; I += 1./w; X += x[i]/w; X2 += x2/w; X3 += x2*x[i]/w; X4 += x2*x2/w; Y += y[i]/w; Y2 += y[i]*y[i]/w; XY += x[i]*y[i]/w; X2Y += x2*y[i]/w; } *n = np; if(np<3) return(-1.); w = X2*(X2*X2-X3*X) -X*(X3*X2-X4*X) +I*(X3*X3-X4*X2); if(w==0.) return(-2.); *a2 = (Y*(X2*X2-X3*X) -XY*(X*X2-X3*I) +X2Y*(X*X-X2*I) )/w; *a1 = -(Y*(X3*X2-X4*X) -XY*(X2*X2-X4*I) +X2Y*(X2*X-X3*I) )/w; *a0 = (Y*(X3*X3-X4*X2) -XY*(X2*X3-X4*X) +X2Y*(X2*X2-X3*X))/w; w = Y2 + *a0**a0*I + *a1**a1*X2 + *a2**a2*X4 +2.*( -Y**a0 -*a1*XY -*a2*X2Y +*a0**a1*X +*a0**a2*X2+*a1**a2*X3 ); return(w); } /*=========================================================================*/ /* ++ double FitParLin - (double *xx,double *y,double *ey,int *n,double x0,int Deg_d - ,double *a0,double *a1,double *b1,double *b2) -- */ /* ++ | Fit d'une parabole: y=a0+b1*(x-x0)+b2*(x-x0)**2 | pour x>x0 | et d'une droite: y=a0+a1*(x-x0) pour x<=x0 | Input: | x = tableau des abscisses | y = tableau des ordonnees | ey = erreurs sur les y | n = nombre de donnees en entree | x0 = abscisse du point pivot (il n'est pas fitte) | Deg_d = degre du fit a droite de x0 (1 ou 2) | Output: | n = nombre de points utilises (point non utilise si ey<=0) | a0,a1 coefficients de la droite | a0,b1,b2 coefficients de la parabole -- */ /* ++ | Return: | valeur du xi2 si fit reussi, | -1. si pas assez de points | -2. si determinant negatif | Remarque: | Il faut evidemment au moins 2 points a gauche du pivot x0 | et 3 points a droite du pivot x0 | Matrices A * a = B : | | I_ X_g X_d X2_d | | a0 | | Y_ | | | X_g X2_g 0 0 | * | a1 | = | XY_g | | | X_d 0 X2_d X3_d | | b1 | | XY_d | | | X2_d 0 X3_d X4_d | | b2 | | X2Y_d | -- */ double FitParLin(double *xx,double *y,double *ey,int *n,double x0,int Deg_d ,double *a0,double *a1,double *b1,double *b2) { int i,np,npg,npd,nddl; double w,x,x2,A[4][4],B[4]; double Y2,I,Y,X_g,X2_g,XY_g,X_d,X2_d,X3_d,X4_d,XY_d,X2Y_d; if( Deg_d<1 || Deg_d>2 ) Deg_d=2; nddl = Deg_d + 2; *a0=*a1=*b1=*b2=0.; Y2=I=Y=X_g=X2_g=XY_g=X_d=X2_d=X3_d=X4_d=XY_d=X2Y_d=0.; np=npg=npd=0; for(i=0;i<*n;i++) { if(ey[i]<=0.) continue; np++; x = xx[i]-x0; x2 = x*x; w = ey[i]*ey[i]; I += 1./w; Y += y[i]/w; Y2 += y[i]*y[i]/w; if(x<=0.) { if(x<0.) npg++; X_g += x/w; X2_g += x2/w; XY_g += x*y[i]/w;; } else { npd++; X_d += x/w; X2_d += x2/w; X3_d += x2*x/w; X4_d += x2*x2/w; XY_d += x*y[i]/w;; X2Y_d += x2*y[i]/w;; } } *n = np; A[0][0] = I; A[1][1] = X2_g; A[3][3] = X4_d; A[0][1] = A[1][0] = X_g; A[0][2] = A[2][0] = X_d; A[3][2] = A[2][3] = X3_d; A[0][3] = A[3][0] = A[2][2] = X2_d; A[1][2] = A[2][1] = A[1][3] = A[3][1] = 0.; B[0] = Y; B[1] = XY_g; B[2] = XY_d; B[3] = X2Y_d; if( np<4 || npg < 1 || npd < 2 ) return(-1.); w = GausPiv(&A[0][0],4,nddl,B,1,1,0); if(w==0.) return(-2.); *a0 = B[0]; *a1 = B[1]; *b1 = B[2]; if(nddl==4) *b2 = B[3]; w = Y2 + *a0**a0*I + *a1**a1*X2_g + *b1**b1*X2_d + *b2**b2*X4_d + 2.*( - *a0*Y - *a1*XY_g + *a0**a1*X_g - *b1*XY_d - *b2*X2Y_d + *a0**b1*X_d + *a0**b2*X2_d + *b1**b2*X3_d ); return(w); } /*=========================================================================*/ /* ++ double FitPropClean(double *x,double *y,double *ey,int *n,double per_clean,double *a1) Fit de y(i) = a1*x(i) en deux passes: -- */ /* ++ | 1-/ fit avec tous les points | 2-/ fit ou on enleve les per_clean*n points les plus eloignes | Input: | x = tableau des abscisses | y = tableau des ordonnees | ey = erreurs sur les y | n = nombre de donnees en entree | per_clean = pourcentage des points a tuer pour la seconde passe -- */ /* ++ | Output: | n = nombre de points utilises (point non utilise si ey<=0) | a1 = coefficients de proportionalite | Return: | valeur du xi2 si fit reussi, | -1. si echec fit passe no 1 | -2. si echec fit passe no 2 | -3. si probleme malloc | -4. si probleme nombre de points a tuer -- */ double FitPropClean(double *x,double *y,double *ey,int *n,double per_clean,double *a1) { int npt,k,i,nclass; double *clas,aa1,c2,cut; *a1 =0.; /* 1ere passe */ npt = *n; c2 = FitProp(x,y,ey,&npt,&aa1); if(c2<0.) {*n = npt; return(-1.);} *a1 = aa1; /* printf("pass 1: %g*x c2=%g/%d\n",*a1,c2,npt); */ clas = (double*) malloc( *n * sizeof(double) ); if( clas == NULL ) {*n=npt; return(-3.);} /* elimination des mauvais points */ nclass = 0; for(i=0;i<*n;i++) { if(ey[i]<=0.) continue; c2 = (y[i]-aa1*x[i])/ey[i]; clas[nclass] = c2*c2; nclass++; } qsort(clas,(size_t) nclass,(size_t) sizeof(double),qSort_Dble); k = (int) ( (1. - per_clean ) * (double) nclass ); if(k<0) k=0; if(k>=nclass) k = nclass-1; cut = clas[k]; k = 0; for(i=0;i<*n;i++) { clas[i] = ey[i]; c2 = (y[i]-aa1*x[i])/ey[i]; c2 *= c2; if(ey[i]>0. && c2>cut) {clas[i] = -1.; k++;} } /* printf("nombre pt tues %d cut=%g\n",k,cut); */ /* 2sd passe */ npt = *n; c2 = FitProp(x,y,clas,&npt,&aa1); if(c2<0.) {*n = npt; free(clas); return(-2.);} *a1 = aa1; *n = npt; /* printf("pass 2: %g*x c2=%g/%d\n",*a1,c2,npt); */ free(clas); return(c2); } /*=========================================================================*/ /* ++ double FitLinClean - (double *x,double *y,double *ey,int *n - ,double per_clean,double *a0,double *a1) Fit de y(i) = a0 + a1*x(i) en deux passes: -- */ /* ++ | 1-/ fit avec tous les points | 2-/ fit ou on enleve les per_clean*n points les plus eloignes | Input: | x = tableau des abscisses | y = tableau des ordonnees | ey = erreurs sur les y | n = nombre de donnees en entree | per_clean = pourcentage des points a tuer pour la seconde passe | Output: | n = nombre de points utilises (point non utilise si ey<=0) | a0,a1 = coefficients de la droite -- */ /* ++ | Return: | valeur du xi2 si fit reussi, | -1. si echec fit passe no 1 | -2. si echec fit passe no 2 | -3. si probleme malloc | -4. si probleme nombre de points a tuer -- */ double FitLinClean(double *x,double *y,double *ey,int *n ,double per_clean,double *a0,double *a1) { int npt,k,i,nclass; double *clas,aa0,aa1,c2,cut; *a0 = *a1 =0.; /* 1ere passe */ npt = *n; c2 = FitLin(x,y,ey,&npt,&aa0,&aa1); if(c2<0.) {*n = npt; return(-1.);} *a0 = aa0; *a1 = aa1; /* printf("pass 1: %g + %g*x c2=%g/%d\n",*a0,*a1,c2,npt); */ clas = (double*) malloc( *n * sizeof(double) ); if( clas == NULL ) {*n=npt; return(-3.);} /* elimination des mauvais points */ nclass = 0; for(i=0;i<*n;i++) { if(ey[i]<=0.) continue; c2 = (y[i]-(aa0+aa1*x[i]))/ey[i]; clas[nclass] = c2*c2; nclass++; } qsort(clas,(size_t) nclass,(size_t) sizeof(double),qSort_Dble); k = (int) ( (1. - per_clean ) * (double) nclass ); if(k<0) k=0; if(k>=nclass) k = nclass-1; cut = clas[k]; k = 0; for(i=0;i<*n;i++) { clas[i] = ey[i]; c2 = (y[i]-(aa0+aa1*x[i]))/ey[i]; c2 *= c2; if(ey[i]>0. && c2>cut) {clas[i] = -1.; k++;} } /* printf("nombre pt tues %d cut=%g\n",k,cut); */ /* 2sd passe */ npt = *n; c2 = FitLin(x,y,clas,&npt,&aa0,&aa1); if(c2<0.) {*n = npt; free(clas); return(-2.);} *a0 = aa0; *a1 = aa1; *n = npt; /* printf("pass 2: %g + %g*x c2=%g/%d\n",*a0,*a1,c2,npt); */ free(clas); return(c2); } /*===================================================================*/ /* ++ double FitParClean - (double *x,double *y,double *ey,int *n - ,double per_clean,double *a0,double *a1,double *a2) Fit de y(i) = a0 + a1*x(i) + a2*x(i)^2 en deux passes: -- */ /* ++ | 1-/ fit avec tous les points | 2-/ fit ou on enleve les per_clean*n points les plus eloignes | Input: | x = tableau des abscisses | y = tableau des ordonnees | ey = erreurs sur les y | n = nombre de donnees en entree | per_clean = pourcentage des points a tuer pour la seconde passe | Output: | n = nombre de points utilises (point non utilise si ey<=0) | a0,a1,a2 = coefficients de la parabole | Return: | valeur du xi2 si fit reussi, | -1. si echec fit passe no 1 | -2. si echec fit passe no 2 | -3. si probleme malloc | -4. si probleme nombre de points a tuer -- */ double FitParClean(double *x,double *y,double *ey,int *n ,double per_clean,double *a0,double *a1,double *a2) { int npt,k,i,nclass; double *clas,aa0,aa1,aa2,c2,cut; *a0 = *a1 = *a2 =0.; /* 1ere passe */ npt = *n; c2 = FitPar(x,y,ey,&npt,&aa0,&aa1,&aa2); if(c2<0.) {*n = npt; return(-1.);} *a0 = aa0; *a1 = aa1; *a2 = aa2; /* printf("pass 1: %g + %g*x + %g*x**2 c2=%g/%d\n",*a0,*a1,*a2,c2,npt); */ clas = (double*) malloc( *n * sizeof(double) ); if( clas == NULL ) {*n=npt; return(-3.);} /* elimination des mauvais points */ nclass = 0; for(i=0;i<*n;i++) { if(ey[i]<=0.) continue; c2 = (y[i]-(aa0+aa1*x[i]+aa2*x[i]*x[i]))/ey[i]; clas[nclass] = c2*c2; nclass++; } qsort(clas,(size_t) nclass,(size_t) sizeof(double),qSort_Dble); k = (int) ( (1. - per_clean ) * (double) nclass ); if(k<0) k=0; if(k>=nclass) k = nclass-1; cut = clas[k]; k = 0; for(i=0;i<*n;i++) { clas[i] = ey[i]; c2 = (y[i]-(aa0+aa1*x[i]+aa2*x[i]*x[i]))/ey[i]; c2 *= c2; if(ey[i]>0. && c2>cut) {clas[i] = -1.; k++;} } /* printf("nombre pt tues %d cut=%g\n",k,cut); */ /* 2sd passe */ npt = *n; c2 = FitPar(x,y,clas,&npt,&aa0,&aa1,&aa2); if(c2<0.) {*n = npt; free(clas); return(-2.);} *a0 = aa0; *a1 = aa1; *a2 = aa2; *n = npt; /* printf("pass 2: %g + %g*x + %g*x**2 c2=%g/%d\n",*a0,*a1,*a2,c2,npt); */ free(clas); return(c2); } /*===========================================================*/ /* ++ float interpole(float m,int n,float *t1,float *t2) Interpolation lineaire y=f(x): -- */ /* ++ | t1[n] = tableau des x | t2[n] = tableau des y | m = valeur ou on interpole | RETURN: f(m) -- */ float interpole(float m,int n,float *t1,float *t2) { int i,n1; float r; if ( n == 1 ) return ( t2[0] ); n1=n-1; if ( m < t1[0] ) m=t1[0]; if ( m > t1[n1] ) m=t1[n1]; for(i=0;i 0. && fabs(v-*mean) < scut ) { n++; m += v; s2 += v * v; } } if ( n >= 2 ) { *mean = m / n; *sigma = sqrt( s2 / n - m/n * m/n ); } else { *mean = *sigma = 0.; *ndata=n; return(-1); } if ( deb>0 ) printf("MeanSig: pass=%d mean=%f sigma=%f n=%d\n" ,pass,*mean,*sigma,n); } *ndata=n; return(0); } /*=========================================================================*/ /* ++ int Most_Probable - ( float *val, int nval, float binin, int nmoy - , float low, float high, float *most, int deb) Pour calculer la valeur la plus probable par maximum d'histogramme. -- */ /* ++ | INPUT: | - val= pointeur sur un tableau de valeurs (float). | - nval= nombre de valeurs a traiter. | - binin= taille du bin. | - nmoy= la valeur retournee est la moyenne de +/- nmoy bins | autour du max de l'histo. | - low, high= les valeurs permises mini et maxi des valeurs | (si low>high calcul automatique). | - deb= niveau de debug. | OUTPUT: | - most = valeur la plus probable. | RETURN CODE: | -1 : nval <=0 | -2 : bin <=0 | -3 : low>=high apres cadrage automatique | -4 : nombre de valeurs remplies nul au niveau de la 1ere passe | -51 : pas trouve de maximum 1ere passe | -52 : pas trouve de maximum 2sd passe -- */ int Most_Probable( float *val, int nval, float binin, int nmoy , float low, float high, float *most, int deb) { int histo[503],i,nbin,n,ib,ibmax,vmax,pass; float bin,xmax=0.; double moy,sum; if(deb>1) printf("Most_Probable: nval=%d binin=%f nmoy=%d low,high=%f %f\n" ,nval,binin,nmoy,low,high); if (nval<=0) return(-1); if (binin<=0.) return(-2); nmoy = (nmoy<0) ? 0 : nmoy; if(low>= high) { low = GRAND; high = -low; for(i=0;ihigh) high=val[i]; if(val[i]1) printf("nmoy=%d low,high=%f %f\n",nmoy,low,high); if(low>= high) return(-3); /* premiere passe "nbin" bins entre low et high, nbin=min(high-low)/bin+1,501) */ /* seconde passe "nbin" autour du maxi 1ere passe, nbin=min(high-low)/bin,501) */ for ( pass=1;pass<=2;pass++) { bin=binin; nbin = (int) ( (high-low)/bin ) + 1; if(nbin>501) { nbin = 501; if(pass!=1){ low = xmax - 250*binin - binin/2.; high = xmax + 250*binin + binin/2.; } } /* re-scaling du bin pour etre sur */ bin=(high-low)/nbin; if(deb>1) printf("pass=%2d low,high=%f %f bin=%f nbin=%d\n" ,pass,low,high,bin,nbin); for(i=0;i=high || val[i]= nbin ) continue; histo[ib]++; n++; } if(n<=0) return (-4); vmax = -1; ibmax= -1; if(n<=0) return (-4); for(i=0;i1) printf("bin du maximum %5d (%d) abscisse=%f\n",ibmax,vmax,xmax); if(deb>3) { printf("histogramme:\n"); for (i= ibmax-25;i<=ibmax+25;i++) { if (i<0) continue; if (i>=nbin) break; printf(" %5d",histo[i]); if(i%10==9) printf("\n"); } printf("\n"); } } sum = moy =0.; n=0; for (i= -nmoy;i<=nmoy;i++) { if (ibmax-i>=0 && ibmax+i0) printf("Most_probable: most=%f (avec %d points)\n",*most,n); return(0); } /*============================================================*/ /* Christophe 27/01/95 */ /* ++ float Ajust_GaFn | (int Ns,float *fcfr | ,float *haut,float *ehaut,float *mean,float *emean | ,float *sigma,float *esigma,float *fond,float *efond | ,int fixfond,int NBIN_RESOL | ,float perc_net,float frac_sgb,float dyn_sgb,int deb) Fonction de fit gaussienne + fond (1D) du tableau fcfr avec reglage des parametres d'entree. -- */ /* ++ | ATTENTION: le tableau fcfr est modifie !!! | --------- | ENTREES: | Ns = nombre d'entrees dans fcfr | fcfr = tableau des valeurs a fitter | fond = valeur a donner au fond si fixfond = 1 | fixfond = 1 fond fixe dans le fit a la valeur fond | = 2 fond fixe dans le fit a une valeur | calculee automatiquement sur | les bords de l'histogramme | > 2 fond fixe a zero (<=> 1 + fond=0) | <= 0 fond libre dans le fit | NBIN_RESOL = nombre maxi de bins pour l'histo de fit | de la resolution | perc_net = pourcentage de donnees a nettoyer pour | calculer mean,sigma de la 1ere passe | frac_sgb = le bin de fit sera sigma*fracsgb | ou sigma est calcule en premiere passe | dyn_sgb = limites de l'histo de fit | xmin=mean-dyn_sgb*sigma , xmax=mean+dyn_sgb*sigma | deb = niveau de debug -- */ /* ++ | SORTIES: | haut = valeur de la hauteur | ehaut = erreur sur la valeur de la hauteur | mean = valeur moyenne du decalage | emean = erreur sur la valeur moyenne du decalage | sigma = valeur de la resolution | esigma = erreur sur la valeur de la resolution | fond = valeur du fond | efond = erreur sur la valeur du fond | return code = chi2 du fit (<0 si Pb) -- */ float Ajust_GaFn(int Ns,float *fcfr ,float *haut,float *ehaut,float *mean,float *emean ,float *sigma,float *esigma,float *fond,float *efond ,int fixfond,int NBIN_RESOL ,float perc_net,float frac_sgb,float dyn_sgb,int deb) { int_4 i,j,i1,i2,nbin,ibin,entries; float c2,xmin,xmax,binw,ymax; float *y,*ey,*x; double m,s; FLOATDOUBLE X,Y,EY; double (*Fun) (double ,double *,double *); int_4 npar,n; double par[4], epar[4],minpar[4],maxpar[4],stepar[4],stochi2; fixfond = ( fixfond <= 0 ) ? 0 : fixfond; perc_net = ( perc_net >= 1. || perc_net < 0. ) ? 0.1 : perc_net; NBIN_RESOL = ( NBIN_RESOL <= 0 ) ? 50 : NBIN_RESOL; frac_sgb = ( frac_sgb <= 0. ) ? 0.5 : frac_sgb; dyn_sgb = ( dyn_sgb <= 0. ) ? 5.0 : dyn_sgb; x = y = ey = NULL; x = (float *) calloc(NBIN_RESOL+2,sizeof(float)); y = (float *) calloc(NBIN_RESOL+2,sizeof(float)); ey = (float *) calloc(NBIN_RESOL+2,sizeof(float)); if ( x==NULL || y==NULL || ey==NULL ) {c2 = -100.; goto END;} if(deb>0) printf("Ajust_GaFn[%d] perc_net=%f nbin=%d frac_sgb=%f dyn_sgb=%f\n" ,Ns,perc_net,NBIN_RESOL,frac_sgb,dyn_sgb); /* on vire perc_net % des points a gauche et a droite de la distribution */ qsort(fcfr,(size_t) Ns,(size_t) sizeof(float),qSort_Float); i = perc_net * Ns; if(perc_net>0. && i==0) i=1; i1 = i; i2 = Ns-1-i; if(deb>1) { printf(" df/f="); for(j=0;j<10;j++) printf("%8.2f ",fcfr[j]); printf("\n"); printf("selection de %d (%f) a %d (%f)\n",i1,fcfr[i1],i2,fcfr[i2]); } if(i2<=i1) { c2= -101.; goto END;} /* calcul mean et sigma 1ere passe */ m = s = 0.; j = 0; for(i=i1;i<=i2;i++) {m += fcfr[i]; s += fcfr[i]*fcfr[i]; j++;} m /= j; s = sqrt(s/j - m*m); *mean = m; *sigma = s; if(deb>1) printf("premiere passe: mean=%f sigma=%f\n",*mean,*sigma); /* remplissage histo a +/- dyn_sgb * sigma */ xmin = *mean - dyn_sgb* *sigma; xmax = *mean + dyn_sgb* *sigma; if(xmin>=xmax) {c2 = -102.; goto END;} binw = *sigma * frac_sgb; nbin = (xmax-xmin)/binw; if(nbin<6) nbin=6; if(nbin>NBIN_RESOL) nbin=NBIN_RESOL; binw = (xmax-xmin)/nbin; for(i=0;i1) { printf("histo[%d] lim=[%f,%f] bw=%f x=\n" ,nbin,xmin,xmax,binw); for(j=0;j=0 && ibin1.)? sqrt((double) y[i]) : 1.; if(y[i]>ymax) ymax=y[i];} if(deb>1) { printf("histo (entries=%d) ymax=%f y=\n",entries,ymax); for(j=0;j2) { printf("histo ey=\n"); for(j=0;j2) *fond = 0.; } *haut = ymax - *fond; /* fit gaussienne + fond constant */ Fun = Gauss1DPolF ; Set_FitFunDPol(0); X.fx = x; Y.fx = y; EY.fx = ey; par[0] = *haut; par[1] = *mean; par[2] = *sigma; par[3] = *fond; stepar[0] = par[0]/10.; stepar[1] = par[2]/5.; stepar[2] = par[2]/10.; stepar[3] = 0.5; if(fixfond) { stepar[3] = 0.; epar[3]=0.;} for(i=0;i<4;i++) {minpar[i] = 1.; maxpar[i] = -1.;} minpar[2] = 0.00001; maxpar[2] = 9999.; npar = 4; stochi2 = 0.0001; n = nbin; j = (deb>2)? 1:0; c2 = FitFun(Fun,FITFUN_FLOAT,X,Y,EY,&n,0,0,par ,epar,stepar,minpar,maxpar,npar,stochi2,60,j); END: if( c2 > 0. ) { *haut = par[0]; *mean = par[1]; *sigma = par[2]; *fond = par[3]; *ehaut = epar[0]; *emean = epar[1]; *esigma = epar[2]; *efond = epar[3]; } else { *ehaut = *emean = *esigma = *efond = 0.; } if(x !=NULL) free(x); if(y !=NULL) free(y); if(ey!=NULL) free(ey); return(c2); } /*==========================================================*/ /* Christophe 27/03/95 */ /* ++ float HFit_GaFn - (int Ns,float *fcfr - ,float *haut,float *ehaut,float *mean,float *emean - ,float *sigma,float *esigma,float *fond,float *efond - ,int fixfond,int nbin,float xmin,float xmax,int deb) Fonction de fit gaussienne + fond (1D) du tableau fcfr dans un histo de "nbin" bins de "xmin a xmax" -- */ /* ++ | ENTREES: | Ns = nombre d'entrees dans fcfr | fcfr = tableau des valeurs a fitter | mean = valeur de depart pour la moyenne | sigma = valeur de depart pour le sigma | fond = valeur de depart pour le fond | fixfond > 0 fond fixe dans le fit a la valeur fond | <= 0 fond libre dans le fit | nbin = nombre de bins pour l'histo de fit | xmin = valeur inferieure de l'histo | xmax = valeur superieure de l'histo | deb = niveau de debug -- */ /* ++ | SORTIES: | haut = valeur de la hauteur | ehaut = erreur sur la valeur de la hauteur | mean = valeur moyenne du decalage | emean = erreur sur la valeur moyenne du decalage | sigma = valeur de la resolution | esigma = erreur sur la valeur de la resolution | fond = valeur du fond | efond = erreur sur la valeur du fond | return code = chi2 du fit (<0 si Pb) -- */ float HFit_GaFn(int Ns,float *fcfr ,float *haut,float *ehaut,float *mean,float *emean ,float *sigma,float *esigma,float *fond,float *efond ,int fixfond,int nbin,float xmin,float xmax,int deb) { int_4 i,j,ibin,entries; float c2,binw,ymax; float *y,*ey,*x; FLOATDOUBLE X,Y,EY; double (*Fun) (double ,double *,double *); int_4 npar,n; double par[4], epar[4],minpar[4],maxpar[4],stepar[4],stochi2; if(xmax<=xmin) return(-102); fixfond = ( fixfond <= 0 ) ? 0 : fixfond; nbin = ( nbin <= 0 ) ? 50 : nbin; x = y = ey = NULL; x = (float *) calloc(nbin+2,sizeof(float)); y = (float *) calloc(nbin+2,sizeof(float)); ey = (float *) calloc(nbin+2,sizeof(float)); if ( x==NULL || y==NULL || ey==NULL ) {c2 = -100.; goto END;} if(deb>0) printf("HFit_GaFn[%d pts] nbin=%d de %g a %g\n" ,Ns,nbin,xmin,xmax); /* remplissage histo */ binw = (xmax-xmin)/nbin; for(i=0;i1) { printf("histo[%d] lim=[%f,%f] bw=%f x=\n",nbin,xmin,xmax,binw); for(j=0;j=0 && ibin1.)? sqrt((double) y[i]) : 1.; if(y[i]>ymax) ymax=y[i];} if(deb>1) { printf("histo (entries=%d) ymax=%f y=\n",entries,ymax); for(j=0;j2) { printf("histo ey=\n"); for(j=0;j2)? 1:0; c2 = FitFun(Fun,FITFUN_FLOAT,X,Y,EY,&n,0,0,par ,epar,stepar,minpar,maxpar,npar,stochi2,60,j); END: if( c2 > 0. ) { *haut = par[0]; *mean = par[1]; *sigma = par[2]; *fond = par[3]; *ehaut = epar[0]; *emean = epar[1]; *esigma = epar[2]; *efond = epar[3]; } else { *ehaut = *emean = *esigma = *efond = 0.; } if(x !=NULL) free(x); if(y !=NULL) free(y); if(ey!=NULL) free(ey); return(c2); } /*==============================================================*/ /* Christophe 15/02/95 */ /* ++ int Ajust_MnSg - (int Ns,float *fcfr - ,float *mean,float *emean,float *sigma,float *esigma - ,float perc_net,float n_sigma,int deb) Calcul mean sigma tronques du tableau fcfr. -- */ /* ++ | ATTENTION: le tableau fcfr est modifie | --------- | Methode: | 1- calcul de la moyenne Mcent en enlevant perc_net% des pts | les + faibles et perc_net% des pts les + forts | 2- calcul de la valeur cutup correspondant a 2*perc_net% | des pts les + hauts en valeur absolue (fcfr-Mcent) | 3- calcul moyenne et sigma en enlevant les points ayant | abs(fcfr-Mcent) > cutup (1ere passe) | 4- calcul moyenne et sigma en enlevant les points ayant | abs(fcfr-Mcent) > cutup et | abs(fcfr-M(1ere passe)) > n_sigma*sigma(1ere passe) -- */ /* ++ | ENTREES: | Ns = nombre d'entrees dans fcfr | fcfr = tableau des valeurs a fitter | perc_net = pourcentage de donnees a nettoyer pour | calculer mean,sigma | n_sigma = nombre de sigma en passe 2 pour | calculer mean,sigma | deb = niveau de debug | SORTIES: | mean = valeur moyenne du decalage | emean = erreur sur la valeur moyenne du decalage | sigma = valeur de la resolution | esigma = erreur sur la valeur de la resolution | return code = nombre de points utilises (<0 si Pb) -- */ int Ajust_MnSg(int Ns,float *fcfr ,float *mean,float *emean,float *sigma,float *esigma ,float perc_net,float n_sigma,int deb) { int i,i1,i2,n,nvire,pass; double m,s,mcent,cutup,cuts; float *dum; /* set up des valeurs par defaut */ perc_net = ( perc_net >= 1. || perc_net < 0. ) ? 0.1 : perc_net; n_sigma = ( n_sigma <= 0. ) ? 3.0 : n_sigma; nvire = perc_net * Ns; if(perc_net>0. && nvire==0) nvire=1; *emean = *esigma = -1.; if(deb>0) printf("Ajust_MnSg[%d] perc_net=%f (vire=%d) n_sigma=%f\n" ,Ns,perc_net,nvire,n_sigma); /* on ordonne par ordre croissant de fcfr */ qsort(fcfr,(size_t) Ns,(size_t) sizeof(float),qSort_Float); i1 = nvire; i2 = Ns-1-nvire; if(deb>1) printf(" select de %d (%f) a %d (%f)\n",i1,fcfr[i1],i2,fcfr[i2]); if(i2<=i1) return(-101); /* on vire perc_net % des points a gauche et a droite de la distribution */ mcent = 0.; n = 0; for(i=i1;i<=i2;i++) {mcent += fcfr[i]; n++;} if(n<1) return(-102); mcent /= (double) n; if(deb>1) printf(" mean cent=%f sur %d points\n",mcent,n); /* allocate space and fill absolute value */ if( (dum = (float *) calloc(Ns,sizeof(float))) == NULL ) return(-103); for(i=0;i1) printf(" cutup=%f sur %d points\n",cutup,i); /* calcul mean et sigma en 2 passes avec coupure n_sigma*sigma(1ere passe)*/ cuts = GRAND2; for(pass=1;pass<=2;pass++) { m = s = 0.; n = 0; for(i=0;i cutup ) continue; if( fabs((double) (*mean-fcfr[i])) > cuts ) continue; m += fcfr[i]; s += fcfr[i]*fcfr[i]; n++; } if(n<=2) {n= -105; *mean = *sigma = -1.; goto END_Ajust_MnSg;} m /= n; s = s/n - m*m; if(s<=0.) {n= -106; *mean = *sigma = -1.; goto END_Ajust_MnSg;} s = sqrt(s); *mean = m; *sigma = s; cuts = n_sigma * s; if(deb>1) printf(" pass=%d mean=%g sigma=%g (%d pts) cuts=%f\n" ,pass,*mean,*sigma,n,cuts); } *emean = s/sqrt((double) n); *esigma = s/sqrt(2. * (double) n); if(deb>0) printf("mean=%g (+/-%g) sigma=%g (+/-%g) sur %d pts\n" ,*mean,*emean,*sigma,*esigma,n); END_Ajust_MnSg: if( dum != NULL ) free(dum); return(n); } /*=================================================================*/ /* Nathalie 16/02/95 */ /* ++ float Int3DCube(float(*fonction)(float,float,float),float step,float precision) Cette fonction calcule l'integrale 3D: f(x,y,z)dx.dy.dz L'integrale est calculee en incrementant des couronnes cubiques centrees sur le point de coordonnees (0,0,0) -- */ /* ++ | ENTREES: | fonction = f(x,y,z) | step = pas de l'integration | precision = coupure en dV(couronne i)/Vtot(couronnes 0 a i) | SORTIES: | return: l'integrale | REMARQUES: | la fonction f(x,y,z) doit decroitre tres vite en r**2 -- */ float Int3DCube(float(*fonction)(float,float,float),float step,float precision) { float f; double vol,volprec; int ecart,i,j,k,l; int encore,deb=0; vol = volprec = 0.; /* contribution du cube central */ for(l=0;l precision) || (ecart <= 2) ); if(deb>1) printf("ec=%d v=%g deltav/v=%g\n" ,ecart-1,vol*step*step*step,((vol-volprec)/vol)); } while(encore); vol *= step * step* step; if(deb>0) printf("\nVol = %g\n",vol); return(vol); } /*=================================================================*/ /* cmv 6/11/97 */ /* ++ int IntFaisDr - (int n,float *cs,float *sn,float *p,float *x0,float *y0 - ,int npass,float perclean,int lp) Pour calculer le point d'intersection moyen d'un faisceau de droites. -- */ /* ++ | L'equation des droites est sous la forme: | cos(alpha)*x + sin(alpha)*y = p | [cos(alpha),sin(alpha)] coordonnees du vecteur unitaire joignant | l'origine au point de moindre approche de la droite a l'origine. | p est la distance de la droite a l'origine. -- */ /* ++ | -- Input: | n : nombre de droites | cs : tableau des coefficients cos(alpha) | sn : tableau des coefficients sin(alpha) | p : tableau des coefficients p | npass : nombre de passes de nettoyage | perclean : pourcentage d'etoiles a tuer | d'une passe a la suivante | ex: perclean=0.2, si il y a 200 etoiles dans une passe | la passe suivante en utilisera 160 et la suivante 128. | lp : niveau d'impression -- */ /* ++ | -- Output: | x0 : valeur de l'abscisse du point d'intersection moyen trouve | y0 : ordonnee | -- Return: | nombre de droites utilisees pour le calcul de x0,y0 -- */ int IntFaisDr(int n,float *cs,float *sn,float *p,float *x0,float *y0 ,int npass,float perclean,int lp) { int i,j,ns, nsuse=-9, ipass; double sumC2,sumS2,sumCS,sumCP,sumSP,den; float *d2=NULL, d2cut=-1.; unsigned short *good=NULL; *x0 = *y0 = 0.; if(n<=1) return(-1); if(lp<0) lp=0;\ if(npass<=0) npass=1; if(perclean<=0.) { perclean=0.; npass=1;} if(lp) printf("IntFaisDr avec %d points en %d passes avec nettoyage de %g%%\n" ,n,npass,perclean*100); d2 = (float *) malloc(n * sizeof(float)); if(d2==NULL) { if(lp) printf("allocation de %d float impossible\n",n); return(-2); } good = (unsigned short *) malloc(n * sizeof(unsigned short)); if(good==NULL) { if(lp) printf("allocation de %d unsigned short impossible\n",n); free(d2); return(-3); } for(i=0;i=ns) j=ns-1; d2cut = d2[j]; ns=0; for(i=0;id2cut ) good[i]=0; else ns++; } if(lp>1) printf(" next pass: i=%d cut=%g -> restera %d dr\n",j,d2cut,ns); } free(d2); free(good); return(nsuse); } /*=========================================== cmv 22/11/04 ===*/ /* ++ double log_factoriel(unsigned int n) Compute the neperian log of n! -- */ double log_factoriel(unsigned int n) { unsigned int i; double sum=0.; if(n<2) return sum; for(i=n;i>1;i--) sum += log((double)i); return sum; } /* ++ double log_stirling(unsigned int n) Compute the neperian log of the Stirling approx of n! -- */ double log_stirling(unsigned int n) /* Approx: n! ~ sqrt(2Pi n) n^n exp(-n) = sqrt(2Pi) n^(n+1/2) exp(-n) log(n!) ~ (n+1/2) log(n) -n + 1/2 log(2Pi) (ordre 0: log(n!) ~ n (log(n)-1) */ { if(n<1) return 0.; return (n+0.5)*log(n) - n + Hln2pi; } /* ++ double log_gosper(unsigned int n); Compute the neperian log of the Gosper approx of n! -- */ double log_gosper(unsigned int n) /* Approx: n! ~ sqrt( (2n+1/3) Pi ) n^n exp(-n) log(n!) ~ 1/2 log( (2n+1/3) Pi ) + n log(n) -n */ { if(n<1) return 0.; return 0.5*log((2.*n+1./3.)*M_PI) + n*log(n) -n; } /* ++ double give_log_factoriel(unsigned int n); Compute the neperian log of the approx of n! -- */ static short give_log_factoriel_OK = 0; #define give_log_factoriel_LIM 21 static double give_log_factoriel_TAB[give_log_factoriel_LIM]; double give_log_factoriel(unsigned int n) { int i; if(give_log_factoriel_OK==0) { give_log_factoriel_OK=1; for(i=0;i