| 
85
 | 
     1 #!/usr/bin/env Rscript
 | 
| 
 | 
     2 
 | 
| 
 | 
     3 suppressPackageStartupMessages(library("optparse"))
 | 
| 
 | 
     4 
 | 
| 
 | 
     5 option_list <- list(
 | 
| 
 | 
     6     make_option(c("-a", "--adult_mort"), action="store", dest="adult_mort", type="integer", help="Adjustment rate for adult mortality"),
 | 
| 
 | 
     7     make_option(c("-b", "--adult_accum"), action="store", dest="adult_accum", type="integer", help="Adjustment of DD accumulation (old nymph->adult)"),
 | 
| 
 | 
     8     make_option(c("-c", "--egg_mort"), action="store", dest="egg_mort", type="integer", help="Adjustment rate for egg mortality"),
 | 
| 
 | 
     9     make_option(c("-e", "--location"), action="store", dest="location", help="Selected location"),
 | 
| 
 | 
    10     make_option(c("-f", "--min_clutch_size"), action="store", dest="min_clutch_size", type="integer", help="Adjustment of minimum clutch size"),
 | 
| 
 | 
    11     make_option(c("-i", "--max_clutch_size"), action="store", dest="max_clutch_size", type="integer", help="Adjustment of maximum clutch size"),
 | 
| 
 | 
    12     make_option(c("-j", "--nymph_mort"), action="store", dest="nymph_mort", type="integer", help="Adjustment rate for nymph mortality"),
 | 
| 
 | 
    13     make_option(c("-k", "--old_nymph_accum"), action="store", dest="old_nymph_accum", type="integer", help="Adjustment of DD accumulation (young nymph->old nymph)"),
 | 
| 
 | 
    14     make_option(c("-n", "--num_days"), action="store", dest="num_days", type="integer", help="Total number of days in the temperature dataset"),
 | 
| 
 | 
    15     make_option(c("-o", "--output"), action="store", dest="output", help="Output dataset"),
 | 
| 
 | 
    16     make_option(c("-p", "--oviposition"), action="store", dest="oviposition", type="integer", help="Adjustment for oviposition rate"),
 | 
| 
 | 
    17     make_option(c("-q", "--photoperiod"), action="store", dest="photoperiod", type="double", help="Critical photoperiod for diapause induction/termination"),
 | 
| 
 | 
    18     make_option(c("-s", "--replications"), action="store", dest="replications", type="integer", help="Number of replications"),
 | 
| 
 | 
    19     make_option(c("-t", "--se_plot"), action="store", dest="se_plot", help="Plot SE"),
 | 
| 
 | 
    20     make_option(c("-v", "--input"), action="store", dest="input", help="Temperature data for selected location"),
 | 
| 
87
 | 
    21     make_option(c("-y", "--young_nymph_accum"), action="store", dest="young_nymph_accum", type="integer", help="Adjustment of DD accumulation (egg->young nymph)"),
 | 
| 
 | 
    22     make_option(c("-x", "--insect"), action="store", dest="insect", help="Insect name")
 | 
| 
85
 | 
    23 )
 | 
| 
 | 
    24 
 | 
| 
 | 
    25 parser <- OptionParser(usage="%prog [options] file", option_list=option_list)
 | 
| 
 | 
    26 args <- parse_args(parser, positional_arguments=TRUE)
 | 
| 
 | 
    27 opt <- args$options
 | 
| 
 | 
    28 
 | 
| 
 | 
    29 parse_input_data = function(input_file, num_rows) {
 | 
| 
 | 
    30     # Read in the input temperature datafile into a data frame.
 | 
| 
 | 
    31     temperature_data_frame <- read.csv(file=input_file, header=T, strip.white=TRUE, sep=",")
 | 
| 
 | 
    32     num_columns <- dim(temperature_data_frame)[2]
 | 
| 
 | 
    33     if (num_columns == 6) {
 | 
| 
 | 
    34         # The input data has the following 6 columns:
 | 
| 
 | 
    35         # LATITUDE, LONGITUDE, DATE, DOY, TMIN, TMAX
 | 
| 
 | 
    36         # Set the column names for access when adding daylight length..
 | 
| 
 | 
    37         colnames(temperature_data_frame) <- c("LATITUDE","LONGITUDE", "DATE", "DOY", "TMIN", "TMAX")
 | 
| 
 | 
    38         # Add a column containing the daylight length for each day.
 | 
| 
 | 
    39         temperature_data_frame <- add_daylight_length(temperature_data_frame, num_columns, num_rows)
 | 
| 
 | 
    40         # Reset the column names with the additional column for later access.
 | 
| 
 | 
    41         colnames(temperature_data_frame) <- c("LATITUDE","LONGITUDE", "DATE", "DOY", "TMIN", "TMAX", "DAYLEN")
 | 
| 
 | 
    42     }
 | 
| 
 | 
    43     return(temperature_data_frame)
 | 
| 
 | 
    44 }
 | 
| 
 | 
    45 
 | 
| 
 | 
    46 add_daylight_length = function(temperature_data_frame, num_columns, num_rows) {
 | 
| 
 | 
    47     # Return a vector of daylight length (photoperido profile) for
 | 
| 
 | 
    48     # the number of days specified in the input temperature data
 | 
| 
 | 
    49     # (from Forsythe 1995).
 | 
| 
 | 
    50     p = 0.8333
 | 
| 
 | 
    51     latitude <- temperature_data_frame$LATITUDE[1]
 | 
| 
 | 
    52     daylight_length_vector <- NULL
 | 
| 
 | 
    53     for (i in 1:num_rows) {
 | 
| 
 | 
    54         # Get the day of the year from the current row
 | 
| 
 | 
    55         # of the temperature data for computation.
 | 
| 
 | 
    56         doy <- temperature_data_frame$DOY[i]
 | 
| 
 | 
    57         theta <- 0.2163108 + 2 * atan(0.9671396 * tan(0.00860 * (doy - 186)))
 | 
| 
 | 
    58         phi <- asin(0.39795 * cos(theta))
 | 
| 
 | 
    59         # Compute the length of daylight for the day of the year.
 | 
| 
 | 
    60         daylight_length_vector[i] <- 24 - (24 / pi * acos((sin(p * pi / 180) + sin(latitude * pi / 180) * sin(phi)) / (cos(latitude * pi / 180) * cos(phi))))
 | 
| 
 | 
    61     }
 | 
| 
 | 
    62     # Append daylight_length_vector as a new column to temperature_data_frame.
 | 
| 
 | 
    63     temperature_data_frame[, num_columns+1] <- daylight_length_vector
 | 
| 
 | 
    64     return(temperature_data_frame)
 | 
| 
 | 
    65 }
 | 
| 
 | 
    66 
 | 
| 
 | 
    67 get_temperature_at_hour = function(latitude, temperature_data_frame, row, num_days) {
 | 
| 
 | 
    68     # Base development threshold for Brown Marmolated Stink Bug
 | 
| 
 | 
    69     # insect phenology model.
 | 
| 
 | 
    70     # TODO: Pass insect on the command line to accomodate more
 | 
| 
 | 
    71     # the just the Brown Marmolated Stink Bub.
 | 
| 
 | 
    72     threshold <- 14.17
 | 
| 
 | 
    73     # Minimum temperature for current row.
 | 
| 
 | 
    74     dnp <- temperature_data_frame$TMIN[row]
 | 
| 
 | 
    75     # Maximum temperature for current row.
 | 
| 
 | 
    76     dxp <- temperature_data_frame$TMAX[row]
 | 
| 
 | 
    77     # Mean temperature for current row.
 | 
| 
 | 
    78     dmean <- 0.5 * (dnp + dxp)
 | 
| 
 | 
    79     # Initialize degree day accumulation
 | 
| 
 | 
    80     dd <- 0
 | 
| 
 | 
    81     if (dxp < threshold) {
 | 
| 
 | 
    82         dd <- 0
 | 
| 
 | 
    83     }
 | 
| 
 | 
    84     else {
 | 
| 
 | 
    85         # Initialize hourly temperature.
 | 
| 
 | 
    86         T <- NULL
 | 
| 
 | 
    87         # Initialize degree hour vector.
 | 
| 
 | 
    88         dh <- NULL
 | 
| 
 | 
    89         # Daylight length for current row.
 | 
| 
 | 
    90         y <- temperature_data_frame$DAYLEN[row]
 | 
| 
 | 
    91         # Darkness length.
 | 
| 
 | 
    92         z <- 24 - y
 | 
| 
 | 
    93         # Lag coefficient.
 | 
| 
 | 
    94         a <- 1.86
 | 
| 
 | 
    95         # Darkness coefficient.
 | 
| 
 | 
    96         b <- 2.20
 | 
| 
 | 
    97         # Sunrise time.
 | 
| 
 | 
    98         risetime <- 12 - y / 2
 | 
| 
 | 
    99         # Sunset time.
 | 
| 
 | 
   100         settime <- 12 + y / 2
 | 
| 
 | 
   101         ts <- (dxp - dnp) * sin(pi * (settime - 5) / (y + 2 * a)) + dnp
 | 
| 
 | 
   102         for (i in 1:24) {
 | 
| 
 | 
   103             if (i > risetime && i < settime) {
 | 
| 
 | 
   104                 # Number of hours after Tmin until sunset.
 | 
| 
 | 
   105                 m <- i - 5
 | 
| 
 | 
   106                 T[i] = (dxp - dnp) * sin(pi * m / (y + 2 * a)) + dnp
 | 
| 
 | 
   107                 if (T[i] < 8.4) {
 | 
| 
 | 
   108                     dh[i] <- 0
 | 
| 
 | 
   109                 }
 | 
| 
 | 
   110                 else {
 | 
| 
 | 
   111                     dh[i] <- T[i] - 8.4
 | 
| 
 | 
   112                 }
 | 
| 
 | 
   113             }
 | 
| 
 | 
   114             else if (i > settime) { 
 | 
| 
 | 
   115                 n <- i - settime
 | 
| 
 | 
   116                 T[i] = dnp + (ts - dnp) * exp( - b * n / z)
 | 
| 
 | 
   117                 if (T[i] < 8.4) {
 | 
| 
 | 
   118                     dh[i] <- 0
 | 
| 
 | 
   119                 }
 | 
| 
 | 
   120                 else {
 | 
| 
 | 
   121                     dh[i] <- T[i] - 8.4
 | 
| 
 | 
   122                 }
 | 
| 
 | 
   123             }
 | 
| 
 | 
   124             else {
 | 
| 
 | 
   125                 n <- i + 24 - settime
 | 
| 
 | 
   126                 T[i]=dnp + (ts - dnp) * exp( - b * n / z)
 | 
| 
 | 
   127                 if (T[i] < 8.4) {
 | 
| 
 | 
   128                     dh[i] <- 0
 | 
| 
 | 
   129                 }
 | 
| 
 | 
   130                 else {
 | 
| 
 | 
   131                     dh[i] <- T[i] - 8.4
 | 
| 
 | 
   132                 }
 | 
| 
 | 
   133             }
 | 
| 
 | 
   134         }
 | 
| 
 | 
   135         dd <- sum(dh) / 24
 | 
| 
 | 
   136     }
 | 
| 
 | 
   137     return(c(dmean, dd))
 | 
| 
 | 
   138 }
 | 
| 
 | 
   139 
 | 
| 
 | 
   140 dev.egg = function(temperature) {
 | 
| 
 | 
   141     dev.rate= -0.9843 * temperature + 33.438
 | 
| 
 | 
   142     return(dev.rate)
 | 
| 
 | 
   143 }
 | 
| 
 | 
   144 
 | 
| 
 | 
   145 dev.young = function(temperature) {
 | 
| 
 | 
   146     n12 <- -0.3728 * temperature + 14.68
 | 
| 
 | 
   147     n23 <- -0.6119 * temperature + 25.249
 | 
| 
 | 
   148     dev.rate = mean(n12 + n23)
 | 
| 
 | 
   149     return(dev.rate)
 | 
| 
 | 
   150 }
 | 
| 
 | 
   151 
 | 
| 
 | 
   152 dev.old = function(temperature) {
 | 
| 
 | 
   153     n34 <- -0.6119 * temperature + 17.602
 | 
| 
 | 
   154     n45 <- -0.4408 * temperature + 19.036
 | 
| 
 | 
   155     dev.rate = mean(n34 + n45)
 | 
| 
 | 
   156     return(dev.rate)
 | 
| 
 | 
   157 }
 | 
| 
 | 
   158 
 | 
| 
 | 
   159 dev.emerg = function(temperature) {
 | 
| 
 | 
   160     emerg.rate <- -0.5332 * temperature + 24.147
 | 
| 
 | 
   161     return(emerg.rate)
 | 
| 
 | 
   162 }
 | 
| 
 | 
   163 
 | 
| 
 | 
   164 mortality.egg = function(temperature) {
 | 
| 
 | 
   165     if (temperature < 12.7) {
 | 
| 
 | 
   166         mort.prob = 0.8
 | 
| 
 | 
   167     }
 | 
| 
 | 
   168     else {
 | 
| 
 | 
   169         mort.prob = 0.8 - temperature / 40.0
 | 
| 
 | 
   170         if (mort.prob < 0) {
 | 
| 
 | 
   171             mort.prob = 0.01
 | 
| 
 | 
   172         }
 | 
| 
 | 
   173     }
 | 
| 
 | 
   174     return(mort.prob)
 | 
| 
 | 
   175 }
 | 
| 
 | 
   176 
 | 
| 
 | 
   177 mortality.nymph = function(temperature) {
 | 
| 
 | 
   178     if (temperature < 12.7) {
 | 
| 
 | 
   179         mort.prob = 0.03
 | 
| 
 | 
   180     }
 | 
| 
 | 
   181     else {
 | 
| 
 | 
   182         mort.prob = temperature * 0.0008 + 0.03
 | 
| 
 | 
   183     }
 | 
| 
 | 
   184     return(mort.prob)
 | 
| 
 | 
   185 }
 | 
| 
 | 
   186 
 | 
| 
 | 
   187 mortality.adult = function(temperature) {
 | 
| 
 | 
   188     if (temperature < 12.7) {
 | 
| 
 | 
   189         mort.prob = 0.002
 | 
| 
 | 
   190     }
 | 
| 
 | 
   191     else {
 | 
| 
 | 
   192         mort.prob = temperature * 0.0005 + 0.02
 | 
| 
 | 
   193     }
 | 
| 
 | 
   194     return(mort.prob)
 | 
| 
 | 
   195 }
 | 
| 
 | 
   196 
 | 
| 
 | 
   197 temperature_data_frame <- parse_input_data(opt$input, opt$num_days)
 | 
| 
 | 
   198 # All latitude values are the same,
 | 
| 
 | 
   199 # so get the value from the first row.
 | 
| 
 | 
   200 latitude <- temperature_data_frame$LATITUDE[1]
 | 
| 
 | 
   201 
 | 
| 
 | 
   202 cat("Number of days: ", opt$num_days, "\n")
 | 
| 
 | 
   203 
 | 
| 
 | 
   204 # Initialize matrix for results from all replications.
 | 
| 
 | 
   205 S0.rep <- S1.rep <- S2.rep <- S3.rep <- S4.rep <- S5.rep <- matrix(rep(0, opt$num_days * opt$replications), ncol = opt$replications)
 | 
| 
 | 
   206 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)
 | 
| 
 | 
   207 
 | 
| 
 | 
   208 # Loop through replications.
 | 
| 
 | 
   209 for (N.rep in 1:opt$replications) {
 | 
| 
 | 
   210     # During each replication start with 1000 individuals.
 | 
| 
 | 
   211     # TODO: user definable as well?
 | 
| 
 | 
   212     n <- 1000
 | 
| 
 | 
   213     # Generation, Stage, DD, T, Diapause.
 | 
| 
 | 
   214     vec.ini <- c(0, 3, 0, 0, 0)
 | 
| 
 | 
   215     # Overwintering, previttelogenic, DD=0, T=0, no-diapause.
 | 
| 
 | 
   216     vec.mat <- rep(vec.ini, n)
 | 
| 
 | 
   217     # Complete matrix for the population.
 | 
| 
 | 
   218     vec.mat <- base::t(matrix(vec.mat, nrow=5))
 | 
| 
 | 
   219     # Time series of population size.
 | 
| 
 | 
   220     tot.pop <- NULL
 | 
| 
 | 
   221     gen0.pop <- rep(0, opt$num_days)
 | 
| 
 | 
   222     gen1.pop <- rep(0, opt$num_days)
 | 
| 
 | 
   223     gen2.pop <- rep(0, opt$num_days)
 | 
| 
 | 
   224     S0 <- S1 <- S2 <- S3 <- S4 <- S5 <- rep(0, opt$num_days)
 | 
| 
 | 
   225     g0.adult <- g1.adult <- g2.adult <- rep(0, opt$num_days)
 | 
| 
 | 
   226     N.newborn <- N.death <- N.adult <- rep(0, opt$num_days)
 | 
| 
 | 
   227     dd.day <- rep(0, opt$num_days)
 | 
| 
 | 
   228     # All the days included in the input temperature dataset.
 | 
| 
 | 
   229     for (row in 1:opt$num_days) {
 | 
| 
 | 
   230         # Get the integer day of the year for the current row.
 | 
| 
 | 
   231         doy <- temperature_data_frame$DOY[row]
 | 
| 
 | 
   232         # Photoperiod in the day.
 | 
| 
 | 
   233         photoperiod <- temperature_data_frame$DAYLEN[row]
 | 
| 
 | 
   234         temp.profile <- get_temperature_at_hour(latitude, temperature_data_frame, row, opt$num_days)
 | 
| 
 | 
   235         mean.temp <- temp.profile[1]
 | 
| 
 | 
   236         dd.temp <- temp.profile[2]
 | 
| 
 | 
   237         dd.day[row] <- dd.temp
 | 
| 
 | 
   238         # Trash bin for death.
 | 
| 
 | 
   239         death.vec <- NULL
 | 
| 
 | 
   240         # Newborn.
 | 
| 
 | 
   241         birth.vec <- NULL
 | 
| 
 | 
   242         # All individuals.
 | 
| 
 | 
   243         for (i in 1:n) {
 | 
| 
 | 
   244             # Find individual record.
 | 
| 
 | 
   245             vec.ind <- vec.mat[i,]
 | 
| 
 | 
   246             # First of all, still alive?
 | 
| 
 | 
   247             # Adjustment for late season mortality rate.
 | 
| 
 | 
   248             if (latitude < 40.0) {
 | 
| 
 | 
   249                 post.mort <- 1
 | 
| 
 | 
   250                 day.kill <- 300
 | 
| 
 | 
   251             }
 | 
| 
 | 
   252             else {
 | 
| 
 | 
   253                 post.mort <- 2
 | 
| 
 | 
   254                 day.kill <- 250
 | 
| 
 | 
   255             }
 | 
| 
 | 
   256             if (vec.ind[2] == 0) {
 | 
| 
 | 
   257                 # Egg.
 | 
| 
 | 
   258                 death.prob = opt$egg_mort * mortality.egg(mean.temp)
 | 
| 
 | 
   259             }
 | 
| 
 | 
   260             else if (vec.ind[2] == 1 | vec.ind[2] == 2) {
 | 
| 
 | 
   261                 death.prob = opt$nymph_mort * mortality.nymph(mean.temp)
 | 
| 
 | 
   262             }
 | 
| 
 | 
   263             else if (vec.ind[2] == 3 | vec.ind[2] == 4 | vec.ind[2] == 5) {
 | 
| 
 | 
   264                 # For adult.
 | 
| 
 | 
   265                 if (doy < day.kill) {
 | 
| 
 | 
   266                     death.prob = opt$adult_mort * mortality.adult(mean.temp)
 | 
| 
 | 
   267                 }
 | 
| 
 | 
   268                 else {
 | 
| 
 | 
   269                     # Increase adult mortality after fall equinox.
 | 
| 
 | 
   270                     death.prob = opt$adult_mort * post.mort * mortality.adult(mean.temp)
 | 
| 
 | 
   271                 }
 | 
| 
 | 
   272             }
 | 
| 
 | 
   273             # (or dependent on temperature and life stage?)
 | 
| 
 | 
   274             u.d <- runif(1)
 | 
| 
 | 
   275             if (u.d < death.prob) {
 | 
| 
 | 
   276                 death.vec <- c(death.vec, i)
 | 
| 
 | 
   277             } 
 | 
| 
 | 
   278             else {
 | 
| 
 | 
   279                 # Aggregrate index of dead bug.
 | 
| 
 | 
   280                 # Event 1 end of diapause.
 | 
| 
 | 
   281                 if (vec.ind[1] == 0 && vec.ind[2] == 3) {
 | 
| 
 | 
   282                     # Overwintering adult (previttelogenic).
 | 
| 
 | 
   283                     if (photoperiod > opt$photoperiod && vec.ind[3] > 68 && doy < 180) {
 | 
| 
 | 
   284                         # Add 68C to become fully reproductively matured.
 | 
| 
 | 
   285                         # Transfer to vittelogenic.
 | 
| 
 | 
   286                         vec.ind <- c(0, 4, 0, 0, 0)
 | 
| 
 | 
   287                         vec.mat[i,] <- vec.ind
 | 
| 
 | 
   288                     }
 | 
| 
 | 
   289                     else {
 | 
| 
 | 
   290                         # Add to dd.
 | 
| 
 | 
   291                         vec.ind[3] <- vec.ind[3] + dd.temp
 | 
| 
 | 
   292                         # Add 1 day in current stage.
 | 
| 
 | 
   293                         vec.ind[4] <- vec.ind[4] + 1
 | 
| 
 | 
   294                         vec.mat[i,] <- vec.ind
 | 
| 
 | 
   295                     }
 | 
| 
 | 
   296                 }
 | 
| 
 | 
   297                 if (vec.ind[1] != 0 && vec.ind[2] == 3) {
 | 
| 
 | 
   298                     # Not overwintering adult (previttelogenic).
 | 
| 
 | 
   299                     current.gen <- vec.ind[1]
 | 
| 
 | 
   300                     if (vec.ind[3] > 68) {
 | 
| 
 | 
   301                         # Add 68C to become fully reproductively matured.
 | 
| 
 | 
   302                         # Transfer to vittelogenic.
 | 
| 
 | 
   303                         vec.ind <- c(current.gen, 4, 0, 0, 0)
 | 
| 
 | 
   304                         vec.mat[i,] <- vec.ind
 | 
| 
 | 
   305                     }
 | 
| 
 | 
   306                     else {
 | 
| 
 | 
   307                         # Add to dd.
 | 
| 
 | 
   308                         vec.ind[3] <- vec.ind[3] + dd.temp
 | 
| 
 | 
   309                         # Add 1 day in current stage.
 | 
| 
 | 
   310                         vec.ind[4] <- vec.ind[4] + 1
 | 
| 
 | 
   311                         vec.mat[i,] <- vec.ind
 | 
| 
 | 
   312                     }
 | 
| 
 | 
   313                 }
 | 
| 
 | 
   314                 # Event 2 oviposition -- where population dynamics comes from.
 | 
| 
 | 
   315                 if (vec.ind[2] == 4 && vec.ind[1] == 0 && mean.temp > 10) {
 | 
| 
 | 
   316                     # Vittelogenic stage, overwintering generation.
 | 
| 
 | 
   317                     if (vec.ind[4] == 0) {
 | 
| 
 | 
   318                         # Just turned in vittelogenic stage.
 | 
| 
 | 
   319                         n.birth=round(runif(1, 2 + opt$min_clutch_size, 8 + opt$max_clutch_size))
 | 
| 
 | 
   320                     }
 | 
| 
 | 
   321                     else {
 | 
| 
 | 
   322                         # Daily probability of birth.
 | 
| 
 | 
   323                         p.birth = opt$oviposition * 0.01
 | 
| 
 | 
   324                         u1 <- runif(1)
 | 
| 
 | 
   325                         if (u1 < p.birth) {
 | 
| 
 | 
   326                             n.birth=round(runif(1, 2, 8))
 | 
| 
 | 
   327                         }
 | 
| 
 | 
   328                     }
 | 
| 
 | 
   329                     # Add to dd.
 | 
| 
 | 
   330                     vec.ind[3] <- vec.ind[3] + dd.temp
 | 
| 
 | 
   331                     # Add 1 day in current stage.
 | 
| 
 | 
   332                     vec.ind[4] <- vec.ind[4] + 1
 | 
| 
 | 
   333                     vec.mat[i,] <- vec.ind
 | 
| 
 | 
   334                     if (n.birth > 0) {
 | 
| 
 | 
   335                         # Add new birth -- might be in different generations.
 | 
| 
 | 
   336                         new.gen <- vec.ind[1] + 1
 | 
| 
 | 
   337                         # Egg profile.
 | 
| 
 | 
   338                         new.ind <- c(new.gen, 0, 0, 0, 0)
 | 
| 
 | 
   339                         new.vec <- rep(new.ind, n.birth)
 | 
| 
 | 
   340                         # Update batch of egg profile.
 | 
| 
 | 
   341                         new.vec <- t(matrix(new.vec, nrow=5))
 | 
| 
 | 
   342                         # Group with total eggs laid in that day.
 | 
| 
 | 
   343                         birth.vec <- rbind(birth.vec, new.vec)
 | 
| 
 | 
   344                     }
 | 
| 
 | 
   345                 }
 | 
| 
 | 
   346                 # Event 2 oviposition -- for generation 1.
 | 
| 
 | 
   347                 if (vec.ind[2] == 4 && vec.ind[1] == 1 && mean.temp > 12.5 && doy < 222) {
 | 
| 
 | 
   348                     # Vittelogenic stage, 1st generation
 | 
| 
 | 
   349                     if (vec.ind[4] == 0) {
 | 
| 
 | 
   350                         # Just turned in vittelogenic stage.
 | 
| 
 | 
   351                         n.birth=round(runif(1, 2 + opt$min_clutch_size, 8 + opt$max_clutch_size))
 | 
| 
 | 
   352                     }
 | 
| 
 | 
   353                     else {
 | 
| 
 | 
   354                         # Daily probability of birth.
 | 
| 
 | 
   355                         p.birth = opt$oviposition * 0.01
 | 
| 
 | 
   356                         u1 <- runif(1)
 | 
| 
 | 
   357                         if (u1 < p.birth) {
 | 
| 
 | 
   358                             n.birth = round(runif(1, 2, 8))
 | 
| 
 | 
   359                         }
 | 
| 
 | 
   360                     }
 | 
| 
 | 
   361                     # Add to dd.
 | 
| 
 | 
   362                     vec.ind[3] <- vec.ind[3] + dd.temp
 | 
| 
 | 
   363                     # Add 1 day in current stage.
 | 
| 
 | 
   364                     vec.ind[4] <- vec.ind[4] + 1
 | 
| 
 | 
   365                     vec.mat[i,] <- vec.ind
 | 
| 
 | 
   366                     if (n.birth > 0) {
 | 
| 
 | 
   367                         # Add new birth -- might be in different generations.
 | 
| 
 | 
   368                         new.gen <- vec.ind[1] + 1
 | 
| 
 | 
   369                         # Egg profile.
 | 
| 
 | 
   370                         new.ind <- c(new.gen, 0, 0, 0, 0)
 | 
| 
 | 
   371                         new.vec <- rep(new.ind, n.birth)
 | 
| 
 | 
   372                         # Update batch of egg profile.
 | 
| 
 | 
   373                         new.vec <- t(matrix(new.vec, nrow=5))
 | 
| 
 | 
   374                         # Group with total eggs laid in that day.
 | 
| 
 | 
   375                         birth.vec <- rbind(birth.vec, new.vec)
 | 
| 
 | 
   376                     }
 | 
| 
 | 
   377                 }
 | 
| 
 | 
   378                 # Event 3 development (with diapause determination).
 | 
| 
 | 
   379                 # Event 3.1 egg development to young nymph (vec.ind[2]=0 -> egg).
 | 
| 
 | 
   380                 if (vec.ind[2] == 0) {
 | 
| 
 | 
   381                     # Egg stage.
 | 
| 
 | 
   382                     # Add to dd.
 | 
| 
 | 
   383                     vec.ind[3] <- vec.ind[3] + dd.temp
 | 
| 
 | 
   384                     if (vec.ind[3] >= (68 + opt$young_nymph_accum)) {
 | 
| 
 | 
   385                         # From egg to young nymph, DD requirement met.
 | 
| 
 | 
   386                         current.gen <- vec.ind[1]
 | 
| 
 | 
   387                         # Transfer to young nymph stage.
 | 
| 
 | 
   388                         vec.ind <- c(current.gen, 1, 0, 0, 0)
 | 
| 
 | 
   389                     }
 | 
| 
 | 
   390                     else {
 | 
| 
 | 
   391                         # Add 1 day in current stage.
 | 
| 
 | 
   392                         vec.ind[4] <- vec.ind[4] + 1
 | 
| 
 | 
   393                     }
 | 
| 
 | 
   394                     vec.mat[i,] <- vec.ind
 | 
| 
 | 
   395                 }
 | 
| 
 | 
   396                 # Event 3.2 young nymph to old nymph (vec.ind[2]=1 -> young nymph: determines diapause).
 | 
| 
 | 
   397                 if (vec.ind[2] == 1) {
 | 
| 
 | 
   398                     # young nymph stage.
 | 
| 
 | 
   399                     # add to dd.
 | 
| 
 | 
   400                     vec.ind[3] <- vec.ind[3] + dd.temp
 | 
| 
 | 
   401                     if (vec.ind[3] >= (250 + opt$old_nymph_accum)) {
 | 
| 
 | 
   402                         # From young to old nymph, dd requirement met.
 | 
| 
 | 
   403                         current.gen <- vec.ind[1]
 | 
| 
 | 
   404                         # Transfer to old nym stage.
 | 
| 
 | 
   405                         vec.ind <- c(current.gen, 2, 0, 0, 0)
 | 
| 
 | 
   406                         if (photoperiod < opt$photoperiod && doy > 180) {
 | 
| 
 | 
   407                             vec.ind[5] <- 1
 | 
| 
 | 
   408                         } # Prepare for diapausing.
 | 
| 
 | 
   409                     }
 | 
| 
 | 
   410                     else {
 | 
| 
 | 
   411                         # Add 1 day in current stage.
 | 
| 
 | 
   412                         vec.ind[4] <- vec.ind[4] + 1
 | 
| 
 | 
   413                     }
 | 
| 
 | 
   414                     vec.mat[i,] <- vec.ind
 | 
| 
 | 
   415                 }  
 | 
| 
 | 
   416                 # Event 3.3 old nymph to adult: previttelogenic or diapausing?
 | 
| 
 | 
   417                 if (vec.ind[2] == 2) {
 | 
| 
 | 
   418                     # Old nymph stage.
 | 
| 
 | 
   419                     # add to dd.
 | 
| 
 | 
   420                     vec.ind[3] <- vec.ind[3] + dd.temp
 | 
| 
 | 
   421                     if (vec.ind[3] >= (200 + opt$adult_accum)) {
 | 
| 
 | 
   422                         # From old to adult, dd requirement met.
 | 
| 
 | 
   423                         current.gen <- vec.ind[1]
 | 
| 
 | 
   424                         if (vec.ind[5] == 0) {
 | 
| 
 | 
   425                             # Non-diapausing adult -- previttelogenic.
 | 
| 
 | 
   426                             vec.ind <- c(current.gen, 3, 0, 0, 0)
 | 
| 
 | 
   427                         }
 | 
| 
 | 
   428                         else {
 | 
| 
 | 
   429                             # Diapausing.
 | 
| 
 | 
   430                             vec.ind <- c(current.gen, 5, 0, 0, 1)
 | 
| 
 | 
   431                         }
 | 
| 
 | 
   432                     }
 | 
| 
 | 
   433                     else {
 | 
| 
 | 
   434                         # Add 1 day in current stage.
 | 
| 
 | 
   435                         vec.ind[4] <- vec.ind[4] + 1
 | 
| 
 | 
   436                     }
 | 
| 
 | 
   437                     vec.mat[i,] <- vec.ind
 | 
| 
 | 
   438                 }
 | 
| 
 | 
   439                 # Event 4 growing of diapausing adult (unimportant, but still necessary).
 | 
| 
 | 
   440                 if (vec.ind[2] == 5) {
 | 
| 
 | 
   441                     vec.ind[3] <- vec.ind[3] + dd.temp
 | 
| 
 | 
   442                     vec.ind[4] <- vec.ind[4] + 1
 | 
| 
 | 
   443                     vec.mat[i,] <- vec.ind
 | 
| 
 | 
   444                 }
 | 
| 
 | 
   445             } # Else if it is still alive.
 | 
| 
 | 
   446         } # End of the individual bug loop.
 | 
| 
 | 
   447         # Find how many died.
 | 
| 
 | 
   448         n.death <- length(death.vec)
 | 
| 
 | 
   449         if (n.death > 0) {
 | 
| 
 | 
   450             vec.mat <- vec.mat[-death.vec, ]
 | 
| 
 | 
   451         }
 | 
| 
 | 
   452         # Remove record of dead.
 | 
| 
 | 
   453         # Find how many new born.
 | 
| 
 | 
   454         n.newborn <- length(birth.vec[,1])
 | 
| 
 | 
   455         vec.mat <- rbind(vec.mat, birth.vec)
 | 
| 
 | 
   456         # Update population size for the next day.
 | 
| 
 | 
   457         n <- n - n.death + n.newborn 
 | 
| 
 | 
   458 
 | 
| 
 | 
   459         # Aggregate results by day.
 | 
| 
 | 
   460         tot.pop <- c(tot.pop, n) 
 | 
| 
 | 
   461         # Egg.
 | 
| 
 | 
   462         s0 <- sum(vec.mat[,2] == 0)
 | 
| 
 | 
   463         # Young nymph.
 | 
| 
 | 
   464         s1 <- sum(vec.mat[,2] == 1)
 | 
| 
 | 
   465         # Old nymph.
 | 
| 
 | 
   466         s2 <- sum(vec.mat[,2] == 2)
 | 
| 
 | 
   467         # Previtellogenic.
 | 
| 
 | 
   468         s3 <- sum(vec.mat[,2] == 3)
 | 
| 
 | 
   469         # Vitellogenic.
 | 
| 
 | 
   470         s4 <- sum(vec.mat[,2] == 4)
 | 
| 
 | 
   471         # Diapausing.
 | 
| 
 | 
   472         s5 <- sum(vec.mat[,2] == 5)
 | 
| 
 | 
   473         # Overwintering adult.
 | 
| 
 | 
   474         gen0 <- sum(vec.mat[,1] == 0)
 | 
| 
 | 
   475         # First generation.
 | 
| 
 | 
   476         gen1 <- sum(vec.mat[,1] == 1)
 | 
| 
 | 
   477         # Second generation.
 | 
| 
 | 
   478         gen2 <- sum(vec.mat[,1] == 2)
 | 
| 
 | 
   479         # Sum of all adults.
 | 
| 
 | 
   480         n.adult <- sum(vec.mat[,2] == 3) + sum(vec.mat[,2] == 4) + sum(vec.mat[,2] == 5)
 | 
| 
 | 
   481 
 | 
| 
 | 
   482         # Generation 0 pop size.
 | 
| 
 | 
   483         gen0.pop[row] <- gen0
 | 
| 
 | 
   484         gen1.pop[row] <- gen1
 | 
| 
 | 
   485         gen2.pop[row] <- gen2
 | 
| 
 | 
   486 
 | 
| 
 | 
   487         S0[row] <- s0
 | 
| 
 | 
   488         S1[row] <- s1
 | 
| 
 | 
   489         S2[row] <- s2
 | 
| 
 | 
   490         S3[row] <- s3
 | 
| 
 | 
   491         S4[row] <- s4
 | 
| 
 | 
   492         S5[row] <- s5
 | 
| 
 | 
   493 
 | 
| 
 | 
   494         g0.adult[row] <- sum(vec.mat[,1] == 0)
 | 
| 
 | 
   495         g1.adult[row] <- 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))
 | 
| 
 | 
   496         g2.adult[row] <- 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))
 | 
| 
 | 
   497 
 | 
| 
 | 
   498         N.newborn[row] <- n.newborn
 | 
| 
 | 
   499         N.death[row] <- n.death
 | 
| 
 | 
   500         N.adult[row] <- n.adult
 | 
| 
 | 
   501     }   # end of days specified in the input temperature data
 | 
| 
 | 
   502 
 | 
| 
 | 
   503     dd.cum <- cumsum(dd.day)
 | 
| 
 | 
   504 
 | 
| 
 | 
   505     # Collect all the outputs.
 | 
| 
 | 
   506     S0.rep[,N.rep] <- S0
 | 
| 
 | 
   507     S1.rep[,N.rep] <- S1
 | 
| 
 | 
   508     S2.rep[,N.rep] <- S2
 | 
| 
 | 
   509     S3.rep[,N.rep] <- S3
 | 
| 
 | 
   510     S4.rep[,N.rep] <- S4
 | 
| 
 | 
   511     S5.rep[,N.rep] <- S5
 | 
| 
 | 
   512     newborn.rep[,N.rep] <- N.newborn
 | 
| 
 | 
   513     death.rep[,N.rep] <- N.death
 | 
| 
 | 
   514     adult.rep[,N.rep] <- N.adult
 | 
| 
 | 
   515     pop.rep[,N.rep] <- tot.pop
 | 
| 
 | 
   516     g0.rep[,N.rep] <- gen0.pop
 | 
| 
 | 
   517     g1.rep[,N.rep] <- gen1.pop
 | 
| 
 | 
   518     g2.rep[,N.rep] <- gen2.pop
 | 
| 
 | 
   519     g0a.rep[,N.rep] <- g0.adult
 | 
| 
 | 
   520     g1a.rep[,N.rep] <- g1.adult
 | 
| 
 | 
   521     g2a.rep[,N.rep] <- g2.adult
 | 
| 
 | 
   522 }
 | 
| 
 | 
   523 
 | 
| 
 | 
   524 # Data analysis and visualization can currently
 | 
| 
 | 
   525 # plot only within a single calendar year.
 | 
| 
 | 
   526 # TODO: enhance this to accomodate multiple calendar years.
 | 
| 
 | 
   527 start_date <- temperature_data_frame$DATE[1]
 | 
| 
 | 
   528 end_date <- temperature_data_frame$DATE[opt$num_days]
 | 
| 
 | 
   529 
 | 
| 
 | 
   530 n.yr <- 1
 | 
| 
 | 
   531 day.all <- c(1:opt$num_days * n.yr)
 | 
| 
 | 
   532 
 | 
| 
 | 
   533 # mean value for adults
 | 
| 
 | 
   534 sa <- apply((S3.rep + S4.rep + S5.rep), 1, mean)
 | 
| 
 | 
   535 # mean value for nymphs
 | 
| 
 | 
   536 sn <- apply((S1.rep + S2.rep), 1,mean)
 | 
| 
 | 
   537 # mean value for eggs
 | 
| 
 | 
   538 se <- apply(S0.rep, 1, mean)
 | 
| 
 | 
   539 # mean value for P
 | 
| 
 | 
   540 g0 <- apply(g0.rep, 1, mean)
 | 
| 
 | 
   541 # mean value for F1
 | 
| 
 | 
   542 g1 <- apply(g1.rep, 1, mean)
 | 
| 
 | 
   543 # mean value for F2
 | 
| 
 | 
   544 g2 <- apply(g2.rep, 1, mean)
 | 
| 
 | 
   545 # mean value for P adult
 | 
| 
 | 
   546 g0a <- apply(g0a.rep, 1, mean)
 | 
| 
 | 
   547 # mean value for F1 adult
 | 
| 
 | 
   548 g1a <- apply(g1a.rep, 1, mean)
 | 
| 
 | 
   549 # mean value for F2 adult
 | 
| 
 | 
   550 g2a <- apply(g2a.rep, 1, mean)
 | 
| 
 | 
   551 
 | 
| 
 | 
   552 # SE for adults
 | 
| 
 | 
   553 sa.se <- apply((S3.rep + S4.rep + S5.rep), 1, sd) / sqrt(opt$replications)
 | 
| 
 | 
   554 # SE for nymphs
 | 
| 
 | 
   555 sn.se <- apply((S1.rep + S2.rep) / sqrt(opt$replications), 1, sd)
 | 
| 
 | 
   556 # SE for eggs
 | 
| 
 | 
   557 se.se <- apply(S0.rep, 1, sd) / sqrt(opt$replications)
 | 
| 
 | 
   558 # SE value for P
 | 
| 
 | 
   559 g0.se <- apply(g0.rep, 1, sd) / sqrt(opt$replications)
 | 
| 
 | 
   560 # SE for F1
 | 
| 
 | 
   561 g1.se <- apply(g1.rep, 1, sd) / sqrt(opt$replications)
 | 
| 
 | 
   562 # SE for F2
 | 
| 
 | 
   563 g2.se <- apply(g2.rep, 1, sd) / sqrt(opt$replications)
 | 
| 
 | 
   564 # SE for P adult
 | 
| 
 | 
   565 g0a.se <- apply(g0a.rep, 1, sd) / sqrt(opt$replications)
 | 
| 
 | 
   566 # SE for F1 adult
 | 
| 
 | 
   567 g1a.se <- apply(g1a.rep, 1, sd) / sqrt(opt$replications)
 | 
| 
 | 
   568 # SE for F2 adult
 | 
| 
 | 
   569 g2a.se <- apply(g2a.rep, 1, sd) / sqrt(opt$replications)
 | 
| 
 | 
   570 
 | 
| 
 | 
   571 dev.new(width=20, height=30)
 | 
| 
 | 
   572 
 | 
| 
 | 
   573 # Start PDF device driver to save charts to output.
 | 
| 
 | 
   574 pdf(file=opt$output, width=20, height=30, bg="white")
 | 
| 
 | 
   575 
 | 
| 
 | 
   576 par(mar = c(5, 6, 4, 4), mfrow=c(3, 1))
 | 
| 
 | 
   577 
 | 
| 
 | 
   578 # Subfigure 1: population size by life stage
 | 
| 
88
 | 
   579 title <- paste(opt$insect, ": Total pop. by life stage :", opt$location, ": Lat:", latitude, ":", start_date, "-", end_date, sep=" ")
 | 
| 
85
 | 
   580 plot(day.all, sa, main=title, type="l", ylim=c(0, max(se + se.se, sn + sn.se, sa + sa.se)), axes=F, lwd=2, xlab="", ylab="", cex=3, cex.lab=3, cex.axis=3, cex.main=3)
 | 
| 
 | 
   581 # Young and old nymphs.
 | 
| 
 | 
   582 lines(day.all, sn, lwd=2, lty=1, col=2)
 | 
| 
 | 
   583 # Eggs
 | 
| 
 | 
   584 lines(day.all, se, lwd=2, lty=1, col=4)
 | 
| 
 | 
   585 axis(1, at=c(1:12) * 30 - 15, cex.axis=3, labels=c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"))
 | 
| 
 | 
   586 axis(2, cex.axis=3)
 | 
| 
 | 
   587 leg.text <- c("Egg", "Nymph", "Adult")
 | 
| 
 | 
   588 legend("topleft", leg.text, lty=c(1, 1, 1), col=c(4, 2, 1), cex=3)
 | 
| 
 | 
   589 if (opt$se_plot == 1) {
 | 
| 
 | 
   590     # Add SE lines to plot
 | 
| 
 | 
   591     # SE for adults
 | 
| 
 | 
   592     lines (day.all, sa + sa.se, lty=2)
 | 
| 
 | 
   593     lines (day.all, sa - sa.se, lty=2) 
 | 
| 
 | 
   594     # SE for nymphs
 | 
| 
 | 
   595     lines (day.all, sn + sn.se, col=2, lty=2)
 | 
| 
 | 
   596     lines (day.all, sn - sn.se, col=2, lty=2)
 | 
| 
 | 
   597     # SE for eggs
 | 
| 
 | 
   598     lines (day.all, se + se.se, col=4, lty=2)
 | 
| 
 | 
   599     lines (day.all, se - se.se, col=4, lty=2)
 | 
| 
 | 
   600 }
 | 
| 
 | 
   601 
 | 
| 
 | 
   602 # Subfigure 2: population size by generation
 | 
| 
88
 | 
   603 title <- paste(opt$insect, ": Total pop. by generation :", opt$location, ": Lat:", latitude, ":", start_date, "-", end_date, sep=" ")
 | 
| 
85
 | 
   604 plot(day.all, g0, main=title, type="l", ylim=c(0, max(g2)), axes=F, lwd=2, xlab="", ylab="", cex=3, cex.lab=3, cex.axis=3, cex.main=3)
 | 
| 
 | 
   605 lines(day.all, g1, lwd = 2, lty = 1, col=2)
 | 
| 
 | 
   606 lines(day.all, g2, lwd = 2, lty = 1, col=4)
 | 
| 
 | 
   607 axis(1, at=c(1:12) * 30 - 15, cex.axis=3, labels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"))
 | 
| 
 | 
   608 axis(2, cex.axis=3)
 | 
| 
 | 
   609 leg.text <- c("P", "F1", "F2")
 | 
| 
 | 
   610 legend("topleft", leg.text, lty=c(1, 1, 1), col=c(1, 2, 4), cex=3)
 | 
| 
 | 
   611 if (opt$se_plot == 1) {
 | 
| 
 | 
   612     # Add SE lines to plot
 | 
| 
 | 
   613     # SE for adults
 | 
| 
 | 
   614     lines (day.all, g0+g0.se, lty=2)
 | 
| 
 | 
   615     lines (day.all, g0-g0.se, lty=2) 
 | 
| 
 | 
   616     # SE for nymphs
 | 
| 
 | 
   617     lines (day.all, g1+g1.se, col=2, lty=2)
 | 
| 
 | 
   618     lines (day.all, g1-g1.se, col=2, lty=2)
 | 
| 
 | 
   619     # SE for eggs
 | 
| 
 | 
   620     lines (day.all, g2+g2.se, col=4, lty=2)
 | 
| 
 | 
   621     lines (day.all, g2-g2.se, col=4, lty=2)
 | 
| 
 | 
   622 }
 | 
| 
 | 
   623 
 | 
| 
 | 
   624 # Subfigure 3: adult population size by generation
 | 
| 
88
 | 
   625 title <- paste(opt$insect, ": Adult pop. by generation :", opt$location, ": Lat:", latitude, ":", start_date, "-", end_date, sep=" ")
 | 
| 
85
 | 
   626 plot(day.all, g0a, ylim=c(0, max(g2a) + 100), main=title, type="l", axes=F, lwd=2, xlab="", ylab="", cex=3, cex.lab=3, cex.axis=3, cex.main=3)
 | 
| 
 | 
   627 lines(day.all, g1a, lwd = 2, lty = 1, col=2)
 | 
| 
 | 
   628 lines(day.all, g2a, lwd = 2, lty = 1, col=4)
 | 
| 
 | 
   629 axis(1, at=c(1:12) * 30 - 15, cex.axis=3, labels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"))
 | 
| 
 | 
   630 axis(2, cex.axis=3)
 | 
| 
 | 
   631 leg.text <- c("P", "F1", "F2")
 | 
| 
 | 
   632 legend("topleft", leg.text, lty=c(1, 1, 1), col=c(1, 2, 4), cex=3)
 | 
| 
 | 
   633 if (opt$se_plot == 1) {
 | 
| 
 | 
   634     # Add SE lines to plot
 | 
| 
 | 
   635     # SE for adults
 | 
| 
 | 
   636     lines (day.all, g0a+g0a.se, lty=2)
 | 
| 
 | 
   637     lines (day.all, g0a-g0a.se, lty=2) 
 | 
| 
 | 
   638     # SE for nymphs
 | 
| 
 | 
   639     lines (day.all, g1a+g1a.se, col=2, lty=2)
 | 
| 
 | 
   640     lines (day.all, g1a-g1a.se, col=2, lty=2)
 | 
| 
 | 
   641     # SE for eggs
 | 
| 
 | 
   642     lines (day.all, g2a+g2a.se, col=4, lty=2)
 | 
| 
 | 
   643     lines (day.all, g2a-g2a.se, col=4, lty=2)
 | 
| 
 | 
   644 }
 | 
| 
 | 
   645 
 | 
| 
 | 
   646 # Turn off device driver to flush output.
 | 
| 
 | 
   647 dev.off()
 |