File S2. R code used for statistical analyses ################################################################################ Import the data ################################################################################ df <- read.table("data_set.txt",header=TRUE,sep='\t') sapply(df,class) source=read.table("source.txt",header=TRUE,sep='\t') sourceC=cbind(source$x-mean(source$x),source$y-mean(source$y)) sourceP=cart2rad(sourceC) coordC=cbind(df$x-mean(source$x),df$y-mean(source$y)) coordP=cart2rad(coordC) nles=df$tnl nlesSub=df$gnl nlesEndo=df$gnrl area=df$surface ################################################################################ Functions needed ################################################################################ library(CircStats) ## Cartesian to Polar coordinates cart2rad=function(x){ phi=atan(x[,2]/x[,1]) phi[sign(x[,1])<0]=pi+phi[sign(x[,1])<0] cbind(sqrt(x[,1]^2+x[,2]^2),phi) } rad2cart=function(rad) cbind(rad[,1]*cos(rad[,2]),rad[,1]*sin(rad[,2])) ## Exponential kernel Sexp=function(par,rho,phi) sapply(1:length(rho),function(i) exp(par[1])*dvm(phi[i],par[2],exp(par[3]))/ (exp(par[4])*dvm(phi[i],par[5],exp(par[6])))^2* exp(-rho[i]/(exp(par[4])*dvm(phi[i],par[5],exp(par[6]))))) ## Geometric Kernel Sgeo=function(par,rho,phi){ b=2+exp(par[7]) sapply(1:length(rho), function(i) exp(par[1])*dvm(phi[i],par[2],exp(par[3]))* (b-1)*(b-2)/(exp(par[4])*dvm(phi[i],par[5],exp(par[6])))^2/ (1+rho[i]/(exp(par[4])*dvm(phi[i],par[5],exp(par[6]))))^b) } ## Power Exponential Kernel Sexpp=function(par,rho,phi){ b=exp(par[7]) sapply(1:length(rho), function(i) exp(par[1])*dvm(phi[i],par[2],exp(par[3])) / (exp(par[4])*dvm(phi[i],par[5],exp(par[6])))^2* (b/gamma(2/b))* exp(-(rho[i]/(exp(par[4])*dvm(phi[i],par[5],exp(par[6]))))^b)) } ## Wald Kernel Swald=function(par,rho,phi){ b=exp(par[7]) sapply(1:length(rho), function(i) exp(par[1])*dvm(phi[i],par[2],exp(par[3])) * sqrt( b / (2*pi*rho^5) ) * exp( -b* (rho-exp(par[4])*dvm(phi[i],par[5],exp(par[6])))^2 / ( 2 * (exp(par[4])*dvm(phi[i],par[5],exp(par[6])))^2 * rho ))) } ## Infectious potential: SMulti=function(par,sourceC,coordC){ out=0 for(i in 1:nrow(sourceC)){ z=cart2rad(t(t(coordC)-sourceC[i,])) out=out+S(par,z[,1],z[,2]) } out } ## Maximum likelihood fitMulti=function(par,sourceC,coordCartesian,area, nlesion,nlesionSub,nlesionEndo){ negloglik=function(par) -LMulti(par,sourceC,coordCartesian,area,nlesion,nlesionSub,nlesionEndo) ui=matrix(0,4,length(par)) ui[1,2]=1 ; ui[2,5]=1 ; ui[3,2]=-1 ; ui[4,5]=-1 res=constrOptim(par,negloglik,ui=ui,ci=c(-10*pi,-10*pi,-10*pi,-10*pi), method="Nelder-Mead",control=list(trace=10)) list(estimate=res$par,loglik=-res$value) } ################################################################################ Poisson model fit including hypergeometric distibution for sampling ################################################################################ LMulti=function(par,sourceC,coordC,area,nlesion,nlesionSub,nlesionEndo){ mu=SMulti(par,sourceC,coordC)*area f=function(nLes,nSub,nEndo,mui){ sum(dhyper(nEndo,0:nLes,nLes:0,nSub)*dpois(0:nLes,mui)) } ll=sum(log(apply(cbind(nlesion,nlesionSub,nlesionEndo,mu),1, function(u) f(u[1],u[2],u[3],u[4])))) ll } # Fix the dispersal kernel chosen: # S= (Sexp, Sgeo, Sexpp, Swald) # Fix the initial parameters for likelihood estimation: para=c(log(10^6), 0, log(0.5), log(10^3), 0, log(0.5)) # Estimate likelihood oo=fitMulti(para,sourceC,coordC,area,nles,nlesSub,nlesEndo) ################################################################################ Negative binomial model fit including hypergeometric distibution for sampling ################################################################################ LMulti=function(par,sourceC,coordC,area,nlesion,nlesionSub,nlesionEndo){ n=length(par) mu=SMulti(par[-n],sourceC,coordC)*area f=function(nLes,nSub,nEndo,mu){ sum(dhyper(nEndo,0:nLes,nLes:0,nSub)* dnbinom(0:nLes,size=exp(par[n]),mu=mui)) } sum(log(apply(cbind(nlesion,nlesionSub,nlesionEndo,mu),1, function(u) f(u[1],u[2],u[3],u[4])))) } # Fix the dispersal kernel chosen: # S= (Sexp, Sgeo, Sexpp, Swald) # Estimate likelihood para=c(oo$estimate,log(50)) oo2=fitMulti(para,sourceC,coordC,area,nles,nlesSub,nlesEndo) ################################################################################ Bootstrap to calculate confidence intervals for kernel parameters ################################################################################ S =Sexpp ## choose the kernel para=oo2$estimate paraboot=NULL for(i in 1:1000){ temp=sample(1:length(nles),length(nles),replace=TRUE) qq2star=fitMulti(para,sourceC,coordC[temp,],area[temp],nles[temp], nlesSub[temp],nlesEndo[temp]) paraboot=rbind(paraboot,qq2star$estimate) } # for parameters in log scale apply(paraboot,2,quantile,c(0.025,0.975)) # for parameters in natural scale apply(exp(paraboot),2,quantile,c(0.025,0.975)) ################################################################################ Average distance and standard deviation (sigma) calculation using the exponential power kernel ################################################################################ EDISTexpp.cond=function(par,angle1,angle2,distmax){ b=exp(par[7]) f=function(phi) dvm(phi,par[2],exp(par[3])) g=function(phi) exp(par[4])*dvm(phi,par[5],exp(par[6])) integrande=function(phi,rho){ rho^2*f(phi)*b/g(phi)^2/gamma(2/b)*exp(-(rho/g(phi))^b) } integrande.sq=function(phi,rho){ rho^3*f(phi)*b/g(phi)^2/gamma(2/b)*exp(-(rho/g(phi))^b) } integrande.denom=function(phi,rho){ rho*f(phi)*b/g(phi)^2/gamma(2/b)*exp(-(rho/g(phi))^b) } integrande2=function(phi){ integrate(function(rho) integrande(phi,rho),0,distmax)$value } integrande2.sq=function(phi){ integrate(function(rho) integrande.sq(phi,rho),0,distmax)$value } integrande2.denom=function(phi){ integrate(function(rho) integrande.denom(phi,rho),0,distmax)$value } n=100 seqphi=seq(angle1,angle2,l=n+1) seqphi=seqphi[-1]+(seqphi[2]-seqphi[1])/2 values=NULL values.sq=NULL values.denom=NULL for(phi in seqphi){ values=c(values,integrande2(phi)) values.sq=c(values.sq,integrande2.sq(phi)) values.denom=c(values.denom,integrande2.denom(phi)) } ER=sum(values*(angle2-angle1)/n)/sum(values.denom*(angle2-angle1)/n) ER2=sum(values.sq*(angle2-angle1)/n)/sum(values.denom*(angle2-angle1)/n) c(ER,sqrt(ER2-ER^2)) } ## sigma calculation SIGMA1expp.cond=function(par,angle1,angle2,distmax){ b=exp(par[7]) f=function(phi) dvm(phi,par[2],exp(par[3])) g=function(phi) exp(par[4])*dvm(phi,par[5],exp(par[6])) integrande=function(phi,rho){ rho^2*f(phi)*b/g(phi)^2/gamma(2/b)*exp(-(rho/g(phi))^b) } integrande.sq=function(phi,rho){ rho^3*f(phi)*b/g(phi)^2/gamma(2/b)*exp(-(rho/g(phi))^b) } integrande.denom=function(phi,rho){ rho*f(phi)*b/g(phi)^2/gamma(2/b)*exp(-(rho/g(phi))^b) } integrande2=function(phi){ integrate(function(rho) integrande(phi,rho),0,distmax)$value } integrande2.sq=function(phi){ integrate(function(rho) integrande.sq(phi,rho),0,distmax)$value } integrande2.denom=function(phi){ integrate(function(rho) integrande.denom(phi,rho),0,distmax)$value } n=100 seqphi=seq(angle1,angle2,l=n+1)[-1] values=NULL values.sq=NULL values.denom=NULL for(phi in seqphi){ values=c(values,integrande2(phi)) values.sq=c(values.sq,integrande2.sq(phi)) values.denom=c(values.denom,integrande2.denom(phi)) } ER=sum(values*(angle2-angle1)/n)/sum(values.denom*(angle2-angle1)/n) ER2=sum(values.sq*(angle2-angle1)/n)/sum(values.denom*(angle2-angle1)/n) seqphi=seqphi+pi values=NULL values.sq=NULL values.denom=NULL for(phi in seqphi){ values=c(values,integrande2(phi)) values.sq=c(values.sq,integrande2.sq(phi)) values.denom=c(values.denom,integrande2.denom(phi)) } ERoppose=sum(values*(angle2-angle1)/n)/sum(values.denom*(angle2-angle1)/n) ER2oppose=sum(values.sq*(angle2-angle1)/n)/sum(values.denom*(angle2-angle1)/n) ED=ER-ERoppose ED2=ER2+ER2oppose c(ED,sqrt(ED2-ED^2)) } SIGMA2expp.cond=function(par,angle,distmax){ b=exp(par[7]) f=function(phi) dvm(phi,par[2],exp(par[3])) g=function(phi) exp(par[4])*dvm(phi,par[5],exp(par[6])) integrande=function(phi,rho){ rho^2*cos(phi-angle)*f(phi)*b/g(phi)^2/gamma(2/b)*exp(-(rho/g(phi))^b) } integrande.sq=function(phi,rho){ rho^3*cos(phi-angle)^2*f(phi)*b/g(phi)^2/gamma(2/b)*exp(-(rho/g(phi))^b) } integrande.denom=function(phi,rho){ rho*f(phi)*b/g(phi)^2/gamma(2/b)*exp(-(rho/g(phi))^b) } integrande2=function(phi){ integrate(function(rho) integrande(phi,rho),0,distmax)$value } integrande2.sq=function(phi){ integrate(function(rho) integrande.sq(phi,rho),0,distmax)$value } integrande2.denom=function(phi){ integrate(function(rho) integrande.denom(phi,rho),0,distmax)$value } n=100 angle1=0 angle2=2*pi seqphi=seq(angle1,angle2,l=n+1) seqphi=seqphi[-1]+(seqphi[2]-seqphi[1])/2 values=NULL values.sq=NULL values.denom=NULL for(phi in seqphi){ values=c(values,integrande2(phi)) values.sq=c(values.sq,integrande2.sq(phi)) values.denom=c(values.denom,integrande2.denom(phi)) } EXa=sum(values*(angle2-angle1)/n)/sum(values.denom*(angle2-angle1)/n) EXa2=sum(values.sq*(angle2-angle1)/n)/sum(values.denom*(angle2-angle1)/n) c(EXa,sqrt(EXa2-EXa^2)) }