# Citation: Sanchez, J.N. and B.R. Hudgens. Impacts of Heterogeneous Host Densities and Contact Rates on Pathogen Transmission in the Channel Island Fox (Urocyon littoralis). Biological Conservation. 2019. # Jessica N. Sanchez # jnsanchez@ucdavis.edu # Institute for Wildlife Studies # P.O. Box 1104 # Arcata, CA 95518 # Brian R. Hudgens # hudgens@iws.org # Institute for Wildlife Studies # P.O. Box 1104 # Arcata, CA 95518 ########################## RABIES ########################## #VARIABLES - PERMANENT VECTORS WITHIN EACH RUN #sim = number of simulations to run #target.N = number of homes to attempt to generate #N = number of home ranges actually generated #X = size of island x axis #Y = size of island y axis #fox = fox ID number #x = fox x coordinate #y = fox y coordinate #radius = radius of fox circular home range #HR.area = area of fox home range #habitat = habitat type of fox based on y coordinate #time = number of time-steps #resample.N = number of simulations to run between resampling home ranges #summary.density = density of foxes in each habitat type during each simulation #transmission.probability = probability of pathogen transmission given contact between S and I fox #potential.seeds = all foxes with min/max y values #seed = random sample of foxes in potential.seeds #new.latents = number of new latent animals at each time-step #infectives = which foxes are infectious at time t-1? #random.sample = random numbers to compare against transmission probabilities #total.0 = sum of all susceptible foxes at each time-step #total.1 = sum of all infectious foxes at each time-step #total.2 = sum of all latent foxes at each time-step #total.3 = sum of all removed foxes at each time-step #total.4 = sum of all vaccinated foxes at each time-step #status.totals.at.end = sum of all foxes in each disease class at last time-step #summary.total.0 = number of suceptible foxes at each time step in each simulation #summary.total.1 = number of latent foxes at each time step in each simulation #summary.total.2 = number of infectious foxes at each time step in each simulation #summary.total.3 = number of removed foxes at each time step in each simulation #summary.total.4 = number of vaccinated foxes at each time step in each simulation #summary.total.i = mean number of susceptible foxes at each time-step (averaged across simulations) #total.0.means = mean number of susceptible foxes at each time-step (averaged across simulations) #total.1.means = mean number of latent foxes at each time-step (averaged across simulations) #total.2.means = mean number of infectious foxes at each time-step (averaged across simulations) #total.3.means = mean number of removed foxes at each time-step (averaged across simulations) #total.4.means = mean number of vaccinated foxes at each time-step (averaged across simulations) #total.i.means = mean number of infected foxes at each time-step (averaged across simulations) #Rs = Re at each time-step #Ro = number of secondary infections caused by seed fox in each simulation #spread = distance between seed fox and furthest infected fox (I or L) at each time-step #latent.period = expected latent period of latent fox #infectious.period = expected life span of infected fox #percent = % of N that must be Removed for time-step to be returned #percent.dead = number of foxes that must be Removed for time-step to be returned #vacc = random sample of foxes assigned to be vaccinated foxes #MATRICES - PERMANENT WITHIN EACH RUN #overlap.area = area of overlap between foxes i and j (N x N) #minta = minta value for foxes i and j (N x N) #B = infection probablity = contact*transmission.probability #status = status of all foxes from time t=0 to t=time (N x time) #VARIABLES - TEMPORARY (MOSTLY IN LOOPS) #need.new = do we need to sample a new xy? #trial = limit of attempts to sample new fox #reject = for weighting y sampling #keep = for weighting y sampling #minta.too.big = is minta < 0.75? #d = distance between home range centers #r = minimum radius #R = maximum radius #theta1 = angle of smaller circle #theta2 = angle of larger circle #outside = area of small circle outside the larger circle when (R-r)0){ ## ## Re-set all variables at start of each simulation ## #Set fox population size N<-target.N fox<-c() x<-c() y<-c() radius<-c() HR.area<-c() habitat<-c() overlap.area<-matrix(data=NA,nrow=N,ncol=N) minta<-matrix(data=NA,nrow=N,ncol=N) B<-matrix(data=NA,nrow=N,ncol=N) new.latents<-c() fox.home.ranges<-c() #Select first home range fox<-1 x[1]<-sample(0:X,1) y[1]<-sample(0:Y,1) radius[1]<-generate.radius(y[1]) HR.area[1]<-pi*(radius[1]^2) habitat[1]<-habitat.function(y[1]) #Loop to create home ranges one by one, checking the distance btwn them as you go. for (i in 2:N) { #Fill vectors for x,y,r need.new<-1 trial<-0 fox[i]<-i while (need.new==1) { x[i]<-sample(0:X,1) y[i]<-sample(0:Y,1) reject<-reject.function(y[i]) keep<-(sample(0:100,1)/100) while (keep>=reject){ x[i]<-sample(0:X,1) y[i]<-sample(0:Y,1) reject<-reject.function(y[i]) keep<-(sample(0:100,1)/100) } #end while statement on keep=(r+R)) overlap.area[i,j]<-0 else #If the smaller circle is >0.5 inside the larger, calculate the area if ((R-r)0.75){ #exit the j loop once we have one distance greater than threshold minta.too.big<-1 break } else{ #Assign value to other half of minta matrix minta[j,i]<-minta[i,j] #Assign value to transmission matrix. (contact*probability of infection) B[i,j]<-(daily.contact.rate(minta[i,j])*transmission.probability) if (B[i,j]>1) B[i,j]<-1 if (B[i,j]<0) B[i,j]<-0 B[j,i]<-B[i,j] } #End else statment on minta check } #End j loop #If none of the mintas were too big, and no centers are the same, we don't need to re-sample a new location if (minta.too.big==0) need.new<-0 #If trial = 400, island is full and we don't need a new location if (trial==400) break } #end of while statement if (trial==400) break } #end of i loop #Update vectors/matrices according to new N value if (trial==400) { fox<-fox[1:(length(x)-1)] x<-x[1:(length(x)-1)] y<-y[1:(length(y)-1)] radius<-radius[1:(length(radius)-1)] HR.area<-HR.area[1:(length(HR.area)-1)] habitat<-habitat[1:(length(habitat)-1)] overlap.area<-overlap.area[1:(length(fox)),1:(length(fox))] minta<-minta[1:(length(fox)),1:(length(fox))] B<-B[1:(length(fox)),1:(length(fox))] } N<-length(fox) percent.dead<-round(percent*N) #Update end population matrix summary.N[s:(s+9)]<-N #Update summary.density matrix summary.density[1,s:(s+9)]<-sum(habitat=="dunes")/(0.1*X*Y/1000000) summary.density[2,s:(s+9)]<-sum(habitat=="MDS.rugged")/(0.3*X*Y/1000000) summary.density[3,s:(s+9)]<-sum(habitat=="MDS.gentle")/(0.3*X*Y/1000000) summary.density[4,s:(s+9)]<-sum(habitat=="grass")/(0.3*X*Y/1000000) } #End of if statement to resample foxes and home ranges ####################### Seed Disease and Loop Time ############################# #Disease classes: #Susceptible = 0 #Latent = 1 #Infectious = 2 #Removed = 3 #Vaccinated = 4 #Create empty matrix of dimensions N by T status<-matrix(nrow=N,ncol=time) #All foxes susceptible at time = 1 status[,1]<-0 #Vaccinate foxes - not done in this version of the model #Seed disease at max or min y value # Use maximum value for high density introduction = potential.seeds<-c(which(y==max(y)),which(y>(Y-300))) # Use minimum value for low density introduction = potential.seeds<-c(which(y==min(y)),which(y<300)) potential.seeds<-c(which(y==max(y)),which(y>(Y-300))) if (length(potential.seeds)==1) seed<-potential.seeds else seed<-sample(potential.seeds,1) status[seed,1]<-2 new.latents<-c() new.latents[1]<-0 #Loop time for (t in 2:time) { new.latents[t]<-0 for (i in 1:N) { #If a fox is Removed if (status[i,(t-1)]==3) status[i,t]<-3 else #If a fox is Vaccinated if (status[i,(t-1)]==4) status[i,t]<-4 else #If a fox is Latent if (status[i,(t-1)]==1) { #Average latent period of 42 days, mortality rate = 1/42, cut off at 90 days if (t==(latent.cut.off+1) && status[i,(t-latent.cut.off)]==1) status[i,t]<-2 else {if (runif(1,min=0,max=1)<=(latent.period)) status[i,t]<-2 else{ status[i,t]<-1} } } #End if statement on latent fox i else #If a fox is Infectious if (status[i,(t-1)]==2) { #Average life span of 4 days, mortality rate = 1/4, cut off at 14 days if (t==(infectious.cut.off+1) && status[i,(t-infectious.cut.off)]==2) status[i,t]<-3 else{ if (runif(1,min=0,max=1)<=(infectious.period)) status[i,t]<-3 else{ status[i,t]<-2 if (i==seed) Ro[s]<-Ro[s]+1} } } #End if statement for infectious fox i else #If a fox is Susceptible, check the status of it's neighbors if (status[i,(t-1)]==0){ #Which foxes are infectious at time t-1? infectives<-which(status[,t-1]==2) random.sample<-runif(length(infectives),min=0,max=1) #Infection occurs through contact with neighbors or background transmission rate if (sum(random.sample<=B[i,infectives],na.rm=TRUE)>0 | runif(1,min=0,max=1)<(1-(1-0.000001)^length(infectives))){ status[i,t]<-1 new.latents[t]<-new.latents[t]+1 } #End if statement on infection else status[i,t]<-0 } #End of if statement on susceptible fox i } #End i loop } #End t loop ####################### Calculate Output Variables ############################# ## ##Population size ## summary.N[s]<-N ## ##Seed location ## summary.seed[s,1]<-x[seed] summary.seed[s,2]<-y[seed] ## ##Number of foxes in each stage at each time step ## total.0<-colSums(status==0,na.rm=FALSE,dims=1) total.1<-colSums(status==1,na.rm=FALSE,dims=1) total.2<-colSums(status==2,na.rm=FALSE,dims=1) total.3<-colSums(status==3,na.rm=FALSE,dims=1) total.4<-colSums(status==4,na.rm=FALSE,dims=1) #total.0 = number of latent foxes at each time step in each simulation summary.total.0[,s]<-total.0 total.0.means<-apply(summary.total.0,1,mean) #total.1 = number of latent foxes at each time step in each simulation summary.total.1[,s]<-total.1 total.1.means<-apply(summary.total.1,1,mean) #total.2 = number of infectious foxes at each time step in each simulation summary.total.2[,s]<-total.2 total.2.means<-apply(summary.total.2,1,mean) #total.3 = number of removed foxes at each time step in each simulation summary.total.3[,s]<-total.3 total.3.means<-apply(summary.total.3,1,mean) #total.4 = number of vaccinated foxes at each time step in each simulation summary.total.4[,s]<-total.4 total.4.means<-apply(summary.total.4,1,mean) #total.i = number of infected foxes at each time step in each simulation summary.total.i<-summary.total.1+summary.total.2 total.i.means<-apply(summary.total.i,1,mean) ## ##Number of foxes in each stage at the end of every simulation ## status.totals.at.end<-rbind(total.0,total.1,total.2,total.3,total.4) summary.status.totals.at.end[,s]<-status.totals.at.end[,time] ## ##Re.time ## Rs<-c() Re.time<-c() for (t in 2:time) { new<-(new.latents[t]/total.2[t-1]) if (new=="-Inf" | new=="Inf" | new=="NA" | new=="NaN" | new<0) Rs[t]<-0 else Rs[t]<-new } summary.Re[s]<-mean(Rs,na.rm=TRUE) Re.time<-mean(summary.Re) ## ##Calculate distance of spread after each day ## spread<-c() for (t in 1:time) { if (t==1) spread[t]<-0 else{ d<-c() for (i in 1:N) { if (i==seed) d[i]<-0 if (status[i,t]==0 | status[i,t]==4 ) next else{ #Distace between home range centers d[i]<-distance(x[seed],y[seed],x[i],y[i]) } #End else statement } #End i loop spread[t]<-max(d,na.rm=TRUE) } #End if statement } #End t loop summary.spread[,s]<-spread ## ##Calculate how many time-steps until a certain % of foxes are dead, and the # Infectious and Latent foxes at that time-step ## if (length(which(total.3>=percent.dead)>0)){ summary.time.at.percent.dead[s]<-min(which(total.3>=percent.dead)) summary.infectious.at.percent.dead[s]<-total.2[summary.time.at.percent.dead[s]] summary.latent.at.percent.dead[s]<-total.1[summary.time.at.percent.dead[s]] } else { summary.time.at.percent.dead[s]<-NA summary.infectious.at.percent.dead[s]<-NA summary.latent.at.percent.dead[s]<-NA } #End else statment } #End sim loop ## ## Percent of original S in each status class at t=365 ## #Percent Suceptible at t=365 percent.S.mean<-mean((summary.total.0[365,]/(summary.N-summary.total.4[1,]))) #Percent Latent at t=365 percent.L.mean<-mean((summary.total.1[365,]/(summary.N-summary.total.4[1,]))) #Percent Infectious at t=365 percent.I.mean<-mean((summary.total.2[365,]/(summary.N-summary.total.4[1,]))) #Percent Removed at t=365 percent.R.mean<-mean((summary.total.3[365,]/(summary.N-summary.total.4[1,]))) ## ## Number of simulations with epidemic fadeout ## epidemic.fadeouts<-sum(summary.status.totals.at.end[1,]>0 & summary.status.totals.at.end[2,]==0 & summary.status.totals.at.end[3,]==0,na.rm=TRUE) ## ##Number of simulations with fox extinction ## fox.extinctions<-sum(summary.status.totals.at.end[4,]==(summary.N-summary.total.4[1,])) ## ##Percent Suceptible at t=average.detection.day ## percent.S.at.average.detection.day<-mean(summary.total.0[average.detection.day,]/(summary.N-summary.total.4[1,])) #Percent Latent at t=average.detection.day percent.L.at.average.detection.day<-mean(summary.total.1[average.detection.day,]/(summary.N-summary.total.4[1,])) ## ##Ro ## average.Ro<-mean(Ro) ## ##Re.individuals ## Re.individuals<-mean(((summary.N-summary.total.4[1,])-summary.total.0[365,])/colSums(summary.total.2)) #Save all objects with a detailed file name save(list=ls(all=TRUE),file="SCI_Rabies_VaccNone_IntroHigh_Main.RData") ################################################################################ ############################## END SIMULATION ################################## ################################################################################ rm(list=ls(all=TRUE))