Skip to content

Instantly share code, notes, and snippets.

Created February 4, 2013 21:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anonymous/4709926 to your computer and use it in GitHub Desktop.
Save anonymous/4709926 to your computer and use it in GitHub Desktop.
Code for Trap Simulations using Shiny
#StrategicPestTechnologies: Functions
#~~~~~~~~~~~Calc trap info~~~~~~~~~~~~
trap.info.func<-function(file){
#Take file
#Return: traps, n.traps, ylims, xlims, total.area
traps<-read.table(file, header=FALSE)
colnames(traps)<-c("ID","X","Y")
n.traps<-dim(traps)[1]
xlims<-c(min(traps$X)-buffer,max(traps$X)+buffer)
ylims<-c(min(traps$Y)-buffer,max(traps$Y)+buffer)
total.area<-(diff(xlims)/100)*(diff(ylims)/100)
trap.area<-((max(traps$X)-min(traps$X))/100) *((max(traps$Y)-min(traps$Y))/100)
list(traps=traps, n.traps=n.traps, ylims=ylims, xlims=xlims, total.area=total.area, trap.area=trap.area)
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~Create traps info~~~~~~~~~~~~
trap.make.func<-function(traps.in.x, traps.in.y, trap.space.x, trap.space.y, buffer, start.xy){
#Take: traps.in.x, traps.in.y, trap.space, buffer, start.xy
#Return: traps, n.traps, ylims, xlims, total.area
x.t<-seq(from=start.xy[1], by=trap.space.x, length.out=traps.in.x)
y.t<-seq(from=start.xy[2], by=trap.space.y, length.out=traps.in.y)
xy<-expand.grid(x.t,y.t)
ID<-1:length(xy[,1])
traps<-cbind(ID,xy)
colnames(traps)<-c("ID","X","Y")
n.traps<-dim(traps)[1]
xlims<-c(min(traps$X)-buffer,max(traps$X)+buffer)
ylims<-c(min(traps$Y)-buffer,max(traps$Y)+buffer)
total.area<-(diff(xlims)/100)*(diff(ylims)/100)
trap.area<-((max(traps$X)-min(traps$X))/100) *((max(traps$Y)-min(traps$Y))/100)
list(traps=traps, n.traps=n.traps, ylims=ylims, xlims=xlims, total.area=total.area, trap.area=trap.area)
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~Place animals on grid~~~~~~~~~~~~
animal.loc.func<-function(xlims, ylims, total.area, density, dist.type="F"){
#Take: xlims, ylims, total.area, density, dist.type,
#Return: animals, n.animals
n.fixed<-round(total.area*density,0)
n.animals<-n.fixed
if(dist.type=="P"){
n.pois<-rpois(1,n.fixed)
n.animals<-n.pois
}
xloc<-runif(n.animals,min=xlims[1],max=xlims[2])
yloc<-runif(n.animals,min=ylims[1],max=ylims[2])
animals<-as.data.frame(cbind(1:n.animals,xloc,yloc))
list(animals=animals, n.animals=n.animals, dist.type=dist.type)
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~Plot distance vs prob from g0 and sigma~~~~~~~~~
plot.g0.sigma<-function(g0,sigma){
#Calculate what the probability of capture will be:
#i.e. P(Cap) = dnorm(distance,sd=sigma)*g0/dnorm(0,sigma)
k<-g0/dnorm(0,sd=sigma)
# X11()
print(plot(c(0:(3*sigma)),dnorm(seq(from=0, by=1, to=(3*sigma)), sd=sigma)*k, type="l", ylim=c(0,min(c(1,max(c(g0+.1,.2))))), xlab="Distance (m)", ylab="Prob of capture"), xaxs="r", yaxs="r")
by.y<-ifelse(g0<.3,.1,.2)
abline(h=seq(from=0, to=1, b=by.y), col="red", lty=2)
abline(v=seq(from=0, by=20, to=(3*sigma)), col="red", lty=2)
abline(h=0)
abline(v=0)
mtext(paste("g0 = ",g0,", sigma = ",sigma, sep=""),3,padj=-1)
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#This runs better than the original as it only calculates the prob when distance < x*Sigma
#~~~~~Calculate distance and probability of capture~~~~~~~~
dist.prob.func<-function(n.animals, animals, n.traps, traps, g0, sigma, max.sd=3){
#For each trap[i], the distance^2 and prob to each animal[j]:
ax2<-(outer(traps$X,animals$xloc,'-'))^2 #Distance in x direction (squared)
ay2<-(outer(traps$Y,animals$yloc,'-'))^2 #Distance in y direction (squared)
dist2.xy<-(ax2+ay2) #Combined
max.dist<-(sigma*max.sd)^2
dist2.xy.tmp<-dist2.xy[dist2.xy<(max.dist)]
# sum(dist2.xy<(max.dist))
prob.xy3<-matrix(0,n.traps,n.animals)
prob.xy3[dist2.xy<(max.dist)]<-g0*exp(-(dist2.xy.tmp)/(2*sigma^2))
prob.xy<-prob.xy3
}
#~~~~~End distance~~~~~~~~~~~~~~
#~~~~Resample function which works when length(x)==1
resamp <- function(x,...){if(length(x)==1) x else sample(x,...)}
#~~~~End resample
#~~~~~Calculate which animals are caught where~~~~~~~~~~
sim.captures.func<-function(n.traps, n.nights, n.animals, max.catch, prob.xy, type="KILL", check="END"){
#type can be KILL or CHEW
#check can be "END" or "DAY" i.e. every day or at the end of the study
#Needs: n.traps, n.nights, n.animals, prob.xy
#Returns: trap.catch, trap.animals
trap.catch<-matrix(0,n.traps,n.nights) #Trap.catch stores the captures in each trap each night
trap.animals<-rep(0,n.animals) #Indicator of whether an animal has been caught
trap.sum<-rep(0,n.traps) #Record the number caught in each trap
trap.rem<-rep(T,n.traps) #Record if the trap remains in operation...TRUE, FALSE
trap.pot.tmp<-rep(FALSE,n.traps)
trap.animal.mat<-matrix(0,n.traps, n.animals) #Record which trap each animal is detected in...
trap.animal.night<-vector("list",n.nights) #Record which trap each animal is detected in each night.
for (t in 1:n.nights){ #For each night
trap.animal.night[[t]]<-matrix(0,n.traps, n.animals)
if (check =="DAY"){ #If checking each day, then this gets reset...
trap.rem<-rep(T,n.traps) #Record if the trap remains in operation...
trap.pot.tmp<-rep(FALSE,n.traps)
}
not.caught<-(1:n.animals)[trap.animals==0] #Animals not already caught
if (type=="CHEW"){
not.caught<-(1:n.animals) #For a chew card, all animals can be redetected...
}
for (j in not.caught){ #For each animal not already caught
prob.tmp<-prob.xy[,j]*(trap.rem) #Adjust the probabilities so previous traps cannot catch anything
prob.gt.0<-prob.tmp>0 #"Probabilities greater than 0"
trap.pot<-trap.pot.tmp
trap.pot[prob.gt.0]<-prob.tmp[prob.gt.0]>runif(sum(prob.gt.0)) #Traps that potentially catch something
#...Only does runif for prob>0
if(sum(trap.pot)>0){ #If at least one trap can catch it...
trap.tmp<-which(trap.pot) #Which traps potentially catch something?
if (type=="KILL"){
trap.i<-resamp(trap.tmp,1) #Sample which trap it is.
trap.catch[trap.i,t]<-trap.catch[trap.i,t]+1 #Set trap.catch to current + 1
trap.sum[trap.i]<-trap.sum[trap.i]+1 #Updates the sum of animals caught in trap (gets rid of rowSums)
trap.animals[j]<-1 #Set trapped animal to 1
}
if (type=="CHEW"){
trap.i<-trap.tmp #Every card gets chewed as possums can eat more than one
trap.catch[trap.i,t]<-trap.catch[trap.i,t]+1 #Set trap.catch to current + 1
trap.sum[trap.i]<-trap.sum[trap.i]+1 #Updates the sum of animals caught in trap (gets rid of rowSums)
trap.animals[j]<-trap.animals[j]+1 #Set trapped animal to 1
trap.animal.mat[trap.i,j]<-trap.animal.mat[trap.i,j]+1
trap.animal.night[[t]][trap.i,j]<-trap.animal.night[[t]][trap.i,j]+1
}
trap.rem<-(trap.sum<max.catch) #Calculate which traps are not full
}
}
}
caught.traps<-(rowSums(trap.catch)>0)*1
list(trap.animals=trap.animals, trap.catch=trap.catch, caught.traps=caught.traps, trap.animal.mat=trap.animal.mat,trap.animal.night=trap.animal.night)
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~Calculate which animals are caught where~~~~~~~~~~
sim.captures.func.month<-function(n.traps, n.months, n.animals, max.catch, prob.xy, type="KILL", check=c(1,2)){
#type can be KILL or CHEW
#check can be "END" or "DAY" i.e. every day or at the end of the study
#Needs: n.traps, n.nights, n.animals, prob.xy
#Returns: trap.catch, trap.animals
n.nights<-n.months*30
n.checks<-(check*30)+1
trap.catch<-matrix(0,n.traps,n.nights) #Trap.catch stores the captures in each trap each night
trap.animals<-rep(0,n.animals) #Indicator of whether an animal has been caught
trap.sum<-rep(0,n.traps) #Record the number caught in each trap
trap.rem<-rep(T,n.traps) #Record if the trap remains in operation...TRUE, FALSE
trap.pot.tmp<-rep(FALSE,n.traps)
trap.animal.mat<-matrix(0,n.traps, n.animals) #Record which trap each animal is detected in...
trap.animal.night<-vector("list",n.nights) #Record which trap each animal is detected in each night.
for (t in 1:n.nights){ #For each night
trap.animal.night[[t]]<-matrix(0,n.traps, n.animals)
if (sum(t==n.checks)>0){ #If checking time, then this gets reset...
trap.rem<-rep(T,n.traps) #Record if the trap remains in operation...
trap.pot.tmp<-rep(FALSE,n.traps)
}
not.caught<-(1:n.animals)[trap.animals==0] #Animals not already caught
for (j in not.caught){ #For each animal not already caught
prob.tmp<-prob.xy[,j]*(trap.rem) #Adjust the probabilities so previous traps cannot catch anything
prob.gt.0<-prob.tmp>0 #"Probabilities greater than 0"
trap.pot<-trap.pot.tmp
trap.pot[prob.gt.0]<-prob.tmp[prob.gt.0]>runif(sum(prob.gt.0)) #Traps that potentially catch something
#...Only does runif for prob>0
if(sum(trap.pot)>0){ #If at least one trap can catch it...
trap.tmp<-which(trap.pot) #Which traps potentially catch something?
if (type=="KILL"){
trap.i<-resamp(trap.tmp,1) #Sample which trap it is.
trap.catch[trap.i,t]<-trap.catch[trap.i,t]+1 #Set trap.catch to current + 1
trap.sum[trap.i]<-trap.sum[trap.i]+1 #Updates the sum of animals caught in trap (gets rid of rowSums)
trap.animals[j]<-1 #Set trapped animal to 1
}
trap.rem<-(trap.sum<max.catch) #Calculate which traps are not full
}
}
}
caught.traps<-(rowSums(trap.catch)>0)*1
list(trap.animals=trap.animals, trap.catch=trap.catch, caught.traps=caught.traps, trap.animal.mat=trap.animal.mat,trap.animal.night=trap.animal.night)
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define server logic required to summarize and view the selected dataset
shinyServer(function(input, output) {
data<-reactive(function(){
#Read in the values from the ui
trap.space.x<-input$trap.space.x
trap.space.y<-input$trap.space.y
traps.in.x<-input$traps.in.x
traps.in.y<-input$traps.in.y
g0<-input$g0
sigma<-input$sigma
max.catch<-input$max.catch
n.nights<-input$n.nights
density<-input$density
start.xy<-c(1000,1000) #Don't need to change this
buffer<-50
dist.type<-input$dist.type
reps<-input$reps
#Call functions
source("pest.tech.functions.R")
dens.vector<-density
d<-1
#Set up matrices to hold the results
n.caught<-rep(NA,reps)
p.caught<-rep(NA,reps)
p.summ<-matrix(NA,length(dens.vector),3)
t.catch<-rep(0,13)
hist.brks<-c(-.5,0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5,11.5,12.5)
pb <- winProgressBar(title = "progress bar", min = 0, max = length(dens.vector)*reps, width = 300)
for(s in 1:reps){
#---------Make the traps from these input parameters above
trap.info<-trap.make.func(traps.in.x, traps.in.y, trap.space.x, trap.space.y, buffer, start.xy)
# print(paste(trap.info$trap.area, "ha"))
xlims<-trap.info$xlims
ylims<-trap.info$ylims
traps<-trap.info$traps
n.traps<-trap.info$n.traps
total.area<-trap.info$total.area
trap.area<-trap.info$trap.area
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#----1. Simulate animal locations.
animal.locs<-animal.loc.func(xlims, ylims, total.area, density, dist.type)
animals<-animal.locs$animals
n.animals<-animal.locs$n.animals
dist.type<-animal.locs$dist.type
#---2. Calculate the distance between each trap/animal and the prob of capture
#Problem here with allocation of memory...fixed with setting sd to 3?
dist.prob<-dist.prob.func(n.animals, animals, n.traps, traps, g0, sigma,3)
prob.xy<-dist.prob #$prob.xy, # dist2.xy<-dist.prob$dist2.xy
#---3. Simulate the captures
#Can also get a problem here with memory allocation
sim.captures<-sim.captures.func(n.traps, n.nights, n.animals,max.catch, prob.xy)
trap.animals<-sim.captures$trap.animals
trap.catch<-sim.captures$trap.catch
caught.traps<-sim.captures$caught.traps
n.caught[s]<-sum(trap.animals)
p.caught[s]<-sum(trap.animals)/n.animals
t.catch<- t.catch+hist(rowSums(trap.catch),hist.brks, plot=FALSE)$counts
#Store histogram of trap catches (after n.nights)
# t.catch[d,]<- t.catch[d,]+hist(rowSums(trap.catch),hist.brks, plot=FALSE)$counts
si<-((d-1)*reps)+s
setWinProgressBar(pb, si, title=paste("Density = ", density, ", Rep =",s," (", round(si/(length(dens.vector)*reps)*100, 0),"% done)"))
}
#The number of animals that each trap catches...
names(t.catch)<-c(0,1,2,3,4,5,6,7,8,9,10,11,12)
t.catch<-t.catch/reps
t.catch<-t.catch[1:(max.catch+1)]
close(pb)
#Summary
data.summary<-as.data.frame(matrix(NA,2,2))
rownames(data.summary)<-c("Animals caught", "Traps with captures")
colnames(data.summary)<-c("Mean", "SD")
data.summary[1,1]<-mean((p.caught))#Proportion of animals caught (number would be n.caught)
data.summary[1,2]<-sd((p.caught))#Proportion of animals caught (number would be n.caught)
# data.summary[2,1]<-sum(caught.traps)/n.traps#Prop of traps with captures
# trap.catch is traps*nights but number of animals per trap
# caught,traps is whether the trap caught anything during the study...
# data.summary<-n.caught
#Return the values...
return(list(animals=animals,traps=traps,xlims=xlims, ylims=ylims, trap.catch=trap.catch, n.animals=n.animals,n.traps=n.traps, total.area=total.area, trap.area=trap.area, g0=g0,sigma=sigma, max.catch=max.catch, n.nights=n.nights, data.summary=data.summary, n.caught=n.caught, p.caught=p.caught, t.catch=t.catch))
# return(list(animals=animals,traps=traps,xlims=xlims, ylims=ylims, n.animals=n.animals,n.traps=n.traps, total.area=total.area, trap.area=trap.area, g0=g0,sigma=sigma, max.catch=max.catch, n.nights=n.nights))
})#End of function....
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
output$main_plot <- reactivePlot(function() {
#~~~~~~~~~~~~~~~~~~~~ Do the plots ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
par(mar=c(4,5,5,1))
par(layout(matrix(c(1,1,2,1,1,3,1,1,4),3,3,byrow=TRUE)))
traps<-data()$traps
pch.trap<-ifelse(data()$max.catch==1,3,8) #
animals<-data()$animals
plot(traps[,2:3], pch=pch.trap, col="red", xlim=data()$xlims, ylim=data()$ylims, asp=1, cex=.6)
points(animals$xloc, animals$yloc, col="blue", pch=20, cex=.8)
mtext(paste("Number of animals = ",data()$n.animals),3, padj=-1, adj=0)
mtext(paste("Number of traps = ",data()$n.traps),3, padj=-2.5, adj=0)
mtext(paste("Total area = ",round(data()$total.area,0),"ha",", Trap area = ",round(data()$trap.area,0),"ha"),3, padj=-4, adj=0)
#~~~~~~~~Plot distance vs prob from g0 and sigma~~~~~~~~~
#Calculate what the probability of capture will be:
#i.e. P(Cap) = dnorm(distance,sd=sigma)*g0/dnorm(0,sigma)
g0<-data()$g0
sigma<-data()$sigma
plot.g0.sigma(g0,sigma)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# #---Plot of cumulative traps occupied by time
plot(1:data()$n.nights,cumsum(colSums(data()$trap.catch))/(data()$n.traps*data()$max.catch),pch=20,xlim=c(0,data()$n.nights), ylim=c(0,1), xlab="Nights", ylab="Proportion of traps full traps" )
mtext("Cumulative traps full up (by time)",3)
# hist((data()$n.caught)) #Number of animals caught
hist((data()$p.caught)) #Propotion of animals caught
})
# Generate a summary of the dataset
output$summary1 <- reactivePrint(function() {
(round(data()$data.summary,3))
})
output$summary2 <- reactivePrint(function() {
data()$t.catch
})
})
shinyUI(pageWithSidebar(
# Application title
headerPanel("Trap simulations v0.1"),
# Sidebar with controls to select a dataset and specify the number
# of observations to view
sidebarPanel(
wellPanel(
h5("Trap Parameters"),
numericInput("trap.space.x", "Spacing (x):", 100),
numericInput("trap.space.y", "Spacing (y):", 50),
numericInput("traps.in.x", "Number of columns:", 20),
numericInput("traps.in.y", "Number of rows:", 20),
numericInput("max.catch", "Catch per trap:", 1),
numericInput("n.nights", "Number of nights:", 20)
),
wellPanel(
h5("Species Parameters"),
numericInput("g0", "g0:", 0.05),
numericInput("sigma", "Home range sigma (m):", 63),
numericInput("density", "Density (per ha):", 1),
radioButtons("dist.type", "Distribution of animals",
list("Fixed" = "F", "Poisson" = "P"))
),
wellPanel(h5("Simulation parameters"),
numericInput("reps","Iterations:",10)),
submitButton("Update")
),
mainPanel(
plotOutput(outputId = "main_plot", height = "800px"),
h5("Probability of capture"),
verbatimTextOutput("summary1"),
h5("Animals captured per trap"),
verbatimTextOutput("summary2")
)
)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment