/* Steven Andrews, 11/20/03 */ /* Rewrite of rebind.c, because that program is confusing. */ /* Here, either of two systems are simulated: clustered receptors on a sphere and unclustered receptors on a sphere. In the former case, the receptors extend over only a small portion of the sphere; in the latter case, they cover the whole sphere nearly uniformly. */ #include #include #include #include "random.h" #define PI 3.14159265358979323846 #define DIFF 500.0 // ### diffusion constant, in nm^2/us (500 for aspartate in water, 136 CheR in cyto) #define TAUU 1000 // ### unbinding time constant, in us (1000 for Tar-aspartate, 45000 for Tar-CheR) #define AVALUE 0.476 // ### a value, in nm (1.0 default, 0.264 aspartate, 0.0019 CheR) #define BVALUE 4.756 // ### b value, in nm (3.0 default, 0.528 aspartate, 0.19 CheR) #define DXMIN (AVALUE/100.0) // ### minimum rms step length, in nm #define SPHRAD 750.0 // ### radius of sphere, in nm (750 for E coli) #define NRECEPT 3000 // ### number of receptors (3000 for E coli) #define CLUSTERED 1 // &&& flag for clustered receptors (1) vs. unclustered (0) #define CLRAD 225.0 // ### radius of cluster by arc length (225 default); only used if clustered #define ESCAPE (SPHRAD*1000.0) // ### escape radius #define RANDTABLEMAX 4095 // ### size of random number table minus 1 float GAUSS[RANDTABLEMAX+1]; // table of random numbers void diffuse(double *x,double dx); double spherelatticedist(double *xptr,double *yptr,double *zptr,int n,double rad); double spherelatticedist2(double *xptr,double *yptr,double *zptr,int n,double rad,double latmin); void spherelatticepts(int n,double rad,double latmin,FILE *fptr); void spherelatticerows(int n,double rad,double latmin,FILE *fptr); double dist2recept(double x[3],double xr[3]); double dist2surf(double x[3]); void reflectsurface(double x[3]); void move2unbind(double x[3]); int diffuse2bind(double x[3],double *tptr); void geminatebind(void); void initialsite(void); void allsites(void); void radcorrfn(void); void radcorrall(void); void barfigure(void); void bindrate(void); void equilibrium(void); void outputrecept(void); void teststuff(void); /* ********************* GENERAL PURPOSE ROUTINES *********************** */ /* diffuse carries out 3-D diffusion on vector x, using rms step length dx. */ void diffuse(double *x,double dx) { x[0]+=dx*GAUSS[rand()&RANDTABLEMAX]; x[1]+=dx*GAUSS[rand()&RANDTABLEMAX]; x[2]+=dx*GAUSS[rand()&RANDTABLEMAX]; return; } /* spherelatticedist returns the distance to the nearest lattice site that is on the surface of a sphere. The sphere is centered about the origin and has radius rad. The lattice on the surface has about n points, although there is some variation due to discretization effects. Send in the current position in xptr, yptr, and zptr. These are returned with the location of the nearest lattice site. The value returned by the function is the distance to that point. Lattice sites are arranged in rows along equally spaced latitudes. The lattice is square near the equator and prime meridian for n large, and is non-square elsewhere. */ double spherelatticedist(double *xptr,double *yptr,double *zptr,int n,double rad) { double x,y,z,r,lat,phi; double deltalat,lat2,deltaphi,phi2; int latn,phin,lati; x=*xptr; y=*yptr; z=*zptr; r=sqrt(x*x+y*y+z*z); lat=(r==0)?0:asin(z/r); phi=atan2(y,x); latn=floor(sqrt(PI*n)/2.0+0.5); // number of rows deltalat=PI/latn; // spacing of rows if(latn%2) { lati=floor(lat/deltalat+0.5); // row number if(lati>latn/2) lati=latn/2; else if(lati<-latn/2) lati=-latn/2; lat2=lati*deltalat; } else { lati=floor(lat/deltalat); if(lati>=latn/2) lati=latn/2-1; else if(lati<-latn/2) lati=-latn/2; lat2=(lati+0.5)*deltalat; } phin=floor(sqrt(n*PI)*cos(lat2)+0.5); // number of points on row deltaphi=2*PI/phin; // spacing along row phi2=floor(phi/deltaphi+0.5)*deltaphi; // long of point *xptr=rad*cos(lat2)*cos(phi2); *yptr=rad*cos(lat2)*sin(phi2); *zptr=rad*sin(lat2); return sqrt((x-*xptr)*(x-*xptr)+(y-*yptr)*(y-*yptr)+(z-*zptr)*(z-*zptr)); } /* spherelatticedist2 returns the distance to the nearest lattice site that is on the surface of a sphere and that is "north" of the latitute latmin. The sphere is centered about the origin and has radius rad. The lattice within the patch above latmin has about n points, although there is some variation due to discretization effects. Send in the current position in xptr, yptr, and zptr. These are returned with the location of the nearest lattice site. The value returned by the function is the distance to that point in a straight line distance. Lattice sites are arranged in rows along equally spaced latitudes. The lattice is square near the equator and prime meridian for n large, and is non-square elsewhere. */ double spherelatticedist2(double *xptr,double *yptr,double *zptr,int n,double rad,double latmin) { double x,y,z,r,lat,phi,f; double deltalat,lat2,deltaphi,phi2; int latn,phin,lati; x=*xptr; y=*yptr; z=*zptr; r=sqrt(x*x+y*y+z*z); lat=(r==0)?0:asin(z/r); phi=atan2(y,x); f=(1.0-sin(latmin))/2.0; latn=floor(sqrt(PI*n/f)/2.0+0.5); // number of rows deltalat=PI/latn; // spacing of rows if(latlatn/2) lati=latn/2; else if(lati<-latn/2) lati=-latn/2; lat2=lati*deltalat; } else { lati=floor(lat/deltalat); if(lati>=latn/2) lati=latn/2-1; else if(lati<-latn/2) lati=-latn/2; lat2=(lati+0.5)*deltalat; } phin=floor(sqrt(n/f*PI)*cos(lat2)+0.5); // number of points on row deltaphi=2*PI/phin; // spacing along row phi2=floor(phi/deltaphi+0.5)*deltaphi; // long of point *xptr=rad*cos(lat2)*cos(phi2); *yptr=rad*cos(lat2)*sin(phi2); *zptr=rad*sin(lat2); return sqrt((x-*xptr)*(x-*xptr)+(y-*yptr)*(y-*yptr)+(z-*zptr)*(z-*zptr)); } /* spherelattticepts lists all points for a lattice on a sphere. As usual, n is the approximate number of points, rad is the sphere radius, and latmin is the minimum latitude on the sphere where there are points. fptr is the file stream for the output. These points exactly correspond to those of the other routines. */ void spherelatticepts(int n,double rad,double latmin,FILE *fptr) { int latn,lati,phin,phii,npts; double f,deltalat,lat2,deltaphi,phi2,x,y,z; npts=0; f=(1.0-sin(latmin))/2.0; latn=floor(sqrt(PI*n/f)/2.0+0.5); // number of rows deltalat=PI/latn; // spacing of rows if(latn%2) { lati=floor(latmin/deltalat+0.5); if(lati>latn/2) lati=latn/2; else if(lati<-latn/2) lati=-latn/2; } else { lati=floor(latmin/deltalat); if(lati>=latn/2) lati=latn/2-1; else if(lati<-latn/2) lati=-latn/2; } for(;lati<=((latn%2)?latn/2:latn/2-1);lati++) { lat2=(latn%2)?lati*deltalat:(lati+0.5)*deltalat; phin=floor(sqrt(n/f*PI)*cos(lat2)+0.5); // number of points on row deltaphi=2*PI/phin; // spacing along row for(phii=0;phiilatn/2) lati=latn/2; else if(lati<-latn/2) lati=-latn/2; } else { lati=floor(latmin/deltalat); if(lati>=latn/2) lati=latn/2-1; else if(lati<-latn/2) lati=-latn/2; } printf("lat phin deltaphi phisp\n"); for(;lati<=((latn%2)?latn/2:latn/2-1);lati++) { lat2=(latn%2)?lati*deltalat:(lati+0.5)*deltalat; phin=floor(sqrt(n/f*PI)*cos(lat2)+0.5); // number of points on row deltaphi=2*PI/phin; // spacing along row if(fptr) fprintf(fptr,"%lf %i\n",lat2,phin); else printf("%lf %i %lf %lf\n",lat2,phin,deltaphi,deltaphi*rad*cos(lat2)); npts+=phin; } printf("latmin=%lf f=%lf\n",latmin,f); printf("latn=%i deltalat=%lf latsp=%lf\n",latn,deltalat,rad*deltalat); printf("n: %i\n",npts); return; } /* ****************** ROUTINES SPECIFIC TO THIS PROGRAM ***************** */ /* Returns distance to nearest receptor and, in xr, the position of that receptor. To speed this routine up, enter the position of the previous closest receptor in xr and if it is still probably the closest one, then the receptor isn't identified again. */ double dist2recept(double x[3],double xr[3]) { double r,f,deltalat; int latn; static double rmin=0; if(rmin==0) { if(CLUSTERED) f=(1.0-sin(PI/2.0-CLRAD/SPHRAD))/2.0; else f=1.0; latn=floor(sqrt(PI*NRECEPT/f)/2.0+0.5); // number of rows deltalat=PI/latn; // spacing of rows rmin=SPHRAD*deltalat*2.0/3.0; } r=sqrt((x[0]-xr[0])*(x[0]-xr[0])+(x[1]-xr[1])*(x[1]-xr[1])+(x[2]-xr[2])*(x[2]-xr[2])); if(rESCAPE) escape=1; dx=0.1*(1.0-0.9*SPHRAD/d2m)*d2m; if(d2rxhi) x[0]=xlo+(x[0]-xhi); else if(x[1]yhi) x[1]=ylo+(x[1]-yhi); else if(x[2]zhi) x[2]=zlo+(x[2]-zhi); dx=0.1*(1.0-0.9*SPHRAD/d2m)*d2m; if(d2r=tmax) printf("bindings, time, time on / time off: %i %f %f / %f = %f\n",it,t,tont,t-tont,tont/(t-tont)); } return; } /* finds initial binding sites of ligands that start far away. Runtime is 10 minutes for itmax=10000. */ void initialsite(void) { double x[3],t; // location of ligand, time int itmax=10000; // ### number of iterations int it,bind; // iteration, bind flag FILE *fptr; fptr=fopen("initsite","w"); t=0; for(it=0;it1&&x[0]==xo[0]&&x[1]==xo[1]&&x[2]==xo[2]; fprintf(fptr,"%i %i %lf\n",sum==1,gem,SPHRAD*asin(sqrt(x[0]*x[0]+x[1]*x[1])/SPHRAD)); xo[0]=x[0];xo[1]=x[1];xo[2]=x[2]; move2unbind(x); it++; } else sum=0; } fclose(fptr); return; } /* finds binding sites of ligand that start at the center. Runtime is 43 seconds for itmax=10000. */ void radcorrfn(void) { double x[3],xo[3],t,th; // location of ligand, time int itmax=10000; // ### number of iterations int it,bind,esc; // iteration, bind flag FILE *fptr; fptr=fopen("radcorrfn","w"); t=0; esc=0; for(it=0;ittmax) t=tmax; fprintf(fptr,"%f inch %f inch lineto\n",0.5+t*sf,5.0-0.1*row); to=t; bind=diffuse2bind(x,&t); } fprintf(fptr,"stroke\n"); row++; }} fprintf(fptr,"showpage\n"); return; } /* Execution time is 85 s for itmax=1000, clustered, all bindings; 25 s for itmax=1000, unclustered, all bindings, 1377 s for itmax=20000, clustered, first binding. */ void bindrate(void) { double x[3],t; double tmax=10000000; const int itmax=20000; const int nhist=200; double hist[nhist],delta; double lo=-6,hi=7; int j,it,bind; FILE *fptr; delta=(hi-lo)/(nhist-1); for(j=0;j=nhist) j=nhist-1; hist[j]+=1.0/itmax; }}} fptr=fopen("bindrate","w"); for(it=0;it