Mercurial > repos > greg > insect_phenology_model
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 |