Mercurial > repos > greg > insect_phenology_model
comparison insect_phenology_model.R @ 117:9c998fd06628 draft
Uploaded
author | greg |
---|---|
date | Tue, 29 May 2018 14:18:14 -0400 |
parents | bcb12b7e8563 |
children | 833f70d9001d |
comparison
equal
deleted
inserted
replaced
116:88b409324611 | 117:9c998fd06628 |
---|---|
4 | 4 |
5 option_list <- list( | 5 option_list <- list( |
6 make_option(c("--adult_mortality"), action="store", dest="adult_mortality", type="integer", help="Adjustment rate for adult mortality"), | 6 make_option(c("--adult_mortality"), action="store", dest="adult_mortality", type="integer", help="Adjustment rate for adult mortality"), |
7 make_option(c("--adult_accumulation"), action="store", dest="adult_accumulation", type="integer", help="Adjustment of degree-days accumulation (old nymph->adult)"), | 7 make_option(c("--adult_accumulation"), action="store", dest="adult_accumulation", type="integer", help="Adjustment of degree-days accumulation (old nymph->adult)"), |
8 make_option(c("--egg_mortality"), action="store", dest="egg_mortality", type="integer", help="Adjustment rate for egg mortality"), | 8 make_option(c("--egg_mortality"), action="store", dest="egg_mortality", type="integer", help="Adjustment rate for egg mortality"), |
9 make_option(c("--end_date"), action="store", dest="end_date", default=NULL, help="End date for custom date interval"), | |
9 make_option(c("--input_norm"), action="store", dest="input_norm", help="30 year normals temperature data for selected station"), | 10 make_option(c("--input_norm"), action="store", dest="input_norm", help="30 year normals temperature data for selected station"), |
10 make_option(c("--input_ytd"), action="store", dest="input_ytd", default=NULL, help="Year-to-date temperature data for selected location"), | 11 make_option(c("--input_ytd"), action="store", dest="input_ytd", default=NULL, help="Year-to-date temperature data for selected location"), |
11 make_option(c("--insect"), action="store", dest="insect", help="Insect name"), | 12 make_option(c("--insect"), action="store", dest="insect", help="Insect name"), |
12 make_option(c("--insects_per_replication"), action="store", dest="insects_per_replication", type="integer", help="Number of insects with which to start each replication"), | 13 make_option(c("--insects_per_replication"), action="store", dest="insects_per_replication", type="integer", help="Number of insects with which to start each replication"), |
13 make_option(c("--life_stages"), action="store", dest="life_stages", help="Selected life stages for plotting"), | 14 make_option(c("--life_stages"), action="store", dest="life_stages", help="Selected life stages for plotting"), |
22 make_option(c("--oviposition"), action="store", dest="oviposition", type="integer", help="Adjustment for oviposition rate"), | 23 make_option(c("--oviposition"), action="store", dest="oviposition", type="integer", help="Adjustment for oviposition rate"), |
23 make_option(c("--photoperiod"), action="store", dest="photoperiod", type="double", help="Critical photoperiod for diapause induction/termination"), | 24 make_option(c("--photoperiod"), action="store", dest="photoperiod", type="double", help="Critical photoperiod for diapause induction/termination"), |
24 make_option(c("--plot_generations_separately"), action="store", dest="plot_generations_separately", help="Plot Plot P, F1 and F2 as separate lines or pool across them"), | 25 make_option(c("--plot_generations_separately"), action="store", dest="plot_generations_separately", help="Plot Plot P, F1 and F2 as separate lines or pool across them"), |
25 make_option(c("--plot_std_error"), action="store", dest="plot_std_error", help="Plot Standard error"), | 26 make_option(c("--plot_std_error"), action="store", dest="plot_std_error", help="Plot Standard error"), |
26 make_option(c("--replications"), action="store", dest="replications", type="integer", help="Number of replications"), | 27 make_option(c("--replications"), action="store", dest="replications", type="integer", help="Number of replications"), |
28 make_option(c("--start_date"), action="store", dest="start_date", default=NULL, help="Start date for custom date interval"), | |
27 make_option(c("--young_nymph_accumulation"), action="store", dest="young_nymph_accumulation", type="integer", help="Adjustment of degree-days accumulation (egg->young nymph)") | 29 make_option(c("--young_nymph_accumulation"), action="store", dest="young_nymph_accumulation", type="integer", help="Adjustment of degree-days accumulation (egg->young nymph)") |
28 ) | 30 ) |
29 | 31 |
30 parser <- OptionParser(usage="%prog [options] file", option_list=option_list); | 32 parser <- OptionParser(usage="%prog [options] file", option_list=option_list); |
31 args <- parse_args(parser, positional_arguments=TRUE); | 33 args <- parse_args(parser, positional_arguments=TRUE); |
141 tmin = norm_data_frame[index,"TMIN"][1]; | 143 tmin = norm_data_frame[index,"TMIN"][1]; |
142 tmax = norm_data_frame[index,"TMAX"][1]; | 144 tmax = norm_data_frame[index,"TMAX"][1]; |
143 return(list(latitude, longitude, date_str, doy, tmin, tmax)); | 145 return(list(latitude, longitude, date_str, doy, tmin, tmax)); |
144 } | 146 } |
145 | 147 |
146 get_temperature_at_hour = function(latitude, temperature_data_frame, row, num_days) { | 148 get_temperature_at_hour = function(latitude, temperature_data_frame, row) { |
147 # Base development threshold for Brown Marmorated Stink Bug | 149 # Base development threshold for Brown Marmorated Stink Bug |
148 # insect phenology model. | 150 # insect phenology model. |
149 threshold = 14.17; | 151 threshold = 14.17; |
150 # Minimum temperature for current row. | 152 # Minimum temperature for current row. |
151 curr_min_temp = temperature_data_frame$TMIN[row]; | 153 curr_min_temp = temperature_data_frame$TMIN[row]; |
351 mortality.probability = temperature * 0.0008 + 0.03; | 353 mortality.probability = temperature * 0.0008 + 0.03; |
352 } | 354 } |
353 return(mortality.probability); | 355 return(mortality.probability); |
354 } | 356 } |
355 | 357 |
356 parse_input_data = function(input_ytd, input_norm, num_days_ytd, location) { | 358 parse_input_data = function(input_ytd, input_norm, num_days, location, start_date, end_date) { |
357 if (is.null(input_ytd)) { | 359 if (is.null(input_ytd)) { |
358 # We're analysing only the 30 year normals data, so create an empty | 360 # We're analysing only the 30 year normals data, so create an empty |
359 # data frame for containing temperature data after it is converted | 361 # data frame for containing temperature data after it is converted |
360 # from the 30 year normals format to the year-to-date format. | 362 # from the 30 year normals format to the year-to-date format. |
361 temperature_data_frame = data.frame(matrix(ncol=6, nrow=0)); | 363 temperature_data_frame = data.frame(matrix(ncol=6, nrow=0)); |
362 colnames(temperature_data_frame) = c("LATITUDE", "LONGITUDE", "DATE", "DOY", "TMIN", "TMAX"); | 364 colnames(temperature_data_frame) = c("LATITUDE", "LONGITUDE", "DATE", "DOY", "TMIN", "TMAX"); |
363 # Base all dates on the current date since 30 year | 365 # Base all dates on the current date since 30 year |
364 # normals data does not include any dates. | 366 # normals data does not include any dates. |
365 year = format(Sys.Date(), "%Y"); | 367 year = format(Sys.Date(), "%Y"); |
366 start_date = paste(year, "01", "01", sep="-"); | 368 if (is.null(start_date) && is.null(end_date)) { |
367 end_date = paste(year, "12", "31", sep="-"); | 369 start_date = paste(year, "01", "01", sep="-"); |
370 end_date = paste(year, "12", "31", sep="-"); | |
371 } else { | |
372 # Extract the month and day from the start date. | |
373 start_date_str = format(start_date); | |
374 start_date_str_items = strsplit(start_date_str, "-")[[1]]; | |
375 start_date_month = start_date_str_items[2]; | |
376 start_date_day = start_date_str_items[3]; | |
377 start_date = paste(year, start_date_month, start_date_day, sep="-"); | |
378 # Extract the month and day from the end date. | |
379 end_date_str = format(start_date); | |
380 end_date_str_items = strsplit(end_date_str, "-")[[1]]; | |
381 end_date_month = end_date_str_items[2]; | |
382 end_date_day = end_date_str_items[3]; | |
383 end_date = paste(year, start_date_month, start_date_day, sep="-"); | |
384 } | |
368 # Set invalid start and end DOY. | 385 # Set invalid start and end DOY. |
369 start_doy_ytd = 0; | 386 start_doy_ytd = 0; |
370 end_doy_ytd = 0; | 387 end_doy_ytd = 0; |
371 } else { | 388 } else { |
372 # Read the input_ytd temperature datafile into a data frame. | 389 # Read the input_ytd temperature data file into a data frame. |
373 # The input_ytd data has the following 6 columns: | 390 # The input_ytd data has the following 6 columns: |
374 # LATITUDE, LONGITUDE, DATE, DOY, TMIN, TMAX | 391 # LATITUDE, LONGITUDE, DATE, DOY, TMIN, TMAX |
375 temperature_data_frame = read.csv(file=input_ytd, header=T, strip.white=TRUE, stringsAsFactors=FALSE, sep=","); | 392 temperature_data_frame = read.csv(file=input_ytd, header=T, strip.white=TRUE, stringsAsFactors=FALSE, sep=","); |
376 # Set the temperature_data_frame column names for access. | 393 # Set the temperature_data_frame column names for access. |
377 colnames(temperature_data_frame) = c("LATITUDE", "LONGITUDE", "DATE", "DOY", "TMIN", "TMAX"); | 394 colnames(temperature_data_frame) = c("LATITUDE", "LONGITUDE", "DATE", "DOY", "TMIN", "TMAX"); |
378 # Get the start date. | 395 if (is.null(start_date) && is.null(end_date)) { |
379 start_date = temperature_data_frame$DATE[1]; | 396 # Get the start date. |
380 end_date = temperature_data_frame$DATE[num_days_ytd]; | 397 start_date = temperature_data_frame$DATE[1]; |
398 end_date = temperature_data_frame$DATE[num_days]; | |
399 } else { | |
400 # Extract the custom date interval from temperature_data_frame. | |
401 temperature_data_frame = temperature_data_frame[date %between% c(start_date, end_date)] | |
402 } | |
381 # Extract the year from the start date. | 403 # Extract the year from the start date. |
382 date_str = format(start_date); | 404 date_str = format(start_date); |
383 date_str_items = strsplit(date_str, "-")[[1]]; | 405 date_str_items = strsplit(date_str, "-")[[1]]; |
384 year = date_str_items[1]; | 406 year = date_str_items[1]; |
385 # Save the first DOY to later check if start_date is Jan 1. | 407 # Save the first DOY to later check if start_date is Jan 1. |
386 start_doy_ytd = as.integer(temperature_data_frame$DOY[1]); | 408 start_doy_ytd = as.integer(temperature_data_frame$DOY[1]); |
387 end_doy_ytd = as.integer(temperature_data_frame$DOY[num_days_ytd]); | 409 end_doy_ytd = as.integer(temperature_data_frame$DOY[num_days]); |
388 } | 410 } |
389 # See if we're in a leap year. | 411 # See if we're in a leap year. |
390 is_leap_year = is_leap_year(start_date); | 412 is_leap_year = is_leap_year(start_date); |
391 # Get the number of days in the year. | |
392 total_days = get_total_days(is_leap_year); | |
393 # Read the input_norm temperature datafile into a data frame. | 413 # Read the input_norm temperature datafile into a data frame. |
394 # The input_norm data has the following 10 columns: | 414 # The input_norm data has the following 10 columns: |
395 # STATIONID, LATITUDE, LONGITUDE, ELEV_M, NAME, ST, MMDD, DOY, TMIN, TMAX | 415 # STATIONID, LATITUDE, LONGITUDE, ELEV_M, NAME, ST, MMDD, DOY, TMIN, TMAX |
396 norm_data_frame = read.csv(file=input_norm, header=T, strip.white=TRUE, stringsAsFactors=FALSE, sep=","); | 416 norm_data_frame = read.csv(file=input_norm, header=T, strip.white=TRUE, stringsAsFactors=FALSE, sep=","); |
397 # Set the norm_data_frame column names for access. | 417 # Set the norm_data_frame column names for access. |
398 colnames(norm_data_frame) = c("STATIONID", "LATITUDE","LONGITUDE", "ELEV_M", "NAME", "ST", "MMDD", "DOY", "TMIN", "TMAX"); | 418 colnames(norm_data_frame) = c("STATIONID", "LATITUDE","LONGITUDE", "ELEV_M", "NAME", "ST", "MMDD", "DOY", "TMIN", "TMAX"); |
399 # All normals data includes Feb 29 which is row 60 in | 419 # All normals data includes Feb 29 which is row 60 in |
400 # the data, so delete that row if we're not in a leap year. | 420 # the data, so delete that row if we're not in a leap year. |
401 if (!is_leap_year) { | 421 if (!is_leap_year) { |
402 norm_data_frame = norm_data_frame[-c(60),]; | 422 norm_data_frame = norm_data_frame[-c(60),]; |
423 } | |
424 if (is.null(start_date) && is.null(end_date)) { | |
425 # Get the number of days in the year. | |
426 total_days = get_total_days(is_leap_year); | |
427 } else { | |
428 # Extract the custom date interval from norm_data_frame. | |
429 norm_data_frame = norm_data_frame[date %between% c(start_date, end_date)] | |
430 # Use the pre-determined num_days for total_days. | |
431 total_days = num_days | |
403 } | 432 } |
404 # Set the location to be the station name if the user elected no to enter it. | 433 # Set the location to be the station name if the user elected no to enter it. |
405 if (is.null(location) | length(location)==0) { | 434 if (is.null(location) | length(location)==0) { |
406 location = norm_data_frame$NAME[1]; | 435 location = norm_data_frame$NAME[1]; |
407 } | 436 } |
517 lines(days, group3-group3_std_error, col=4, lty=2); | 546 lines(days, group3-group3_std_error, col=4, lty=2); |
518 } | 547 } |
519 } | 548 } |
520 } | 549 } |
521 | 550 |
551 stop_err = function(msg) { | |
552 cat(msg, file=stderr()); | |
553 quit(save="no", status=1); | |
554 } | |
555 | |
556 validate_date = function(date_str) { | |
557 valid_date = as.Date(date_str, format="%Y-%m-%d"); | |
558 if( class(valid_date)=="try-error" || is.na(valid_date)) { | |
559 msg = paste("Invalid date: ", date_str, ", valid date format is yyyy-mm-dd.", sep=""); | |
560 stop_err(msg); | |
561 } | |
562 return(valid_date); | |
563 } | |
564 | |
522 # Determine if we're plotting generations separately. | 565 # Determine if we're plotting generations separately. |
523 if (opt$plot_generations_separately=="yes") { | 566 if (opt$plot_generations_separately=="yes") { |
524 plot_generations_separately = TRUE; | 567 plot_generations_separately = TRUE; |
525 } else { | 568 } else { |
526 plot_generations_separately = FALSE; | 569 plot_generations_separately = FALSE; |
527 } | 570 } |
571 # If opt$start_date and opt$end_date have values, then the | |
572 # user chose to plot a custom date interval rather than the | |
573 # entire contents of the input temperature data, so we'll | |
574 # calaculate the number of days in the custom date interval | |
575 # rather than using the number of rows in the input temperature | |
576 # data. | |
577 if (is.null(opt$start_date) && is.null(opt$end_date)) { | |
578 # Use the default number of rows in the input temperature | |
579 # data as the number of days. | |
580 num_days = opt$num_days_ytd; | |
581 } else { | |
582 # FIXME: currently custom date fields are free text, but | |
583 # Galaxy should soon include support for a date selector | |
584 # at which point this tool should be enhanced to use it. | |
585 # Validate start_date. | |
586 start_date = validate_date(opt$start_date); | |
587 # Validate end_date. | |
588 end_date = validate_date(opt$end_date); | |
589 if (start_date >= end_date) { | |
590 stop_err("The start date must be before the end date for custom date intervals."); | |
591 } | |
592 # Calculate the number of days in the custom date interval. | |
593 num_days = difftime(start_date, end_date, units=c("days")); | |
594 if (num_days > 50) { | |
595 # We need to restrict custom date intervals since | |
596 # plots render tick marks for each day. | |
597 stop_err("Custom date intervals cannot exceed 50 days."); | |
598 } | |
599 } | |
528 # Display the total number of days in the Galaxy history item blurb. | 600 # Display the total number of days in the Galaxy history item blurb. |
529 cat("Year-to-date number of days: ", opt$num_days_ytd, "\n"); | 601 cat("Year-to-date number of days: ", num_days, "\n"); |
530 | |
531 # Parse the inputs. | 602 # Parse the inputs. |
532 data_list = parse_input_data(opt$input_ytd, opt$input_norm, opt$num_days_ytd, opt$location); | 603 data_list = parse_input_data(opt$input_ytd, opt$input_norm, num_days, opt$location, opt$start_date, opt$end_date); |
533 temperature_data_frame = data_list[[1]]; | 604 temperature_data_frame = data_list[[1]]; |
534 # Information needed for plots. | 605 # Information needed for plots, some of these values are |
606 # being reset here since in some case they were set above. | |
535 start_date = data_list[[2]]; | 607 start_date = data_list[[2]]; |
536 end_date = data_list[[3]]; | 608 end_date = data_list[[3]]; |
537 start_doy_ytd = data_list[[4]]; | 609 start_doy_ytd = data_list[[4]]; |
538 end_doy_ytd = data_list[[5]]; | 610 end_doy_ytd = data_list[[5]]; |
539 is_leap_year = data_list[[6]]; | 611 is_leap_year = data_list[[6]]; |
776 for (row in 1:total_days) { | 848 for (row in 1:total_days) { |
777 # Get the integer day of the year for the current row. | 849 # Get the integer day of the year for the current row. |
778 doy = temperature_data_frame$DOY[row]; | 850 doy = temperature_data_frame$DOY[row]; |
779 # Photoperiod in the day. | 851 # Photoperiod in the day. |
780 photoperiod = temperature_data_frame$DAYLEN[row]; | 852 photoperiod = temperature_data_frame$DAYLEN[row]; |
781 temp.profile = get_temperature_at_hour(latitude, temperature_data_frame, row, total_days); | 853 temp.profile = get_temperature_at_hour(latitude, temperature_data_frame, row); |
782 mean.temp = temp.profile[1]; | 854 mean.temp = temp.profile[1]; |
783 averages.temp = temp.profile[2]; | 855 averages.temp = temp.profile[2]; |
784 averages.day[row] = averages.temp; | 856 averages.day[row] = averages.temp; |
785 # Trash bin for death. | 857 # Trash bin for death. |
786 death.vector = NULL; | 858 death.vector = NULL; |