comparison insect_phenology_model.R @ 85:8f5c05be4efe draft

Uploaded
author greg
date Wed, 22 Nov 2017 13:02:16 -0500
parents 0c807f99a816
children 522fe34a1dfc
comparison
equal deleted inserted replaced
84:1863d847749b 85:8f5c05be4efe
26 opt <- args$options 26 opt <- args$options
27 27
28 parse_input_data = function(input_file, num_rows) { 28 parse_input_data = function(input_file, num_rows) {
29 # Read in the input temperature datafile into a data frame. 29 # Read in the input temperature datafile into a data frame.
30 temperature_data_frame <- read.csv(file=input_file, header=T, strip.white=TRUE, sep=",") 30 temperature_data_frame <- read.csv(file=input_file, header=T, strip.white=TRUE, sep=",")
31 if (dim(temperature_data_frame)[2] == 6) { 31 num_columns <- dim(temperature_data_frame)[2]
32 if (num_columns == 6) {
32 # The input data has the following 6 columns: 33 # The input data has the following 6 columns:
33 # LATITUDE, LONGITUDE, DATE, DOY, TMIN, TMAX 34 # LATITUDE, LONGITUDE, DATE, DOY, TMIN, TMAX
35 # Set the column names for access when adding daylight length..
36 colnames(temperature_data_frame) <- c("LATITUDE","LONGITUDE", "DATE", "DOY", "TMIN", "TMAX")
34 # Add a column containing the daylight length for each day. 37 # Add a column containing the daylight length for each day.
35 temperature_data_frame <- add_daylight_length(temperature_data_frame, num_rows) 38 temperature_data_frame <- add_daylight_length(temperature_data_frame, num_columns, num_rows)
36 } 39 # Reset the column names with the additional column for later access.
37 # Return the temperature_data_frame. 40 colnames(temperature_data_frame) <- c("LATITUDE","LONGITUDE", "DATE", "DOY", "TMIN", "TMAX", "DAYLEN")
38 temperature_data_frame 41 }
39 } 42 return(temperature_data_frame)
40 43 }
41 add_daylight_length = function(temperature_data_frame, num_rows) { 44
45 add_daylight_length = function(temperature_data_frame, num_columns, num_rows) {
42 # Return a vector of daylight length (photoperido profile) for 46 # Return a vector of daylight length (photoperido profile) for
43 # the number of days specified in the input temperature data 47 # the number of days specified in the input temperature data
44 # (from Forsythe 1995). 48 # (from Forsythe 1995).
45 p = 0.8333 49 p = 0.8333
46 latitude <- temperature_data_frame[1, 1] 50 latitude <- temperature_data_frame$LATITUDE[1]
47 daylight_length_vector <- NULL 51 daylight_length_vector <- NULL
48 for (i in 1:num_rows) { 52 for (i in 1:num_rows) {
49 # Get the day of the year from the current row 53 # Get the day of the year from the current row
50 # of the temperature data for computation. 54 # of the temperature data for computation.
51 doy <- temperature_data_frame[i, 4] 55 doy <- temperature_data_frame$DOY[i]
52 theta <- 0.2163108 + 2 * atan(0.9671396 * tan(0.00860 * (doy - 186))) 56 theta <- 0.2163108 + 2 * atan(0.9671396 * tan(0.00860 * (doy - 186)))
53 phi <- asin(0.39795 * cos(theta)) 57 phi <- asin(0.39795 * cos(theta))
54 # Compute the length of daylight for the day of the year. 58 # Compute the length of daylight for the day of the year.
55 daylight_length_vector[i] <- 24 - (24 / pi * acos((sin(p * pi / 180) + sin(latitude * pi / 180) * sin(phi)) / (cos(latitude * pi / 180) * cos(phi)))) 59 daylight_length_vector[i] <- 24 - (24 / pi * acos((sin(p * pi / 180) + sin(latitude * pi / 180) * sin(phi)) / (cos(latitude * pi / 180) * cos(phi))))
56 } 60 }
57 # Append daylight_length_vector as a new column to temperature_data_frame. 61 # Append daylight_length_vector as a new column to temperature_data_frame.
58 temperature_data_frame[, 7] <- daylight_length_vector 62 temperature_data_frame[, num_columns+1] <- daylight_length_vector
59 # Return the temperature_data_frame. 63 return(temperature_data_frame)
60 temperature_data_frame
61 } 64 }
62 65
63 get_temperature_at_hour = function(latitude, temperature_data_frame, row, num_days) { 66 get_temperature_at_hour = function(latitude, temperature_data_frame, row, num_days) {
64 # Base development threshold for Brown Marmolated Stink Bug 67 # Base development threshold for Brown Marmolated Stink Bug
65 # insect phenology model. 68 # insect phenology model.
66 # TODO: Pass insect on the command line to accomodate more 69 # TODO: Pass insect on the command line to accomodate more
67 # the just the Brown Marmolated Stink Bub. 70 # the just the Brown Marmolated Stink Bub.
68 threshold <- 14.17 71 threshold <- 14.17
69
70 # Input temperature currently has the following columns.
71 # # LATITUDE, LONGITUDE, DATE, DOY, TMIN, TMAX
72 # Minimum temperature for current row. 72 # Minimum temperature for current row.
73 dnp <- temperature_data_frame[row, 5] 73 dnp <- temperature_data_frame$TMIN[row]
74 # Maximum temperature for current row. 74 # Maximum temperature for current row.
75 dxp <- temperature_data_frame[row, 6] 75 dxp <- temperature_data_frame$TMAX[row]
76 # Mean temperature for current row. 76 # Mean temperature for current row.
77 dmean <- 0.5 * (dnp + dxp) 77 dmean <- 0.5 * (dnp + dxp)
78 # Initialize degree day accumulation 78 # Initialize degree day accumulation
79 dd <- 0 79 dd <- 0
80 if (dxp < threshold) { 80 if (dxp < threshold) {
84 # Initialize hourly temperature. 84 # Initialize hourly temperature.
85 T <- NULL 85 T <- NULL
86 # Initialize degree hour vector. 86 # Initialize degree hour vector.
87 dh <- NULL 87 dh <- NULL
88 # Daylight length for current row. 88 # Daylight length for current row.
89 y <- temperature_data_frame[row, 7] 89 y <- temperature_data_frame$DAYLEN[row]
90 # Darkness length. 90 # Darkness length.
91 z <- 24 - y 91 z <- 24 - y
92 # Lag coefficient. 92 # Lag coefficient.
93 a <- 1.86 93 a <- 1.86
94 # Darkness coefficient. 94 # Darkness coefficient.
131 } 131 }
132 } 132 }
133 } 133 }
134 dd <- sum(dh) / 24 134 dd <- sum(dh) / 24
135 } 135 }
136 return=c(dmean, dd) 136 return(c(dmean, dd))
137 return
138 } 137 }
139 138
140 dev.egg = function(temperature) { 139 dev.egg = function(temperature) {
141 dev.rate= -0.9843 * temperature + 33.438 140 dev.rate= -0.9843 * temperature + 33.438
142 return = dev.rate 141 return(dev.rate)
143 return
144 } 142 }
145 143
146 dev.young = function(temperature) { 144 dev.young = function(temperature) {
147 n12 <- -0.3728 * temperature + 14.68 145 n12 <- -0.3728 * temperature + 14.68
148 n23 <- -0.6119 * temperature + 25.249 146 n23 <- -0.6119 * temperature + 25.249
149 dev.rate = mean(n12 + n23) 147 dev.rate = mean(n12 + n23)
150 return = dev.rate 148 return(dev.rate)
151 return
152 } 149 }
153 150
154 dev.old = function(temperature) { 151 dev.old = function(temperature) {
155 n34 <- -0.6119 * temperature + 17.602 152 n34 <- -0.6119 * temperature + 17.602
156 n45 <- -0.4408 * temperature + 19.036 153 n45 <- -0.4408 * temperature + 19.036
157 dev.rate = mean(n34 + n45) 154 dev.rate = mean(n34 + n45)
158 return = dev.rate 155 return(dev.rate)
159 return
160 } 156 }
161 157
162 dev.emerg = function(temperature) { 158 dev.emerg = function(temperature) {
163 emerg.rate <- -0.5332 * temperature + 24.147 159 emerg.rate <- -0.5332 * temperature + 24.147
164 return = emerg.rate 160 return(emerg.rate)
165 return
166 } 161 }
167 162
168 mortality.egg = function(temperature) { 163 mortality.egg = function(temperature) {
169 if (temperature < 12.7) { 164 if (temperature < 12.7) {
170 mort.prob = 0.8 165 mort.prob = 0.8
173 mort.prob = 0.8 - temperature / 40.0 168 mort.prob = 0.8 - temperature / 40.0
174 if (mort.prob < 0) { 169 if (mort.prob < 0) {
175 mort.prob = 0.01 170 mort.prob = 0.01
176 } 171 }
177 } 172 }
178 return = mort.prob 173 return(mort.prob)
179 return
180 } 174 }
181 175
182 mortality.nymph = function(temperature) { 176 mortality.nymph = function(temperature) {
183 if (temperature < 12.7) { 177 if (temperature < 12.7) {
184 mort.prob = 0.03 178 mort.prob = 0.03
185 } 179 }
186 else { 180 else {
187 mort.prob = temperature * 0.0008 + 0.03 181 mort.prob = temperature * 0.0008 + 0.03
188 } 182 }
189 return = mort.prob 183 return(mort.prob)
190 return
191 } 184 }
192 185
193 mortality.adult = function(temperature) { 186 mortality.adult = function(temperature) {
194 if (temperature < 12.7) { 187 if (temperature < 12.7) {
195 mort.prob = 0.002 188 mort.prob = 0.002
196 } 189 }
197 else { 190 else {
198 mort.prob = temperature * 0.0005 + 0.02 191 mort.prob = temperature * 0.0005 + 0.02
199 } 192 }
200 return = mort.prob 193 return(mort.prob)
201 return
202 } 194 }
203 195
204 temperature_data_frame <- parse_input_data(opt$input, opt$num_days) 196 temperature_data_frame <- parse_input_data(opt$input, opt$num_days)
205 latitude <- temperature_data_frame[1, 1] 197 # All latitude values are the same,
198 # so get the value from the first row.
199 latitude <- temperature_data_frame$LATITUDE[1]
206 200
207 cat("Number of days: ", opt$num_days, "\n") 201 cat("Number of days: ", opt$num_days, "\n")
208 202
209 # Initialize matrix for results from all replications. 203 # Initialize matrix for results from all replications.
210 S0.rep <- S1.rep <- S2.rep <- S3.rep <- S4.rep <- S5.rep <- matrix(rep(0, opt$num_days * opt$replications), ncol = opt$replications) 204 S0.rep <- S1.rep <- S2.rep <- S3.rep <- S4.rep <- S5.rep <- matrix(rep(0, opt$num_days * opt$replications), ncol = opt$replications)
211 newborn.rep <- death.rep <- adult.rep <- pop.rep <- g0.rep <- g1.rep <- g2.rep <- g0a.rep <- g1a.rep <- g2a.rep <- matrix(rep(0, opt$num_days * opt$replications), ncol=opt$replications) 205 newborn.rep <- death.rep <- adult.rep <- pop.rep <- g0.rep <- g1.rep <- g2.rep <- g0a.rep <- g1a.rep <- g2a.rep <- matrix(rep(0, opt$num_days * opt$replications), ncol=opt$replications)
212 206
213 # loop through replications 207 # Loop through replications.
214 for (N.rep in 1:opt$replications) { 208 for (N.rep in 1:opt$replications) {
215 # During each replication start with 1000 individuals. 209 # During each replication start with 1000 individuals.
216 # TODO: user definable as well? 210 # TODO: user definable as well?
217 n <- 1000 211 n <- 1000
218 # Generation, Stage, DD, T, Diapause. 212 # Generation, Stage, DD, T, Diapause.
228 gen2.pop <- rep(0, opt$num_days) 222 gen2.pop <- rep(0, opt$num_days)
229 S0 <- S1 <- S2 <- S3 <- S4 <- S5 <- rep(0, opt$num_days) 223 S0 <- S1 <- S2 <- S3 <- S4 <- S5 <- rep(0, opt$num_days)
230 g0.adult <- g1.adult <- g2.adult <- rep(0, opt$num_days) 224 g0.adult <- g1.adult <- g2.adult <- rep(0, opt$num_days)
231 N.newborn <- N.death <- N.adult <- rep(0, opt$num_days) 225 N.newborn <- N.death <- N.adult <- rep(0, opt$num_days)
232 dd.day <- rep(0, opt$num_days) 226 dd.day <- rep(0, opt$num_days)
233
234 # All the days included in the input temperature dataset. 227 # All the days included in the input temperature dataset.
235 for (row in 1:opt$num_days) { 228 for (row in 1:opt$num_days) {
236 # Get the integer day of the year for the current row. 229 # Get the integer day of the year for the current row.
237 doy <- temperature_data_frame[row, 4] 230 doy <- temperature_data_frame$DOY[row]
238 # Photoperiod in the day. 231 # Photoperiod in the day.
239 photoperiod <- temperature_data_frame[row, 7] 232 photoperiod <- temperature_data_frame$DAYLEN[row]
240 temp.profile <- get_temperature_at_hour(latitude, temperature_data_frame, row, opt$num_days) 233 temp.profile <- get_temperature_at_hour(latitude, temperature_data_frame, row, opt$num_days)
241 mean.temp <- temp.profile[1] 234 mean.temp <- temp.profile[1]
242 dd.temp <- temp.profile[2] 235 dd.temp <- temp.profile[2]
243 dd.day[row] <- dd.temp 236 dd.day[row] <- dd.temp
244 # Trash bin for death. 237 # Trash bin for death.
245 death.vec <- NULL 238 death.vec <- NULL
246 # Newborn. 239 # Newborn.
247 birth.vec <- NULL 240 birth.vec <- NULL
248
249 # All individuals. 241 # All individuals.
250 for (i in 1:n) { 242 for (i in 1:n) {
251 # Find individual record. 243 # Find individual record.
252 vec.ind <- vec.mat[i,] 244 vec.ind <- vec.mat[i,]
253 # First of all, still alive? 245 # First of all, still alive?
316 # Add 1 day in current stage. 308 # Add 1 day in current stage.
317 vec.ind[4] <- vec.ind[4] + 1 309 vec.ind[4] <- vec.ind[4] + 1
318 vec.mat[i,] <- vec.ind 310 vec.mat[i,] <- vec.ind
319 } 311 }
320 } 312 }
321
322 # Event 2 oviposition -- where population dynamics comes from. 313 # Event 2 oviposition -- where population dynamics comes from.
323 if (vec.ind[2] == 4 && vec.ind[1] == 0 && mean.temp > 10) { 314 if (vec.ind[2] == 4 && vec.ind[1] == 0 && mean.temp > 10) {
324 # Vittelogenic stage, overwintering generation. 315 # Vittelogenic stage, overwintering generation.
325 if (vec.ind[4] == 0) { 316 if (vec.ind[4] == 0) {
326 # Just turned in vittelogenic stage. 317 # Just turned in vittelogenic stage.
349 new.vec <- t(matrix(new.vec, nrow=5)) 340 new.vec <- t(matrix(new.vec, nrow=5))
350 # Group with total eggs laid in that day. 341 # Group with total eggs laid in that day.
351 birth.vec <- rbind(birth.vec, new.vec) 342 birth.vec <- rbind(birth.vec, new.vec)
352 } 343 }
353 } 344 }
354 345 # Event 2 oviposition -- for generation 1.
355 # Event 2 oviposition -- for gen 1.
356 if (vec.ind[2] == 4 && vec.ind[1] == 1 && mean.temp > 12.5 && doy < 222) { 346 if (vec.ind[2] == 4 && vec.ind[1] == 1 && mean.temp > 12.5 && doy < 222) {
357 # Vittelogenic stage, 1st generation 347 # Vittelogenic stage, 1st generation
358 if (vec.ind[4] == 0) { 348 if (vec.ind[4] == 0) {
359 # Just turned in vittelogenic stage. 349 # Just turned in vittelogenic stage.
360 n.birth=round(runif(1, 2 + opt$min_clutch_size, 8 + opt$max_clutch_size)) 350 n.birth=round(runif(1, 2 + opt$min_clutch_size, 8 + opt$max_clutch_size))
382 new.vec <- t(matrix(new.vec, nrow=5)) 372 new.vec <- t(matrix(new.vec, nrow=5))
383 # Group with total eggs laid in that day. 373 # Group with total eggs laid in that day.
384 birth.vec <- rbind(birth.vec, new.vec) 374 birth.vec <- rbind(birth.vec, new.vec)
385 } 375 }
386 } 376 }
387
388 # Event 3 development (with diapause determination). 377 # Event 3 development (with diapause determination).
389 # Event 3.1 egg development to young nymph (vec.ind[2]=0 -> egg). 378 # Event 3.1 egg development to young nymph (vec.ind[2]=0 -> egg).
390 if (vec.ind[2] == 0) { 379 if (vec.ind[2] == 0) {
391 # Egg stage. 380 # Egg stage.
392 # Add to dd. 381 # Add to dd.
401 # Add 1 day in current stage. 390 # Add 1 day in current stage.
402 vec.ind[4] <- vec.ind[4] + 1 391 vec.ind[4] <- vec.ind[4] + 1
403 } 392 }
404 vec.mat[i,] <- vec.ind 393 vec.mat[i,] <- vec.ind
405 } 394 }
406
407 # Event 3.2 young nymph to old nymph (vec.ind[2]=1 -> young nymph: determines diapause). 395 # Event 3.2 young nymph to old nymph (vec.ind[2]=1 -> young nymph: determines diapause).
408 if (vec.ind[2] == 1) { 396 if (vec.ind[2] == 1) {
409 # young nymph stage. 397 # young nymph stage.
410 # add to dd. 398 # add to dd.
411 vec.ind[3] <- vec.ind[3] + dd.temp 399 vec.ind[3] <- vec.ind[3] + dd.temp
422 # Add 1 day in current stage. 410 # Add 1 day in current stage.
423 vec.ind[4] <- vec.ind[4] + 1 411 vec.ind[4] <- vec.ind[4] + 1
424 } 412 }
425 vec.mat[i,] <- vec.ind 413 vec.mat[i,] <- vec.ind
426 } 414 }
427
428 # Event 3.3 old nymph to adult: previttelogenic or diapausing? 415 # Event 3.3 old nymph to adult: previttelogenic or diapausing?
429 if (vec.ind[2] == 2) { 416 if (vec.ind[2] == 2) {
430 # Old nymph stage. 417 # Old nymph stage.
431 # add to dd. 418 # add to dd.
432 vec.ind[3] <- vec.ind[3] + dd.temp 419 vec.ind[3] <- vec.ind[3] + dd.temp
446 # Add 1 day in current stage. 433 # Add 1 day in current stage.
447 vec.ind[4] <- vec.ind[4] + 1 434 vec.ind[4] <- vec.ind[4] + 1
448 } 435 }
449 vec.mat[i,] <- vec.ind 436 vec.mat[i,] <- vec.ind
450 } 437 }
451
452 # Event 4 growing of diapausing adult (unimportant, but still necessary). 438 # Event 4 growing of diapausing adult (unimportant, but still necessary).
453 if (vec.ind[2] == 5) { 439 if (vec.ind[2] == 5) {
454 vec.ind[3] <- vec.ind[3] + dd.temp 440 vec.ind[3] <- vec.ind[3] + dd.temp
455 vec.ind[4] <- vec.ind[4] + 1 441 vec.ind[4] <- vec.ind[4] + 1
456 vec.mat[i,] <- vec.ind 442 vec.mat[i,] <- vec.ind
457 } 443 }
458 } # Else if it is still alive. 444 } # Else if it is still alive.
459 } # End of the individual bug loop. 445 } # End of the individual bug loop.
460
461 # Find how many died. 446 # Find how many died.
462 n.death <- length(death.vec) 447 n.death <- length(death.vec)
463 if (n.death > 0) { 448 if (n.death > 0) {
464 vec.mat <- vec.mat[-death.vec, ] 449 vec.mat <- vec.mat[-death.vec, ]
465 } 450 }
536 } 521 }
537 522
538 # Data analysis and visualization can currently 523 # Data analysis and visualization can currently
539 # plot only within a single calendar year. 524 # plot only within a single calendar year.
540 # TODO: enhance this to accomodate multiple calendar years. 525 # TODO: enhance this to accomodate multiple calendar years.
541 start_date <- temperature_data_frame[1, 3] 526 start_date <- temperature_data_frame$DATE[1]
542 end_date <- temperature_data_frame[opt$num_days, 3] 527 end_date <- temperature_data_frame$DATE[opt$num_days]
543 528
544 n.yr <- 1 529 n.yr <- 1
545 day.all <- c(1:opt$num_days * n.yr) 530 day.all <- c(1:opt$num_days * n.yr)
546 531
547 # mean value for adults 532 # mean value for adults