#include "machdefs.h" #include #include #include #include "nbtri.h" #include "nbmath.h" #include "matxop.h" #include "filtccd.h" static int DEB_FitPan = 0; static int DEB_BaseLine = 0; static int DEB_Bosse = 0; static int DEB_BossePaG = 0; static int DEB_SigmaInt = 0; static int DEB_FiltMed = 0; static int DEB_FiltInt = 0; static int Bosse_probnb = 0; /*=========================================================================*/ void SetDebFilt(int razer) { char *c; DEB_FitPan = DEB_BaseLine = DEB_Bosse = DEB_BossePaG = DEB_SigmaInt = DEB_FiltMed = DEB_FiltInt = 0; if( razer < 0 ) return; if( (c = getenv("DEB_FitPan")) ) DEB_FitPan = atoi(c); else DEB_FitPan = 0; if( (c = getenv("DEB_BaseLine")) ) DEB_BaseLine = atoi(c); else DEB_BaseLine = 0; if( (c = getenv("DEB_Bosse")) ) DEB_Bosse = atoi(c); else DEB_Bosse = 0; if( (c = getenv("DEB_BossePaG")) ) DEB_BossePaG = atoi(c); else DEB_BossePaG = 0; if( (c = getenv("DEB_SigmaInt")) ) DEB_SigmaInt = atoi(c); else DEB_SigmaInt = 0; if( (c = getenv("DEB_FiltMed")) ) DEB_FiltMed = atoi(c); else DEB_FiltMed = 0; if( (c = getenv("DEB_FiltInt")) ) DEB_FiltInt = atoi(c); else DEB_FiltInt = 0; } /*=========================================================================*/ double LPacZin(double t,double *Par,double *DgDpar) /* Christophe 11/02/94 fonction de paczinski en -magnitude 2.5*log10(Paczin) au temps t pour U0,T0,Tau,magfond et derivees de la fonction par rapport aux parametres [0]=U0,[1]=T0,[2]=Tau,[3]=magfond */ { double Paczin,u2,su2u24,tt0tau,dadu2; tt0tau = (t-Par[1])/Par[2]; u2 = Par[0]*Par[0] + tt0tau*tt0tau; su2u24 = sqrt(u2*(u2+4.)); dadu2 = -4./su2u24/su2u24/su2u24; Paczin = (u2+2.)/su2u24; DgDpar[0] = DftoDm/Paczin *dadu2* 2.*Par[0]; DgDpar[1] = DftoDm/Paczin *dadu2*(-2.*tt0tau/Par[2]); DgDpar[2] = DftoDm/Paczin *dadu2*(-2.*tt0tau*tt0tau/Par[2]); DgDpar[3] = 1.; Paczin = 2.5*log10(Paczin) + Par[3]; return (Paczin); } /*=========================================================================*/ double MPacZin(double t,double *Par,double *DgDpar) /* rcecile 13/06/94 fonction de paczinski a l'envers en -magnitude 2.5*log10(Paczin) au temps t pour U0,T0,Tau,magfond et derivees de la fonction par rapport aux parametres [0]=U0,[1]=T0,[2]=Tau,[3]=magfond */ { double Paczin,u2,su2u24,tt0tau,dadu2; tt0tau = (t-Par[1])/Par[2]; u2 = Par[0]*Par[0] + tt0tau*tt0tau; su2u24 = sqrt(u2*(u2+4.)); dadu2 = -4./su2u24/su2u24/su2u24; Paczin = (u2+2.)/su2u24; DgDpar[0] = DftoDm/Paczin *dadu2* 2.*Par[0]; DgDpar[1] = DftoDm/Paczin *dadu2*(-2.*tt0tau/Par[2]); DgDpar[2] = DftoDm/Paczin *dadu2*(-2.*tt0tau*tt0tau/Par[2]); DgDpar[3] = 1.; Paczin = -2.5*log10(Paczin) + Par[3]; return (Paczin); } /*=========================================================================*/ double LPacZin2(double t,double *Par,double *DgDpar) /* Christophe 11/02/94 fonction de paczinski en -magnitude 2.5*log10(Paczin) au temps t pour 1/U0,T0,1/Tau,magfond et derivees de la fonction par rapport aux parametres [0]=1/U0,[1]=T0,[2]=1/Tau,[3]=magfond */ { double Paczin,U2,U02,tt0,tt0tau,tt0tau2,dPdU2,U24p1,sU24p1,den; tt0 = t-Par[1]; tt0tau = tt0*Par[2]; tt0tau2 = tt0tau*tt0tau; U02 = Par[0]*Par[0]; U2 = U02/(1.+U02*tt0tau2); U24p1 = 1.+4*U2; sU24p1 = sqrt(U24p1); den = 1.+U02*tt0tau2; den *= den; dPdU2 = 4.*U2/(U24p1*sU24p1); Paczin = (1.+2.*U2)/sU24p1; DgDpar[0] = DftoDm/Paczin *dPdU2* 2.*Par[0]/den; DgDpar[1] = DftoDm/Paczin *dPdU2* 2.*U02*U02*Par[2]*tt0tau/den; DgDpar[2] = -DftoDm/Paczin *dPdU2* 2.*U02*U02*tt0*tt0tau/den; DgDpar[3] = 1.; Paczin = 2.5*log10(Paczin) + Par[3]; return (Paczin); } /*=========================================================================*/ double MPacZin2(double t,double *Par,double *DgDpar) /* rcecile 13/06/94 fonction de paczinski a l'envers en -magnitude 2.5*log10(Paczin) au temps t pour 1/U0,T0,1/Tau,magfond et derivees de la fonction par rapport aux parametres [0]=1/U0,[1]=T0,[2]=1/Tau,[3]=magfond */ { double Paczin,U2,U02,tt0,tt0tau,tt0tau2,dPdU2,U24p1,sU24p1,den; tt0 = t-Par[1]; tt0tau = tt0*Par[2]; tt0tau2 = tt0tau*tt0tau; U02 = Par[0]*Par[0]; U2 = U02/(1.+U02*tt0tau2); U24p1 = 1.+4*U2; sU24p1 = sqrt(U24p1); den = 1.+U02*tt0tau2; den *= den; dPdU2 = 4.*U2/(U24p1*sU24p1); Paczin = (1.+2.*U2)/sU24p1; DgDpar[0] = DftoDm/Paczin *dPdU2* 2.*Par[0]/den; DgDpar[1] = DftoDm/Paczin *dPdU2* 2.*U02*U02*Par[2]*tt0tau/den; DgDpar[2] = -DftoDm/Paczin *dPdU2* 2.*U02*U02*tt0*tt0tau/den; DgDpar[3] = 1.; Paczin = -2.5*log10(Paczin) + Par[3]; return (Paczin); } /*=========================================================================*/ double LErrExt(double m,double *Par,double *DgDpar) /* fonction des erreurs externes -- Cecile 23/02/94 */ { double errext; errext =exp(Par[1]*m) ; if ( errext < 1.e-200 ) errext = 0.; DgDpar[0] = errext; errext *= Par[0]; DgDpar[1] = m*errext; DgDpar[2] = 1.; errext += Par[2]; return (errext); } /*=========================================================================*/ void SetBosse_probnb(int iset) { if( iset<=0 ) Bosse_probnb=0; else Bosse_probnb=1; } /*=========================================================================*/ int_4 Bosse(float *mag,float *err,int_4 ndata ,float mean,int_4 nptmin,float scut,int_4 nptscut ,float *chi2,int_4 *npoint,float *Pchi2 ,int_4 *ideb,int_4 *ifin,int_4 *classB,int_4 NbossMX) /* Christophe 10/11/93 La Silla **** Recherche de Bosses **** ENTREE: mag: magnitude err: erreur sur la magnitude ndata: nombre de donnees mean: moyenne de reference pour calculer les bosses nptmin: nombre minimum de points pour valider une bosse scut, nptscut: definition des conditions d'arret de la bosse: Soit un point de signe oppose a plus de abs(scut*sigma) Soit nptscut points a moins de abs(scut*sigma) si scut<=0. la seule interruption est sur le changement de signe SORTIE: chi2: Xi2 des bosses npoint: nombre de points dans la bosse Pchi2: probabilite de Xi2 des bosses ideb: indice du debut de la bosse ifin: indice de fin de la bosse (idem) classB: tableau des indices de rangement par probabilite de Xi2 croissant NbossMX: nombre maximum de bosses permis Bosse: nombre de bosse trouvees */ { int_4 deb=DEB_Bosse; int_4 ipo,ifirst,j,k,npt,i1,i2,sgn,sgnsave,nbosse,np_scut,cont_bosse,pass; double v,av,ev,c2,sc2,pc2; ipo = sgnsave = npt = i1 = i2 = ifirst = np_scut = 0; nbosse = -1; c2 = sc2= pc2 = 0.; nptmin = ( nptmin <= 0 ) ? 1 : nptmin ; nptscut = ( nptscut <= 0 ) ? 1 : nptscut ; scut = ( scut <= 0. ) ? 0. : scut ; while ( ipo < ndata ) { ev = err[ipo]; v = 0.; if ( ev > 0. ) v = ( mag[ipo] - mean ) / ev; av = fabs(v); sgn = ( v > 0. ) ? 1 : -1 ; if ( deb >= 4 ) printf("ipo=%5d sgn=%2d v=%f ev=%f\n",ipo,sgn,v,ev); /* conditions d'increment de la fluctuation*/ cont_bosse = 1; if ( sgn != sgnsave && av > scut ) cont_bosse = 0; if ( cont_bosse && ev > 0. ) { npt++; c2 += v*v; pc2 += nberfc(av/Rac2) + Log2; i2 = ipo; if( av < scut ) { np_scut++;} else { np_scut=0;} } /* conditions d'arret de la fluctuation */ if ( ( cont_bosse == 0 && ev>0. ) || ( np_scut>=nptscut && ev>0. ) || ( ipo == ndata-1 ) ) { /* y a t il assez de points ? */ if ( npt >= nptmin ) { nbosse++; /* on prend prob(xi2,npt)/2**(npt-1) */ if(Bosse_probnb) pc2 = (double) probnb( (float) c2,npt,&pass) + (npt-1)*Log2; if ( nbosse >= NbossMX ) { printf("Bosse: Trop de bosses (%d), changez dimension tableaux",nbosse); exit(-1); } else if ( nbosse == 0 ) { classB[0] = 0; } else if ( nbosse > 0 ) { for ( j=0;j fabs( (double) Pchi2[classB[j]] ) ) break; for ( k=nbosse-1;k>=j;k--) classB[k+1] = classB[k]; classB[j] = nbosse; } Pchi2[nbosse] = sgnsave*pc2; sc2 += sgnsave*c2; chi2[nbosse] = sgnsave*c2; npoint[nbosse] = npt; ideb[nbosse] = i1; ifin[nbosse] = i2; if(deb>=3) printf("Find bosse %5d, npt=%5d lim=%5d %5d classB=%5d pc2=%.2f\n" ,nbosse,npoint[nbosse],ideb[nbosse],ifin[nbosse] ,classB[nbosse],Pchi2[nbosse]); } i1 = ipo; npt = 1; sgnsave = ( v > 0. ) ? 1 : -1; c2 = v*v; pc2 = nberfc(av/Rac2) + Log2; } ipo++; } nbosse++; if(deb) printf("Bosse: nombre de bosses trouvees=%d, somme des Pchi2=%f\n" ,nbosse,sc2); if ( nbosse > 0 && deb ) { k=3; if ( deb >= 2 ) k=nbosse; for (ipo=0;ipo scut (ou < -scut) scut, nptscut: definition des conditions d'arret de la bosse: nptscut points a moins de scut**err si bosse positive nptscut points a plus de -scut**err si bosse negative Conseil: scut = 1. NbossMX: nombre maximum permis de bosses SORTIE: chi2: tableau des Xi2 des bosses npoint: tableau des nombres de points dans les bosses (du meme signe que la bosse) Pchi2: tableau des probabilites de Xi2 des bosses ideb: tableau des indices de debut des bosses ifin: tableau des indices de fin des bosses (idem) classB: tableau des indices de rangement par probabilite de Xi2 croissant ex: pchi2 de la 3ieme bosse = Pchi2[classB[2]] return: Bosse: nombre de bosses trouvees REMARQUE: npoints != ifin-ideb+1 car 1-/ il y a des points a erreur <=0 2-/ les points de signes opposes au signe de la bosse ne sont pas comptabilises c'est le nombre de points de meme signe que la bosse dans la bosse le nombre total de points dans la bossse est ifin-ideb+1 */ { int deb=DEB_Bosse; /* 0,1,2,3 */ int j,k,ipo,npt=0,npt_cut=0,npt_c2_cut=0,i1=-1,i2=-1,sgn,sgnsave,nbosse,npt_valid,pass; double v,av,ev,c2,pc2,c2_cut,pc2_cut; char s; if(smin<0.) smin = 1.; if(nptsmin<=0) nptsmin = 1; if(scut<0.) scut = 1.; if(nptscut<=0) nptscut = 1; if(deb>=1) printf("***** BosseN ndata=%d smin=%d, %f scut=%d, %f\n" ,ndata,nptsmin,smin,nptscut,scut); if( ndata <= 1 ) return(-1); nbosse = -1; ipo = sgnsave = 0; for (;;) { /* caracteristiques du point ipo */ ev = err[ipo]; if ( ev > 0. ) v = ( mag[ipo] - mean ) / ev; else v = 0.; if ( v > 0. ) { av = v; sgn = 1; } else { av = -v; sgn = -1; } if (deb>=3) printf(" ipo=%5d sgn=%2d v=%f ev=%f c2=%f\n",ipo,sgn,v,ev,v*v); if ( ev>0. && sgnsave==0 && av>=scut ) { /* essai d'une nouvelle bosse (sgnsave==0), on demarre si > scut */ i1 = i2 = ipo; sgnsave = sgn; c2 = v*v; pc2 = nberfc(av/Rac2) + Log2; npt = 1; if( av >= smin ) npt_valid = 1; else npt_valid = 0; c2_cut = pc2_cut = 0.; npt_cut = npt_c2_cut = 0; if(deb>=3) printf("* Dep bosse [%d] i1=%d n,c2,pc2= %d, %.3f, %.3f\n" ,sgnsave,i1,npt,c2,pc2); } else if( sgnsave!=0 && ( (ev>0. && sgnsave*v0. && sgnsave*v0. && sgnsave*v>=scut ) { /* c-a-d le dernier point (ipo==ndata-1) */ /* avec une amplitude (grande) continuant la bosse */ /* --> dans ce cas la bosse doit inclure ce point */ /* et eventuellement les precedents de cette coupure */ s = '+'; npt += 1 + npt_c2_cut; c2 += v*v + c2_cut; pc2 += nberfc(av/Rac2) + Log2 + pc2_cut; if( av >= smin ) npt_valid++; i2 = ipo; } else { /* cas ipo==ndata-1 et ev<=0. : point ignore */ s = '0'; } if(deb>=3) printf("- Fin%c ncut=%d n,c2,pc2= %d, %.3f, %.3f cut= %d, %.3f, %.3f\n" ,s,npt_cut,npt,c2,pc2,npt_c2_cut,c2_cut,pc2_cut); if ( npt_cut>=nptscut || ipo==ndata-1 ) { /* c'est une fin de bosse */ if ( npt_valid >= nptsmin ) { /* validation de la bosse */ nbosse++; /* on prend prob(xi2,npt)/2**(npt-1) */ if(Bosse_probnb) pc2 = (double) probnb((float) c2,npt,&pass) + (npt-1)*Log2; if ( nbosse >= NbossMX ) { printf("Bosse: Trop de bosses (%d), changez dimension tableaux",nbosse); return(-NbossMX); } else if ( nbosse == 0 ) { classB[0] = 0; } else if ( nbosse > 0 ) { for ( j=0;j fabs( (double) Pchi2[classB[j]] ) ) break; for ( k=nbosse-1;k>=j;k--) classB[k+1] = classB[k]; classB[j] = nbosse; } Pchi2[nbosse] = sgnsave*pc2; chi2[nbosse] = sgnsave*c2; npoint[nbosse] = npt; ideb[nbosse] = i1; ifin[nbosse] = i2; if(deb>=3) printf("* Bosse %d, lim=%d %d classB=%d n,c2,pc2=%d %.3f %.3f\n" ,nbosse,ideb[nbosse],ifin[nbosse],classB[nbosse] ,npoint[nbosse],chi2[nbosse],Pchi2[nbosse]); } else { if(deb>=3) printf("* Bosse rejetee npt=%d /%d\n",npt,nptsmin); } sgnsave = 0; ipo = i2; } } else if ( ev>0. && sgnsave!=0 ) { /* c'est un point normal dans la bosse */ npt += 1 + npt_c2_cut; c2 += v*v + c2_cut; pc2 += nberfc(av/Rac2) + Log2 + pc2_cut; if( av >= smin ) npt_valid++; i2 = ipo; if(deb>=3) printf("- add point i2=%d n,c2,pc2= %d, %.3f, %.3f cut= %d, %.3f, %.3f\n" ,i2,npt,c2,pc2,npt_c2_cut,c2_cut,pc2_cut); npt_cut = npt_c2_cut = 0; c2_cut = pc2_cut = 0.; } else { /* point a erreur negative ou points a moins de scut sans bosse demarree */ if(deb>=3) printf("- pas de bosse demarree (%d) ou erreur negative (%f)\n" ,sgnsave,ev); } ipo++; if(ipo >= ndata ) break; } nbosse++; if(deb>=1) { printf("Bosse: nombre de bosses trouvees=%d\n",nbosse); if ( nbosse>0 ) { printf("********************************************************\n"); k=3; if ( deb>=2 ) k=nbosse; for (ipo=0;ipo0 mag=magnitudes, si <0 mag=flux) mean: valeur de la ligne de base I1: indice de depart de la bosse I2: indice de fin de la bosse U0: si >0 la bosse est positive, si <0 la bosse est negative SORTIE: U0: estimation du parametre d'impact U0 T0: estimation du temps de minimum d'approche T0 Tau: estimation de la largeur Tau BossePaG: retourne 0 si calcul ok, <0 sinon Methode: Les parametres T0 et Tau sont estimes a partir de la distribution en temps des points dans la bosse, U0 par l'estimation de la hauteur de la gaussienne de sigma calcule pour la valeur de Tau et de l'aire de la bosse. */ { int_4 deb=DEB_BossePaG; int_4 i,flu=0,bossp=1; float tprev,magprev; double v,m,s,norm,sint,hgauss,a,aa,u12,hmax; int ifirst; if( ndata<0 ) { flu=1; ndata *= -1;} if( *U0<0 ) bossp = -1; *U0 = *T0 = *Tau = 0.; if ( I2 <= I1 ) {printf("BossePaG: I1 <= I2 %d %d\n",I1,I2); return(-1);} if ( mean <= 0. && flu ) return(-11); if(deb) printf("BossePaG: de I1=%d a I2=%d n=%d mean=%g flu=%d\n" ,I1,I2,ndata,mean,flu); /* Calcul de T0 et Tau */ hmax= -1.e30; tprev = temps[I1]; magprev = mean; /* $CHECK$ EA pas cool l'init de magprev */ /* magprev peut etre une amplitude, mais pas mean !! */ /* $CHECK$ EA si on tue le point I1, sint delire. Je rajoute ifirst */ m = s = norm = sint = 0.; ifirst = 1; for (i=I1;i<=I2;i++) { if ( err[i] <= 0. ) continue; if(flu && bossp<0 && mag[i]<=0.) continue; if(flu && bossp>=0) a = mag[i]/mean-1.; else if(flu && bossp<0) a = 1.-mean/mag[i]; else a = mag[i]-mean; aa = bossp*a; if( aa<=0 ) continue; if( aa > hmax ) hmax=aa; v = temps[i]; m += v*aa; s += v*v*aa; norm += aa; if ( !ifirst ) sint += (temps[i]-tprev)*(a+magprev)/2.; else ifirst = 0; tprev = temps[i]; magprev = a; } if(norm <= 0. ) return(-2); sint = fabs(sint); m = m/norm; s = s/norm - m*m; if(s <= 0.) return(-3); s = sqrt(s); hgauss = sint / S2Pi / s; if (deb>=2) printf("m=%f s=%f int=%f hgauss=%f hmax=%f\n",m,s,sint,hgauss,hmax); /* T0 = moyenne */ *T0 = m; /* U0 = hauteur de la gaussienne de sigma s */ if(flu) a = hgauss+1.; else a = pow(10.,0.4*hgauss); if(a<=1. || a>= sqrt(GRAND2)) return(-4); *U0 = 2.*(a/sqrt(a*a-1.)-1.); if(deb>=2) printf("A0=%f u0^2=%f",a,*U0); /* Tau = en considerant que 2.36*s est la largeur a mi-hauteur (magnitude) de la courbe de pazcinski */ if(flu) a = hgauss/2.+1.; else a = pow(10.,0.2*hgauss); if(a<1.) return(-5); u12 = 2*(a/sqrt(a*a-1.)-1.); if (deb>=2) printf(" a1/2=%f u1/2^2=%f\n",a,u12); v = 2.36*s/2.; if ( u12 <= *U0 ) return(-6); v = v*v/(u12-*U0); *Tau = sqrt(v); *U0 = sqrt(*U0); if (deb) printf("BossePaG: U0=%f, T0=%f, Tau=%f\n",*U0,*T0,*Tau); return(0); } /*=========================================================================*/ float SigmaInt(float *temps,float *mag,float *err,int_4 *ndata,float nsigma) /* Christophe 12/11/93 La Silla **** Calcul du sigma interne d'une courbe de lumiere **** ENTREE: temps: temps mag: magnitude err: erreur sur la magnitude ndata: nombre de donnees nsigma: nombre de sigmas pour la coupure de la 2sd passe si <=0 une seule passe SORTIE: SigmaInt: retourne le sigma Interne ou <0 si il y a eu un probleme - Methode: On calcul le sigma avec la dispersion d'un point Y(t) et de la prediction lineaire a partir de ses 2 voisins Y0(t) et Y1(t): M = Y - Ypred = Y - (Y1 +(Y2-Y1)/(t2-t1)*(t-t1)) le calcul de propagation des erreurs donne: SM = 2*(R^2-R+1)*SY avec SY=SY1=SY2 et R=(t-t1)/(t2-t1) (<1.) donc pour avoir SY on calcul le sigma de la quantite: M et on divise le resultat par sqrt( <2*(R^2-R+1)> ) ce qui dans le cas ou les points sont equidistants donne comme R=1/2: SM/sqrt(3/2) */ { int_4 deb=DEB_SigmaInt; int_4 pass,passmx,i,n=0; float sigma; double m,s,fpred,R,sR; passmx = ( nsigma > 0. ) ? 2 : 1 ; if ( *ndata < 3 ) return(-1.); sigma = GRAND; if( nsigma <= 0. ) nsigma = 1.; for (pass=1;pass<=passmx;pass++) { n=0; m = s = sR = 0.; for (i=1;i<*ndata-1;i++) { if ( err[i] > 0. && err[i-1] > 0. && err[i+1] > 0. ) { R = ( temps[i] - temps[i-1] ) / ( temps[i+1]- temps[i-1] ); fpred = mag[i] - ( mag[i-1] + (mag[i+1]- mag[i-1] )*R ); if ( fabs(fpred) < nsigma*sigma ) { m += fpred; s += fpred*fpred; sR += 2.*(R*R-R+1.); n++; } } } if ( n <= 0 ) return(-2.); m = m/n; sR = sR/n; sigma = sqrt(s/n) / sqrt(sR); if ( deb ) printf("SigmaInt: pass=%d sigma=%f m=%f sR=%f npoints=%d\n" ,pass,sigma,m,sR,n); } *ndata = n; return(sigma); } /*=========================================================================*/ int_4 FiltMed(float *mag,float *err ,float *magflt, float* errflt, int_4 ndata) /* Christophe 13/11/93 La Silla **** Filtre Statistique Median a 3 points **** ENTREE: mag: magnitude err: erreur sur la magnitude ndata: nombre de donnees SORTIE: magflt: magnitude filtree errflt: erreur sur la magnitude filtree FiltMed: retourne 0 si ok, <0 sinon. */ { int deb=DEB_FiltMed; int j,k0,k1,k2,imin=-1,imax=-1; if ( ndata<3 ) { for (k0=0;k0 0 ) k1--; /* recherche du 1er point superieur utilisable */ k2 = k0+1; while ( err[k2] <= 0. && k2 < ndata-1 ) k2++; if ( err[k1]<=0. || err[k2]<=0. ) continue; if ((mag[k1]-mag[k0])*(mag[k2]-mag[k0])<0.) j=k0; else if((mag[k0]-mag[k1])*(mag[k2]-mag[k1])<0.) j=k1; else if((mag[k1]-mag[k2])*(mag[k0]-mag[k2])<0.) j=k2; else { if (mag[k0]==mag[k1]) {if(err[k0]<=err[k1]) j=k0; else j=k1;} else if(mag[k1]==mag[k2]) {if(err[k1]<=err[k2]) j=k1; else j=k2;} else {if(err[k2]< err[k0]) j=k2; else j=k0;} } magflt[k0] = mag[j]; errflt[k0] = err[j]; if( imin == -1 ) imin = k0; imax = k0; } /* cas du premier point */ k0 = 0; magflt[k0] = mag[k0]; errflt[k0] = err[k0]; if( err[k0]>0. && imin>=0 ) { magflt[k0] = magflt[imin]; errflt[k0] = errflt[imin];} /* cas du dernier point */ k0 = ndata-1; magflt[k0] = mag[k0]; errflt[k0] = err[k0]; if( err[k0]>0. && imax>=0 ) { magflt[k0] = magflt[imax]; errflt[k0] = errflt[imax];} /* debug? */ if (deb>=1) { printf("FiltMed:"); for(k0=0;k01) printf("FiltInt: limites bosse %f %f (%f)\n",t1,t2,dt); t1 -= dt; t2 += dt; if(deb>1) printf("FiltInt: limites intervalle de fit %f %f\n",t1,t2); /* calcul de la borne inferieure de fit */ n=0; for (i=I1;i>=0;i--) { if(err[i] > 0. ) { n++; if( temps[i] < t1 && n > npomin ) break; } } ntot += n; *ideb= ( i<0 ) ? 0 : i; /* calcul de la borne superieure de fit */ n=0; for (i=I2;i 0. ) { n++; if( temps[i] > t2 && n > npomin ) break; } } ntot += n; *ifin= ( i>= ndata ) ? ndata-1 : i; if(deb) printf("FiltInt: limites intervalle de fit %d %d\n",*ideb,*ifin); return(ntot); } /*======================================================================================*/ double chi2_exterieur(float *mag,float *err,int_4 ndata,float mean ,int_4 I1,int_4 I2,int_4 *npt) /* Cecile calcul du Chi2 par degre de liberte a l'exterieur de la bosse delimitee par i1 et I2 ENTREE : mag : magnitude err : erreur sur la magnitude ndata : nombre de donnees mean : moyenne des mesures I1, I2 : limites de la bosse SORTIE: chi2_exterieur : valeur du Chi2 reduit a l'exterieur de la bosse */ { int_4 i; double chi2,d; if ( I2 <= I1 ) {printf("chi2_ext. : I2 <= I1 %d %d\n",I1,I2); return(-1.);} *npt=0; chi2=0.; if(I1>0) { for(i=0;i 0.) { d = (mag[i] - mean) / err[i]; chi2+= d*d; (*npt)++; } } } if(I2 0.) { d = (mag[i] - mean) / err[i]; chi2+= d*d; (*npt)++; } } } return(chi2); } /*===================================================================*/ double Dt_PacZin(double u0,double tau,double A) /* pour calculer le DT ou la paczinsky a une ampli de A */ { double x; if( A <= 1. ) return(-1.); x = 2.*( A / sqrt(A*A-1.) - 1. ) - u0*u0; if( x <= 0. ) return(-2.); x = tau * sqrt(x); return(x); } /*==================================================================*/ int_4 Most_3D2D(float *Y,float *EY,int_4 *ndata,float Ymin,float Ymax ,float *Res_2D,float *Res_3D) /* Pour calculer la valeur la + probable par estimation des parametres d'une distribution parabolique / polynome de degre 3 INPUT: Y: tableau des valeurs EY: tableau des erreurs (<=0 point non traite) ndata: nombre de valeurs Ymin,Ymax: limites des valeurs a considerees pour Y OUTPUT: ndata: nombre de valeurs utilisees pour le calcul Res_2D: resultat du fit parabolique Res_3D: resultat du fit polynome d'ordre 3 rc: validation des resultats =0 : probleme =1 : fit parabolique ok =2 : fit polynome_ordre_3 ok =3 : fit parabolique + polynome_ordre_3 ok */ { int i,n,Flag,lp=0; double xmoy,x2moy,x3moy; double v1,v2,VN,det; double M3[3][3],M2[2][2],B[3],AX[4]; if(lp) printf("Most_3D2D: ndata=%d Ymin=%g Ymax=%g\n",*ndata,Ymin,Ymax); *Res_3D = 0.; *Res_2D = 0.; Flag = 0; if( *ndata<=0 || Ymax <= Ymin ) goto END; /* on recentre tout entre 0 et 1 donc Ymin=0 YMax=1 */ VN = Ymax-Ymin; n = 0; xmoy = x2moy = x3moy = 0.; for(i=0;i<*ndata;i++) { if( EY[i]>0. && Y[i]>Ymin && Y[i]=%g =%g =%g\n",xmoy,x2moy,x3moy); /* On remplit la matrice 2x2 pour le fit parabolique */ M2[0][0] = 1./5. -1./9.; M2[0][1] = M2[1][0] = M2[1][1] = 1./12.; /* = 1./4. -1./6. = 1./3. -1./4. */ B[0] = x2moy - 1./3.; B[1] = xmoy - 0.5; det = SolveDLinSyst(&(M2[0][0]), B, AX, 2); if(lp) printf("Solve_2D: det=%g sol=%g %g\n",det,AX[0],AX[1]); if ( det != 0. ) { if ( AX[0] != 0. ) { Flag += 1; *Res_2D = -AX[1]/(2.*AX[0]); if(lp) printf(" s1=%g\n",*Res_2D); *Res_2D = Ymin + *Res_2D*VN; } } /* On remplit la matrice 3x3 pour le fit polynome d'ordre 3 */ M3[0][0] = M3[2][2] = 1./5. -1./8.; /* 1./12. = 1./4. -1./6. = 1./3. -1./4. = 1./6. -1./12 */ M3[0][1] = M3[1][2] = M3[0][2] = M3[1][0] = M3[2][1] = 1./12.; M3[1][1] = 1./5. -1./9.; M3[2][0] = 1./7. -1./16.; B[0] = xmoy - 0.5; B[1] = x2moy - 1./3.; B[2] = x3moy - 0.25; det = SolveDLinSyst(&(M3[0][0]), B, AX, 3); if(lp) printf("Solve_3D: det=%g sol=%g %g %g\n",det,AX[0],AX[1],AX[2]); if ( det != 0. ) { /* on cherche les 2 racines de l'annulation de la derivee */ det = AX[1]*AX[1] - 3.*AX[0]*AX[2]; if(lp) printf(" det=%g\n",det); if ( det >= 0. && AX[0] != 0. ) { xmoy = (-AX[1] + sqrt(det))/(3.*AX[0]); v1 = 6.*AX[0]*xmoy+2.*AX[1]; x2moy = (-AX[1] - sqrt(det))/(3.*AX[0]); v2 = 6.*AX[0]*x2moy+2.*AX[1]; if(lp) printf(" s1=%g (%g) s2=%g (%g)\n",xmoy,v1,x2moy,v2); Flag += 2; *Res_3D = xmoy; if(v2<0.) *Res_3D = x2moy; *Res_3D = Ymin + *Res_3D*VN; } } END: if(lp) printf("Most_3D2D: *Res_2D=%g *Res_3D=%g Flag=%d\n" ,*Res_2D,*Res_3D,Flag); return(Flag); } /*==================================================================*/ double correlation(int_4 npts,double *x,double *y) { /* Cecile Numerical Recipies p. 503 Calcule le coefficient de correlation de x et y sur npts points ENTREE : npts nombre de points x, y tableau des valeurs SORTIE: correlation : coefficient de correlation -2 si nb de points OK < 3 -3 si produit des (x[i]-ax)(y[i]-ay)<=0 */ int_4 i,n; double ax,ay,xt,yt,sxx,syy,sxy; n=0; ay = ax= 0.; for(i=0;i0.) ? sxy/sqrt(sxx*syy) : -3.) ); } /*==================================================================*/ double CorrelatioN(int_4 nptX,float *X,float *Y,int_4* IndXvY) /* cmv 17/4/99 Calcule le coefficient de correlation de X[] et Y[] sur nptX points ENTREE : nptX nombre de points dans le tableau X[] X[], Y[] : tableau des valeurs a correler IndXvY[] : tableau des indices de Y[] a correler a X[] SORTIE: coefficient de correlation -2 si nb de points OK (>3) -3 si somme des (X[i]-ax)^2 ou (Y[i]-ay)^2 <=0 EXPLICATION: X[1,nptX-1], Y[....], IndXvY[1,nptX-1] - le point X[i] correspond au point Y[IndXvY[i]] si IndXvY[i]>=0 - le point X[i] n'est pas pris en compte si IndXvY[i]<0 */ { int_4 i,n; double ax,ay,xt,yt,sxx,syy,sxy; n=0; ay=ax=0.; for(i=0;i=0) {ax+=X[i]; ay+=Y[IndXvY[i]]; n++;} if(n<3) {printf("CorrelatioN: %d<3 points pour le calcul\n",n); return(-2.);} ax /= n; ay /= n; xt = yt = syy = sxy = sxx = 0.; for(i=0;i=0) { xt = X[i]-ax; yt = Y[IndXvY[i]]-ay; sxx += xt*xt; syy += yt*yt; sxy += xt*yt; } return( ((sxx*syy>0.) ? sxy/sqrt(sxx*syy) : -3.) ); } /*=========================================================================*/ int_4 MeanLine(float *mag,float *err,int_4 *ndata ,int passmx,float nsigma,float *mean,float *sigma) /* Calcul de la moyenne et du sigma en plusieurs passes avec nettoyage ENTREE: mag: magnitude err: erreur sur la magnitude (Si NULL pas d'erreur) ndata: nombre de donnees nsigma: nombre de sigma dans lequel on calcule le mean passmx: nombre de passes SORTIE: ndata: nombre de data utilises pour calculer le most mean: moyenne des donnees sigma: sigma des donnees MeanLine: 0 si calcul ok, <0 sinon */ { int_4 pass,n,i; double m,s2,scut,v; if( passmx<=0 ) passmx = 1; *mean = *sigma = 0.; for (pass=1;pass<=passmx;pass++) { m = s2 = 0.; n=0; if( pass>=2 ) scut=*sigma*nsigma; else scut=GRAND; for (i=0;i<*ndata;i++) { v = mag[i]; if(err!=NULL) if( err[i] <= 0. ) continue; if( fabs(v-*mean) >= scut ) continue; n++; m += v; s2 += v * v; } if ( n>0 ) { m /= (double) n; v = s2/n - m*m; *mean = m; *sigma = (v>0) ? sqrt(v) : 0.; } else { *mean = *sigma = 0.; *ndata=n; return(-1); } /* printf("MeanLine: pass=%d mean=%f sigma=%f n=%d\n" ,pass,*mean,*sigma,n); */ } return(0); } /*=========================================================================*/ int_4 BaseLine(float *mag,float *err,int_4 *ndata,float nsigma ,float binini,float *mean,float *sigma,float *most) /* Christophe 10/11/93 La Silla + modif 28/7/94 Saclay **** calcul de la ligne de base d'une etoile par maxi d'histogramme **** Methode: 1-/ moyenne, 2-/ moyenne tronquee, 3-/ maximum d'histogramme, 4-/ puis deuxieme passe sur histo plus lache ENTREE: mag: magnitude err: erreur sur la magnitude ndata: nombre de donnees nsigma: nombre de sigma dans lequel on calcule le maximum si <=0, une seule passe pour la moyenne et dynamique histo = 5. binini: bin minimum de la methode d'histogramme SORTIE: ndata: nombre de data utilises pour calculer le most mean: moyenne des donnees sigma: sigma des donnees most: maximum de probabilite RETURN: nombre d entrees dans le bin du maximum, <0 si echec */ { int_4 deb=DEB_BaseLine; int_4 pass,passmx,i,ib0,ib1,n=0,ibin,nbin=0,tab0mx,nbinmx=100,tab0[101]; float mini,maxi,binw; double m,s2,v,vv,scut; double SX4,SX3,SX2,SX,S1,SYX2,SYX,SY; double MX33[3][3],BB[3],AX[3],det; if(deb) printf("BaseLine: n=%d nsigma=%f binini=%f\n",*ndata,nsigma,binini); /*********** D'abord une moyenne et sigma ************/ *mean = *sigma = 0.; passmx = ( nsigma <= 0. ) ? 1 : 2 ; for (pass=1;pass<=passmx;pass++) { m = s2 = 0.; n=0; scut = GRAND; if( pass == 2 ) scut = nsigma* *sigma; for (i=0;i<*ndata;i++) { v = mag[i]; if( err[i] <= 0. || fabs(v-*mean) >= scut ) continue; n++; m += v; s2 += v*v; } if ( n >= 2 ) { *mean = m / n; v = s2 / n - m/n * m/n; *sigma = ( v>0. ) ? sqrt(v) : 0.; } else { *mean = *sigma = 0.; *ndata=n; return(-1); } if(deb) printf("BaseLine: pass=%d mean=%f sigma=%f n=%d\n" ,pass,*mean,*sigma,n); if( *sigma == 0. ) return(-1); } /***** Puis une methode de maximum d'histogramme *****/ if ( nsigma <= 0. ) nsigma = 5.; mini = *mean - nsigma * *sigma; maxi = *mean + nsigma * *sigma; for (pass=1;pass<=2;pass++) { if( binini > 0. ) { if ( pass == 1 ) nbin = (maxi-mini)/(2.*binini) + 0.5; /* 1ere pass a 2*binini */ if ( pass == 2 ) nbin = (maxi-mini)/binini + 0.5; /* 2sd pass a binini */ if ( nbin >= nbinmx ) nbin = nbinmx; if ( nbin < 3 ) nbin = 3; } else nbin = nbinmx; binw = (maxi-mini)/nbin; if(deb) printf("mini=%f maxi=%f binw=%f nbin=%d\n",mini,maxi,binw,nbin); /*fill histogramme tab0*/ for (i=0;i= 0 && ibin < nbin ) tab0[ibin] += 1; } /*maximum de l'histogramme tab0*/ ibin=0; tab0mx = 0; for (i=0;i tab0mx ) {tab0mx = tab0[i]; ibin=i;} ib0 = ibin-1; ib1 = ibin+1; if(ib0<0) { ib0 = 0; ib1++;} if(ib1>=nbin) { ib1 = nbin-1; ib0--;} if (deb>1) { printf("Maximum tab0=%d (%d [%d,%d])\n",tab0mx,ibin,ib0,ib1); if (deb>2) { printf("Tableau final tab0:\n"); for (i=0;i= maxi ) return(-3); /*nouveaux parametres de l'histogramme tab0 */ mini = *most-2.5*binw; maxi = *most+2.5*binw; } *ndata=n; return(tab0mx); } /*=========================================================================*/ int BaseLineS(float *y,float *ey,int ny,int nfiltre,float *mean,float *sigma) /* D'apres Alain M. + modifs + code cmv 5/5/97 Determination de la ligne de base comme sequence de nfiltre points consecutifs de dispersion minimale: y : tableau des flux ey : tableau des erreurs sur les flux (pt non util. si <=0) ny : nombre de points nfiltre : nombre de points consecutifs pour calculer le sigma si <0 y est d'abord range par flux croissants mean : valeur du fond de ciel retourne sigma : valeur du sigma mini trouve rc : nombre d essais ( si <=0 echec) */ { int rc=0, isort=0,i,j,npt,n; double s,m; float *ys=NULL; *mean = *sigma = -1.; if( ny<=1 ) return(-1); if( nfiltre<0 ) { isort = 1; nfiltre *= -1; npt = 0; ys = (float *) malloc(ny*sizeof(float)); if( ys==NULL ) return(-2); for(i=0;i0.) ys[npt++] = y[i]; qsort(ys,(size_t) npt,(size_t) sizeof(float),qSort_Float); } else { npt=ny; ys = y;} if( nfiltre>npt || nfiltre<=1 ) { if(isort) free(ys); return(-3);} for(i=0;i0. ) ? sqrt(s) : 0.; if( s<*sigma || rc==1 ) { *sigma=s; *mean=m; } break; } } if(isort) free(ys); return(rc); } /*=========================================================================*/ int BaseLineP(float *y,float *ey,int ny,int nfiltre,float *mean) /* D'apres Alain M. + modifs + code cmv 5/5/97 Determination de la ligne de base comme endroit de pente minimale entre le point [i] et [i+nfiltre-1]. Ceci marche mieux avec le tableau trie mais la possibilite de ne pas trier est laissee: y : tableau des flux ey : tableau des erreurs sur les flux (pt non util. si <=0) ny : nombre de points nfiltre : nombre de points pour calculer la pente si <0 y est d'abord range par flux croissants mean : valeur du fond de ciel retourne rc : nombre d essais ( si <=0 echec) */ { int rc=0, isort=0,i,j,npt,n; float p=-1.,pmin=-1.,m; float *ys=NULL; *mean = -1.; if( ny<=1 ) return(-1); if( nfiltre<0 ) { isort = 1; nfiltre *= -1; npt = 0; ys = (float *) malloc(ny*sizeof(float)); if( ys==NULL ) return(-2); for(i=0;i0.) ys[npt++] = y[i]; qsort(ys,(size_t) npt,(size_t) sizeof(float),qSort_Float); } else { npt=ny; ys = y;} if( nfiltre>npt || nfiltre<=1 ) { if(isort) free(ys); return(-3);} for(i=0;i