view bmsb.R @ 26:641c4954c76c draft

Uploaded
author greg
date Fri, 19 Aug 2016 14:48:43 -0400
parents 08cb8c7228c2
children 79cef4a790cc
line wrap: on
line source

#!/usr/bin/env Rscript

suppressPackageStartupMessages(library("optparse"))

options_list <- list(
    make_option(c("-i", "--input"), action="store", help="Input dataset")
    make_option(c("-o", "--output"), action="store", help="Output dataset")
)

parser <- OptionParser(usage="%prog [options] file", options_list)
args <- parse_args(parser, positional_arguments=TRUE)
opt <- args$options

#########################################
daylength=function(L){
# from Forsythe 1995
p=0.8333
dl<-NULL
for (i in 1:365) {
theta<-0.2163108+2*atan(0.9671396*tan(0.00860*(i-186)))
phi<-asin(0.39795*cos(theta))
dl[i]<-24-24/pi*acos((sin(p*pi/180)+sin(L*pi/180)*sin(phi))/(cos(L*pi/180)*cos(phi)))
}
dl   # return a vector of daylength in 365 days
}
#########################################

#########################################
# source("daylength.R")
hourtemp=function(L,date){
# L=37.5 specify this in main program
threshold<-12.7  # base development threshold for BMSB
# threshold2<-threshold/24 degree hour accumulation
#expdata<-tempdata[1:365,11:13] # Use daily max, min, mean
dnp<-expdata[date,2]  # daily minimum
dxp<-expdata[date,3]  # daily maximum
dmean<-0.5*(dnp+dxp)
#if (dmean>0) {
#dnp<-dnp-k1*dmean  
#dxp<-dxp+k2*dmean 
#} else {
#dnp<-dnp+k1*dmean  
#dxp<-dxp-k2*dmean
#}
dd<-0  # initialize degree day accumulation

if (dxp<threshold) {dd<-0} else
{
dlprofile<-daylength(L)  # extract daylength data for entire year
T<-NULL  # initialize hourly temperature
dh<-NULL #initialize degree hour vector
# date<-200
y<-dlprofile[date]  # calculate daylength in given date
z<-24-y     # night length
a<-1.86     # lag coefficient
b<-2.20     # night coefficient
#tempdata<-read.csv("tempdata.csv") #import raw data set
# Should be outside function otherwise its redundant
risetime<-12-y/2      # sunrise time
settime<-12+y/2       # sunset time
ts<-(dxp-dnp)*sin(pi*(settime-5)/(y+2*a))+dnp
for (i in 1:24){      
  if (i>risetime && i<settime) {
    m<-i-5  # number of hours after Tmin until sunset
    T[i]=(dxp-dnp)*sin(pi*m/(y+2*a))+dnp
    if (T[i]<8.4) {dh[i]<-0} else
    {dh[i]<-T[i]-8.4}
    } else
  if (i>settime){ 
    n<-i-settime
    T[i]=dnp+(ts-dnp)*exp(-b*n/z)
    if (T[i]<8.4) {dh[i]<-0} else
    {dh[i]<-T[i]-8.4}
    } else
           {
    n<-i+24-settime
    T[i]=dnp+(ts-dnp)*exp(-b*n/z)
    if (T[i]<8.4) {dh[i]<-0} else
    {dh[i]<-T[i]-8.4}
    }
}
dd<-sum(dh)/24
}
return=c(dmean,dd)
return
}
#########################################


#########################################
mortality.egg=function(temperature){
if (temperature<12.7) {
 mort.prob=0.8} else 
{mort.prob=0.8-temperature/40
if (mort.prob<0) {mort.prob=0.01}
}
return=mort.prob
return
}
#########################################


#########################################
mortality.nymph=function(temperature){
if (temperature<12.7) {
 mort.prob=0.03} else 
{mort.prob=temperature*0.0008+0.03}
return=mort.prob
return
}
#########################################

#########################################
mortality.adult=function(temperature){
if (temperature<12.7) {
 mort.prob=0.002} else 
{mort.prob=temperature*0.0005+0.02}
return=mort.prob
return
}
#########################################

# model initialization
# setwd(“/home/lunarmouse/Dropbox/Nelson's project/") 
# PLEASE CHANGE TO YOUR OWN DIRECTORY!!!
# PLEASE LOAD BSMB FUNCTIONS FIRST!!!

n<-1000 # start with 1000 individuals
# Generation, Stage, DD, T, Diapause
vec.ini<-c(0,3,0,0,0)
# overwintering, previttelogenic,DD=0, T=0, no-diapause
vec.mat<-rep(vec.ini,n)
vec.mat<-t(matrix(vec.mat,nrow=5)) # complete matrix for the population
L<-35.58 # latitude for Asheville NC
ph.p<-daylength(L) # complete photoperiod profile in a year, requires daylength function

#load("asheville2014.Rdat") # load temperature data@location/year
load(opt$input) # load temperature data@location/year
tot.pop<-NULL # time series of population size
gen0.pop<-rep(0,365) # gen.0 pop size
gen1.pop<-rep(0,365)
gen2.pop<-rep(0,365)
S0<-S1<-S2<-S3<-S4<-S5<-rep(0,365)
g0.adult<-g1.adult<-g2.adult<-rep(0,365)
N.newborn<-N.death<-N.adult<-rep(0,365)
dd.day<-rep(0,365)

ptm <- proc.time() # start tick

for (day in 1:365) { # all the day
photoperiod<-ph.p[day] # photoperiod in the day
temp.profile<-hourtemp(L,day)
mean.temp<-temp.profile[1]
dd.temp<-temp.profile[2]
dd.day[day]<-dd.temp
death.vec<-NULL # trash bin for death
birth.vec<-NULL # new born
#n<-length(vec.mat[,1]) # population size at previous day

  for (i in 1:n) { # all individual
  vec.ind<-vec.mat[i,] # find individual record
  
# first of all, still alive?  
if(vec.ind[2]==0){ # egg
death.prob=mortality.egg(mean.temp)
 } else if (vec.ind[2]==1 | vec.ind[2]==2) {
death.prob=mortality.nymph(mean.temp)
}  else if (vec.ind[2]==3 | vec.ind[2]==4 | vec.ind[2]==5) { # for adult
 if (day<120 && day>270) {death.prob=0.33*mortality.adult(mean.temp)
  } else { 
death.prob=mortality.adult(mean.temp)} # reduce adult mortality after fall equinox
}


#(or dependent on temperature and life stage?)
u.d<-runif(1)
if (u.d<death.prob) {
death.vec<-c(death.vec,i)} else # aggregrate index of dead bug
  {
# event 1 end of diapause
if (vec.ind[1]==0 && vec.ind[2]==3) { # overwintering adult (previttelogenic)
 if (photoperiod>13.5 && vec.ind[3]>77 && day<180) { # add 77C to become fully reproductively matured
    vec.ind<-c(0,4,0,0,0) # transfer to vittelogenic
	vec.mat[i,]<-vec.ind
	
 } else {
    vec.ind[3]<-vec.ind[3]+dd.temp # add to DD
    vec.ind[4]<-vec.ind[4]+1 # add 1 day in current stage
	vec.mat[i,]<-vec.ind
 }
}

if (vec.ind[1]!=0 && vec.ind[2]==3) { # NOT overwintering adult (previttelogenic)
    current.gen<-vec.ind[1]
 if (vec.ind[3]>77) { # add 77C to become fully reproductively matured
    vec.ind<-c(current.gen,4,0,0,0) # transfer to vittelogenic
	vec.mat[i,]<-vec.ind
 } else {
    vec.ind[3]<-vec.ind[3]+dd.temp # add to DD
    vec.ind[4]<-vec.ind[4]+1 # add 1 day in current stage
	vec.mat[i,]<-vec.ind
 }
}

 
 
# event 2 oviposition -- where population dynamics comes from
if (vec.ind[2]==4 && vec.ind[1]==0 && mean.temp>10) { # vittelogenic stage, overwintering generation
   if (vec.ind[4]==0) { # just turned in vittelogenic stage
   n.birth=round(runif(1,2,8))} else{
   p.birth=0.01 # daily probability of birth
   u1<-runif(1)
      if (u1<p.birth) {n.birth=round(runif(1,2,8))}
   }
    vec.ind[3]<-vec.ind[3]+dd.temp # add to DD
    vec.ind[4]<-vec.ind[4]+1 # add 1 day in current stage
	vec.mat[i,]<-vec.ind
     if (n.birth>0) { # add new birth -- might be in different generations
	  new.gen<-vec.ind[1]+1 # generation +1
	  new.ind<-c(new.gen,0,0,0,0) # egg profile
	  new.vec<-rep(new.ind,n.birth)
	  new.vec<-t(matrix(new.vec,nrow=5)) # update batch of egg profile
	  birth.vec<-rbind(birth.vec,new.vec) # group with total eggs laid in that day
	 }
}

# event 2 oviposition -- for gen 1.
if (vec.ind[2]==4 && vec.ind[1]==1 && mean.temp>12.5 && day<222) { # vittelogenic stage, 1st generation
   if (vec.ind[4]==0) { # just turned in vittelogenic stage
   n.birth=round(runif(1,2,8))} else{
   p.birth=0.01 # daily probability of birth
   u1<-runif(1)
      if (u1<p.birth) {n.birth=round(runif(1,2,8))}
   }
    vec.ind[3]<-vec.ind[3]+dd.temp # add to DD
    vec.ind[4]<-vec.ind[4]+1 # add 1 day in current stage
	vec.mat[i,]<-vec.ind
     if (n.birth>0) { # add new birth -- might be in different generations
	  new.gen<-vec.ind[1]+1 # generation +1
	  new.ind<-c(new.gen,0,0,0,0) # egg profile
	  new.vec<-rep(new.ind,n.birth)
	  new.vec<-t(matrix(new.vec,nrow=5)) # update batch of egg profile
	  birth.vec<-rbind(birth.vec,new.vec) # group with total eggs laid in that day
	 }
}



# event 3 development (with diapause determination)
  # event 3.1 egg development to young nymph (vec.ind[2]=0 -> egg)
if (vec.ind[2]==0) { # egg stage
   vec.ind[3]<-vec.ind[3]+dd.temp # add to DD
    if (vec.ind[3]>=68) { # from egg to young nymph, DD requirement met
	    current.gen<-vec.ind[1]
		vec.ind<-c(current.gen,1,0,0,0) # transfer to young nym stage
	} else {
	vec.ind[4]<-vec.ind[4]+1 # add 1 day in current stage
	}
	vec.mat[i,]<-vec.ind
}
  
  # event 3.2 young nymph to old nymph (vec.ind[2]=1 -> young nymph: determines diapause)
if (vec.ind[2]==1) { # young nymph stage
      vec.ind[3]<-vec.ind[3]+dd.temp # add to DD
   if (vec.ind[3]>=250) { # from young to old nymph, DD requirement met
	    current.gen<-vec.ind[1]
		vec.ind<-c(current.gen,2,0,0,0) # transfer to old nym stage
		  if (photoperiod<13.5 && day > 180) {vec.ind[5]<-1} # prepare for diapausing
	} else {
	vec.ind[4]<-vec.ind[4]+1 # add 1 day in current stage
	}
    vec.mat[i,]<-vec.ind
}  
  
  
  # event 3.3 old nymph to adult: previttelogenic or diapausing?
if (vec.ind[2]==2) { # old nymph stage
    vec.ind[3]<-vec.ind[3]+dd.temp # add to DD
       if (vec.ind[3]>=200) { # from old to adult, DD requirement met
       current.gen<-vec.ind[1]
         if (vec.ind[5]==0) { # non-diapausing adult -- previttelogenic
          vec.ind<-c(current.gen,3,0,0,0)
        } else { # diapausing 
          vec.ind<-c(current.gen,5,0,0,1)
        }		
   } else {
   vec.ind[4]<-vec.ind[4]+1 # add 1 day in current stage
   }
   vec.mat[i,]<-vec.ind
}

# event 4 growing of diapausing adult (unimportant, but still necessary)## 
if (vec.ind[2]==5) {
  vec.ind[3]<-vec.ind[3]+dd.temp
  vec.ind[4]<-vec.ind[4]+1
  vec.mat[i,]<-vec.ind
}

 } # else if it is still alive

} # end of the individual bug loop

# find how many died
n.death<-length(death.vec)
if (n.death>0) {
vec.mat<-vec.mat[-death.vec, ]}
# remove record of dead
# find how many new born  
n.newborn<-length(birth.vec[,1])
vec.mat<-rbind(vec.mat,birth.vec)
# update population size for the next day
n<-n-n.death+n.newborn 

# aggregate results by day
tot.pop<-c(tot.pop,n) 
s0<-sum(vec.mat[,2]==0) #egg
s1<-sum(vec.mat[,2]==1) # young nymph
s2<-sum(vec.mat[,2]==2) # old nymph
s3<-sum(vec.mat[,2]==3) # previtellogenic
s4<-sum(vec.mat[,2]==4) # vitellogenic
s5<-sum(vec.mat[,2]==5) # diapausing
gen0<-sum(vec.mat[,1]==0) # overwintering adult
gen1<-sum(vec.mat[,1]==1) # first generation
gen2<-sum(vec.mat[,1]==2) # second generation
n.adult<-sum(vec.mat[,2]==3)+sum(vec.mat[,2]==4)+sum(vec.mat[,2]==5) # sum of all adults
gen0.pop[day]<-gen0 # gen.0 pop size
gen1.pop[day]<-gen1
gen2.pop[day]<-gen2
S0[day]<-s0
S1[day]<-s1
S2[day]<-s2
S3[day]<-s3
S4[day]<-s4
S5[day]<-s5
g0.adult[day]<-sum(vec.mat[,1]==0)
g1.adult[day]<-sum((vec.mat[,1]==1 & vec.mat[,2]==3) | (vec.mat[,1]==1 & vec.mat[,2]==4) | (vec.mat[,1]==1 & vec.mat[,2]==5))
g2.adult[day]<-sum((vec.mat[,1]==2 & vec.mat[,2]==3) | (vec.mat[,1]==2 & vec.mat[,2]==4) | (vec.mat[,1]==2 & vec.mat[,2]==5))



N.newborn[day]<-n.newborn
N.death[day]<-n.death
N.adult[day]<-n.adult
print(c(day,n,n.adult))
}   

proc.time() - ptm
dd.cum<-cumsum(dd.day)
save(dd.day,dd.cum,S0,S1,S2,S3,S4,S5,N.newborn,N.death,N.adult,tot.pop,gen0.pop,gen1.pop,gen2.pop,g0.adult,g1.adult,g2.adult,file="opt$output")