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;