This RMarkdown document creates the thermal niche model reported in
Gutaker et al. In review.
# Set the knitting behavior knitr::opts_chunk$set(echo = TRUE, warning = FALSE, message = FALSE, collapse = TRUE, cache = FALSE, cache.lazy = FALSE, results = 'hold', out.width = "100%", fig.height = 5, comment = "#>", fig.path = here::here("analysis/figures/") ) library(gutaker2020) library(sf) library(magrittr) library(fields) # Set the behavior for printing scientific notation # options(digits = 3, scipen = -2) options(scipen = 999, knitr.table.format = "html") # Force Raster to load large rasters into memory raster::rasterOptions(chunksize = 2e+09, maxmemory = 2e+10) # Create the plan for (possibly parallel) execution future::plan(future::multisession, workers = min(parallel::detectCores(), params$cores), gc = TRUE) raw_data <- here::here("analysis/data/raw_data/") derived_data <- here::here("analysis/data/derived_data/") figures <- here::here("analysis/figures/") # Create output directories dir.create(raw_data, recursive = TRUE, showWarnings = FALSE) dir.create(derived_data, recursive = TRUE, showWarnings = FALSE) dir.create(figures, recursive = TRUE, showWarnings = FALSE)
In this section we define the study area by a bounding box, the calendar years used to define climatology (here, 1961--1990), and a plotting theme for ggplot.
# Set a series of colors for the crops crop_colors <- RColorBrewer::brewer.pal(6,"Dark2") # A function to set an objects class set_class <- function(x, classes){ class(x) <- classes return(x) } #Define the study region ASIA_poly <- raster::extent(55,150,-11,60) %>% FedData::polygon_from_extent("+proj=longlat") %>% sf::st_as_sf() # Set the calibration period for paleoclimate reconstructions calibration.years <- 1961:1990 # A ggplot2 theme for Nature Publishing Group nature_theme <- ggplot2::theme(panel.grid.major = ggplot2::element_line(size = 0.5, color = "grey"), axis.line = ggplot2::element_line(size = 0.7, color = "black"), legend.position = c(0.85, 0.7), text = ggplot2::element_text(size = 14))
Indicator kriging takes place on the ETOPO5 digital elevation model. Here, we load the ETOPO5 data from the geomapdata package, then mask out the oceans adn large lakes, as well as islands outside of mainland Asia.
message("Preparing the ETOPO5 grid-aligned dataset") time_check <- Sys.time() ne_dir <- paste0(raw_data,"NaturalEarth/") if(!params$clean & file.exists(paste0(raw_data,"ASIA_rast_etopo5.tif"))){ ASIA_rast_etopo5 <- raster::raster(paste0(raw_data,"ASIA_rast_etopo5.tif")) }else{ # Get the Natural Earth country lakes data dir.create(ne_dir, showWarnings = FALSE, recursive = TRUE) FedData::download_data( url = "http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/physical/ne_10m_lakes.zip", destdir = ne_dir ) unzip( paste0(ne_dir,"ne_10m_lakes.zip"), exdir = paste0(ne_dir,"ne_10m_lakes/") ) ne_10m_lakes <- paste0(ne_dir,"ne_10m_lakes/ne_10m_lakes.shp") %>% sf::st_read() %>% sf::st_make_valid() %>% sf::st_transform(sf::st_crs(ASIA_poly)) %>% sf::st_intersection(ASIA_poly) # Get the Natural Earth country boundaries data dir.create( paste0(ne_dir,"ne_10m_admin_0_countries_lakes/"), showWarnings = FALSE, recursive = TRUE ) FedData::download_data( url = "http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_admin_0_countries_lakes.zip", destdir = ne_dir ) unzip( paste0(ne_dir,"ne_10m_admin_0_countries_lakes.zip"), exdir = paste0(ne_dir,"ne_10m_admin_0_countries_lakes/") ) ne_10m_admin_0_countries_lakes <- paste0(ne_dir,"ne_10m_admin_0_countries_lakes/ne_10m_admin_0_countries_lakes.shp") %>% sf::st_read() %>% sf::st_transform(sf::st_crs(ASIA_poly)) %>% sf::st_intersection(ASIA_poly) %>% dplyr::filter(!(NAME %in% c("Scarborough Reef", "Maldives", "Spratly Is.", "Oman", "United Arab Emirates", "Saudi Arabia"))) library(geomapdata) data("ETOPO5") ASIA_rast_etopo5 <- ETOPO5 %>% t() %>% raster::raster(xmn = 0, xmx = 360, ymn = -90, ymx = 90, crs = sp::CRS("+proj=longlat +ellps=clrk66 +no_defs")) %>% raster::crop(ASIA_poly %>% sf::st_transform("+proj=longlat +ellps=clrk66 +no_defs") %>% as("Spatial")) %>% raster::mask(ne_10m_admin_0_countries_lakes %>% sf::st_transform("+proj=longlat +ellps=clrk66 +no_defs") %>% as("Spatial")) %>% raster::mask(ne_10m_lakes %>% sf::st_transform("+proj=longlat +ellps=clrk66 +no_defs") %>% as("Spatial"), inverse = TRUE) %T>% raster::writeRaster(filename = paste0(raw_data,"ASIA_rast_etopo5.tif"), datatype="INT2S", options=c("COMPRESS=DEFLATE", "ZLEVEL=9", "INTERLEAVE=BAND", "PHOTOMETRIC=MINISWHITE"), overwrite=T, setStatistics=FALSE) rm(ETOPO5) } countries <- paste0(ne_dir,"ne_10m_admin_0_countries_lakes/ne_10m_admin_0_countries_lakes.shp") %>% sf::st_read() %>% sf::st_transform(sf::st_crs(ASIA_poly)) %>% sf::st_intersection(ASIA_poly) %>% dplyr::filter(!(NAME %in% c("Scarborough Reef", "Maldives", "Spratly Is.", "Oman", "United Arab Emirates", "Saudi Arabia"))) %>% dplyr::select(NAME, geometry) message("ETOPO5 grid-aligned dataset preparation complete: ", capture.output(Sys.time() - time_check))
Here, we download daily weather records from the Global Historical Climatology Network,
## Downloads and cleans daily climate records from the Global Historical Climate Database. message("Preparing the daily climate records from the Global Historical Climate Database") time_check <- Sys.time() GHCN.data.final <- prepare_ghcn(region = ASIA_poly %>% as("Spatial"), label = "ASIA_poly", calibration.years = calibration.years, google_maps_elevation_api_key = params$google_maps_elevation_api_key, raw_dir = paste0(raw_data,"ghcn/"), derived_dir = paste0(derived_data,"ghcn/"), force.redo = params$clean) message("GHCN preparation complete: ", capture.output(Sys.time() - time_check)) ## An example of plotting the GHCN data # climate_plotter(data = GHCN.data.final, station = "CHM00051334", element = "TMIN")
# Run the script that transforms the Marcott et al. 2013 data into standard scores. message("Preparing the Marcott et al. 2013 data") time_check <- Sys.time() marcott2013 <- prepare_marcott(calibration.years = calibration.years, raw_dir = paste0(raw_data,"marcott2013/"), derived_dir = paste0(derived_data,"marcott2013/")) message("Marcott et al. 2013 data preparation complete: ", capture.output(Sys.time() - time_check))
#### Calculating growing degree days #### message("Modulating local climatology by Marcott et al. 2013 data") time_check <- Sys.time() # How often to sample GDD, in z-space, for model tuning # Here, we sample from -20 to 20 SD, at 1 SD interval sample.points <- -20:20 # Read in data on different crop GDD needs crop_GDD <- readr::read_csv(here::here("inst/crops.csv"), col_types = readr::cols( cultivar_long = readr::col_character(), cultivar = readr::col_character(), crop_long = readr::col_character(), crop = readr::col_character(), t_base = readr::col_double(), min_gdd = readr::col_integer() )) %T>% readr::write_csv(paste0(derived_data,"/crops.csv")) # Transform GHCN data to GDDs of each base, and modulate to Marcott GDDs <- sort(unique(crop_GDD$t_base)) GHCN.GDD.incremented.sd <- furrr::future_map(GDDs, # purrr::map(GDDs, .options = furrr::future_options( packages = c("magrittr", "gutaker2020"), globals = c("sample.points", "GHCN.data.final")), .f = function(base){ purrr::map_dfr(sample.points, function(change){ GHCN.GDDs <- purrr::map_dbl(GHCN.data.final$climatology, function(station){ return(sdModulator(data.df = station, temp.change.sd = change, t.base = base, t.cap = 30)) }) names(GHCN.GDDs) <- names(GHCN.data.final$climatology) return(tibble::tibble(SD_change = change, ID = names(GHCN.GDDs), GDD = GHCN.GDDs)) }) %>% dplyr::left_join(GHCN.data.final$spatial %>% tibble::as_tibble() %>% magrittr::set_names(c("ID", "NAME", "elevation", "x", "y")), by = "ID") }) names(GHCN.GDD.incremented.sd) <- GDDs # stop the cluster (will free memory) # stopCluster(cl) message("Modulation of local climatology by Marcott et al. 2013 data complete: ", capture.output(Sys.time() - time_check))
message("Calculating indicator Krige models") time_check <- Sys.time() # Create a spatialPointsDataFrame of the etopo5 data, and convert to WGS84 ellipsoid ASIA_rast_etopo5.sp <- ASIA_rast_etopo5 %>% magrittr::set_names("elevation") %>% raster::rasterToPoints(spatial = T) %>% sp::spTransform(sp::CRS(raster::projection(GHCN.data.final$spatial))) # A function that generates the kriging model, then predicts krige_and_predict <- function(dt){ model <- fields::mKrig(x = dt[,c("x","y")], y = dt$GDD_thresh, Z = dt$elevation, Covariance = "Exponential", Distance = "rdist.earth") prediction <- ASIA_rast_etopo5.sp %>% tibble::as_tibble() %>% dplyr::mutate(chunk = rep(1:ceiling(nrow(.)/chunk_size),length.out = nrow(.)) %>% sort() ) %>% dplyr::group_by(chunk) %>% dplyr::do(prediction = fields::predict.mKrig(model, xnew = .[,c("x","y")], Z = .$elevation) %>% as.vector()) %$% prediction %>% unlist() return(list(model = model, prediction = prediction)) } # Calculate gdd kriging models for each crop gdd_model_files <- paste0(derived_data,"models/",crop_GDD$cultivar,"_models.rds") if(params$clean){ unlink(paste0(derived_data,"models/"), recursive = TRUE, force = TRUE) dir.create(paste0(derived_data,"models/"), recursive = TRUE, showWarnings = F) crop_GDD_run <- crop_GDD }else{ dir.create(paste0(derived_data,"models/"), recursive = TRUE, showWarnings = F) crop_GDD_run <- crop_GDD[!file.exists(gdd_model_files),] } if(nrow(crop_GDD_run) == 0){ message("All indicator Krige models have already been calculated. Continuing.") }else message("Calculating indicator Krige models for ", nrow(crop_GDD_run), " cultivars:\n", paste0(capture.output(crop_GDD_run), collapse = "\n")) # A function to reduce the size of a loess model by half skinny.loess <- function(x){ x[c("fitted", "residuals", "enp", "one.delta", "two.delta", "trace.hat", "call", "terms", "xnames")] <- NULL return(x) } # A function of correct the indication predictions and estimate a smooth # monotonic function # This first uses isotonic regression, then loess smoothing with a degree of 1 smooth.preds <- function(y){ y[y<0] <- 0 y[y>1] <- 1 y <- loess(isoreg(y~sample.points)$yf~sample.points, span=0.1, degree=1) %>% skinny.loess() return(y) } if(nrow(crop_GDD_run) > 0){ options(dplyr.show_progress = FALSE) chunk_size <- 10000 gdd.models <- furrr::future_map(1:nrow(crop_GDD_run), .options = furrr::future_options( packages = c("fields", "dplyr", "magrittr", "readr", "gutaker2020")), .f = function(crop){ # Threshold for indicator kriging GHCN.GDD.incremented.sd[[as.character(crop_GDD_run[crop,"t_base"])]] %>% dplyr::mutate(GDD_thresh = {GDD >= as.numeric(crop_GDD_run[crop,"min_gdd"])}) %>% dplyr::group_by(SD_change) %>% dplyr::do(out_preds = krige_and_predict(.)) %$% out_preds %>% sapply("[[","prediction") %>% apply(1,smooth.preds) %>% tibble::tibble(model = .) %>% maptools::spCbind(ASIA_rast_etopo5.sp,.) %>% readr::write_rds(paste0(derived_data,"models/", crop_GDD_run[crop,"cultivar"], "_models.rds"), compress = "xz") return(paste0(derived_data,"models/", crop_GDD_run[crop,"cultivar"], "_models.rds")) }) } rm(ASIA_rast_etopo5, ASIA_rast_etopo5.sp) message("Calculation indicator Krige models complete: ", capture.output(Sys.time() - time_check))
## Predicting crop niche from smoothed Krige models # Calculate niches for each crop using the Marcott et al. 2013. # create the cluster for parallel computation message("Generating niche reconstructions") time_check <- Sys.time() if(params$clean){ unlink(paste0(derived_data,"recons/"), recursive = TRUE, force = TRUE) } dir.create(paste0(derived_data,"recons/"), recursive = TRUE, showWarnings = F) # Create the plan for (possibly parallel) execution future::plan(future::multisession, workers = max( floor( min( future::availableCores(), params$cores)/2), 1), gc = TRUE) furrr::future_walk(crop_GDD$cultivar, .options = furrr::future_options( packages = c("fields", "dplyr", "magrittr", "sp", "readr", "gutaker2020")), function(crop){ if(file.exists(paste0(derived_data,"recons/", crop, "_recons.rds"))) return() if(!file.exists(paste0(derived_data,"models/", crop, "_models.rds"))) stop("Models for ", crop, " are missing! Aborting.") Zs <- c("Z_Lower","Z","Z_Upper") crop.models <- readr::read_rds(paste0(derived_data,"models/", crop, "_models.rds")) purrr::map(Zs, function(z){ suppressWarnings( crop.models@data %$% model %>% purrr::map( function(x){ x %>% predict(newdata = marcott2013[[z]]) %>% magrittr::multiply_by(100) %>% round() %>% as.integer() }) %>% do.call(rbind, .) %>% tibble::as_tibble() %>% magrittr::set_colnames(marcott2013$YearBP) %>% new("SpatialPointsDataFrame", data = ., coords.nrs = crop.models@coords.nrs, coords = crop.models@coords, bbox = crop.models@bbox, proj4string = crop.models@proj4string) %>% as("SpatialPixelsDataFrame") %>% raster::brick() %>% raster::setZ(marcott2013$YearBP, name="Years BP") ) }) %>% magrittr::set_names(Zs) %>% purrr::map(raster::readAll) %>% readr::write_rds(paste0(derived_data,"recons/", crop, "_recons.rds"), compress = "xz", compression = 9) return() }) message("Generation of niche reconstructions complete: ", capture.output(Sys.time() - time_check))
## Combining crop niches from similar crops by taking an arithmatic mean message("Combining like crop niches") time_check <- Sys.time() # Force Raster to load large rasters into memory raster::rasterOptions(chunksize = 2e+10, maxmemory = 2e+11) crop_GDD %>% split(as.factor(crop_GDD$crop)) %>% purrr::walk(function(x){ if(file.exists(paste0(derived_data,"recons/all_",x$crop[[1]],".rds"))) return() n_crops <- length(x$crop) if(n_crops == 1){ file.copy(paste0(derived_data,"recons/", x$cultivar[[1]], "_recons.rds"), paste0(derived_data,"recons/all_", x$crop[[1]], ".rds")) return() } x %$% cultivar %>% purrr::map(function(cultivar){ paste0(derived_data,"recons/",cultivar,"_recons.rds") %>% readr::read_rds() }) %>% purrr::transpose() %>% purrr::map(function(x){ x %>% Reduce(f = "+", x = .) %>% magrittr::divide_by(n_crops) %>% round() %>% raster::readAll() %>% magrittr::set_names(names(x[[1]])) }) %>% readr::write_rds(paste0(derived_data,"recons/all_", x$crop[[1]], ".rds"), compress = "xz", compression = 9) }) message("Combining like crop niches complete: ", capture.output(Sys.time() - time_check))
## Plotting cultivar niche # create the cluster for parallel computation message("Plotting cultivar niche reconstructions") time_check <- Sys.time() dir.create(paste0(figures,"cultivar_niches/"), recursive = TRUE, showWarnings = FALSE) breaks <- seq(0, 100, 10) pal <- viridisLite::viridis(length(breaks) - 1) gdd.recons <- purrr::map_chr(1:nrow(crop_GDD), function(n){ cultivar <- crop_GDD[n,]$cultivar title <- stringr::str_c(crop_GDD[n,]$cultivar_long, " \u2014 Required GDD: ", crop_GDD[n,]$min_gdd, " at a ", crop_GDD[n,]$t_base, "°C base") rasts <- readr::read_rds(paste0(derived_data,"recons/",cultivar,"_recons.rds")) %>% purrr::map(function(x){ x %>% magrittr::extract2(which(.@z$`Years BP` > 1000)) %>% # raster:::readAll() %>% magrittr::extract2(raster::nlayers(.):1) }) years <- rasts[[1]] %>% names() %>% gsub(pattern = "X", replacement = "", x = .) %>% as.numeric() if(!file.exists(paste0(figures,"cultivar_niches/",cultivar,".pdf"))) gutaker2020:::space_time_plot( the_brick = rasts$Z, the_brick_lower = rasts$Z_Lower, the_brick_upper = rasts$Z_Upper, out_file = paste0(figures,"cultivar_niches/",cultivar,".pdf"), title = title, time = years, timelim = c(max(years),min(years)), timeaxis = seq(from = max(years)-500, to = min(years), by = -500), timelab = "Years BP", zbreaks = breaks, zlab = "Probability of being in niche", zaxis = seq(0,100,10), zcolors = pal ) if(!file.exists(paste0(figures,"cultivar_niches/",cultivar,".mp4"))) gutaker2020:::space_time_video( the_brick = rasts$Z, the_brick_lower = rasts$Z_Lower, the_brick_upper = rasts$Z_Upper, out_file = paste0(figures,"cultivar_niches/",cultivar,".mp4"), title = title, time = years, timelim = c(max(years),min(years)), timeaxis = seq(from = max(years)-500, to = min(years), by = -500), timelab = "Years BP", zbreaks = breaks, zlab = "Probability of being in niche", zaxis = seq(0,100,10), zcolors = pal ) return(paste0(figures,"cultivar_niches/",cultivar,".pdf")) }) message("Plotting of cultivar niche reconstructions complete: ", capture.output(Sys.time() - time_check))
# Create a static plot for paper publication # A function to extract data from a crop raster brick tidyCrop <- function(x, years){ x %>% paste0(derived_data,"recons/all_",.,".rds") %>% readr::read_rds() %$% Z %>% magrittr::extract2(stringr::str_c("X",years)) %>% as("SpatialPixelsDataFrame") %>% tibble::as_tibble() %>% tidyr::gather(Year, Niche, -x:-y) %>% dplyr::rename(Longitude = x, Latitude = y) %>% dplyr::mutate(Year = stringr::str_remove(Year, "X") %>% factor(levels = years) %>% forcats::fct_relabel(function(x){stringr::str_c(x," cal. BP")}), Crop = x) } breaks <- seq(0, 100, 10) pal <- (RColorBrewer::brewer.pal(10, "Spectral") %>% rev() %>% colorRampPalette(.))(length(breaks) - 1) # A function to create a plot of years and crops facet_niche <- function(crops, years){ these_rasters <- crops %>% purrr::map(tidyCrop, years = years) %>% dplyr::bind_rows() %>% dplyr::mutate(Crop = dplyr::recode_factor(Crop, rice = "Rice"), Niche = Niche %>% cut(breaks = breaks, include.lowest = TRUE)) p <- these_rasters %>% ggplot2::ggplot() + ggplot2::geom_raster(mapping = ggplot2::aes(x = Longitude, y = Latitude, fill = Niche), show.legend = TRUE) + ggplot2::coord_quickmap() + ggplot2::facet_grid(Crop ~ Year, switch = "y") return(p) } message("Plotting of crop niche reconstructions complete: ", capture.output(Sys.time() - time_check))
japan_thai <- countries %>% dplyr::filter(NAME %in% c("Japan","Thailand")) # # Get the pixel counts # crop <- "tropical" # y.vx <- velox::velox(readr::read_rds(paste0("./data/derived_data/recons/all_",crop,".rds"))[[1]]) # y.vx$extract(japan_thai, # fun = function(i){sum(!is.na(i))})[,1] japan_thai_data <- c("Tropical Japonica" = "tropical_japonica", "Temperate Japonica" = "temperate_japonica", "Indica" = "indica") %>% purrr::map( function(crop){ readr::read_rds(paste0(derived_data,"recons/all_",crop,".rds")) %>% purrr::map( function(y){ y.vx <- velox::velox(y) y.vx$extract(japan_thai, fun = function(i){mean(i, na.rm = TRUE)}) %>% t() %>% tibble::as_tibble() %>% magrittr::set_names(japan_thai$NAME) %>% dplyr::mutate(`Years BP` = names(y) %>% stringr::str_remove("X") %>% as.integer()) %>% dplyr::select(`Years BP`, dplyr::everything()) }) }) %>% purrr::map(dplyr::bind_rows, .id = "Series") %>% dplyr::bind_rows(.id = "Crop") %>% tidyr::gather(Country, `Probability of being in niche`,-Crop:-`Years BP`) %>% tidyr::spread(Series, `Probability of being in niche`) japan_thai_data %>% ggplot2::ggplot(ggplot2::aes(x = `Years BP`, color = Country)) + ggplot2::geom_ribbon(ggplot2::aes(ymin = Z_Lower, ymax = Z_Upper, fill = Country), color = NA, alpha = 0.3) + ggplot2::geom_line(ggplot2::aes(y = Z)) + ggplot2::scale_x_reverse(limits = c(5510,1010), breaks = seq(5510,1010,-500), expand = c(0,0)) + ggplot2::scale_y_continuous(name = "Probability of being in niche", limits = c(0,100), expand = c(0,0)) + ggplot2::facet_wrap(facets = "Crop", ncol = 1) + ggplot2::theme_minimal() + ggplot2::theme(legend.position="bottom", plot.margin = ggplot2::margin(t = 0, r = 10, b = 0, l = 0, unit = "pt")) ggplot2::ggsave(paste0(figures,"supplementary_figure_20b.pdf"), width = 6.5, height = 6, device = cairo_pdf) smooth.preds <- function(y){ y[y<0] <- 0 y[y>1] <- 1 y <- loess(isoreg(y~sample.points)$yf~sample.points, span=0.1, degree=1) %>% skinny.loess() return(y) } GHCN.data.final$spatial %>% sf::st_as_sf() %>% sf::st_transform(sf::st_crs(japan_thai)) %>% sf::st_intersection(japan_thai) %>% dplyr::select(ID) %>% tibble::as_tibble() %>% sf::st_as_sf() %>% dplyr::left_join( GHCN.GDD.incremented.sd[[1]] %>% dplyr::group_by(ID) %>% dplyr::summarise(`GDD Model` = list(loess(isoreg(GDD ~ SD_change)$yf ~ sample.points, span=0.1, degree=1))) ) %>% dplyr::rowwise() %>% dplyr::mutate(`GDD` = list( marcott2013 %>% dplyr::select(`Years BP` = YearBP, Z_Lower, Z, Z_Upper) %>% dplyr::mutate_at(.vars = vars(Z_Lower, Z, Z_Upper), .funs = function(x){ predict(`GDD Model`,newdata = x) }) )) %>% sf::st_as_sf() %>% dplyr::select(GDD) %>% dplyr::ungroup() %>% sf::st_intersection(japan_thai) %>% dplyr::rename(Country = NAME) %>% sf::st_drop_geometry() %>% tidyr::unnest(cols = c(GDD)) %>% dplyr::group_by(Country,`Years BP`) %>% dplyr::summarise_all(mean, na.rm = TRUE) %>% ggplot2::ggplot(ggplot2::aes(x = `Years BP`, color = Country)) + ggplot2::geom_ribbon(ggplot2::aes(ymin = Z_Lower, ymax = Z_Upper, fill = Country), color = NA, alpha = 0.3) + ggplot2::geom_line(ggplot2::aes(y = Z)) + ggplot2::scale_x_reverse(limits = c(5510, 1010), breaks = seq(5510, 1010, -500), expand = c(0,0)) + ggplot2::scale_y_continuous(name = "Growing Degree Days", limits = c(0,8000), expand = c(0,0)) + ggplot2::theme_minimal() + ggplot2::theme(legend.position="bottom", plot.margin = ggplot2::margin(t = 10, r = 10, b = 0, l = 0, unit = "pt")) ggplot2::ggsave(paste0(figures,"supplementary_figure_20a.pdf"), width = 6.5, height = 6.5/1.618, device = cairo_pdf)
# Force Raster to load large rasters into memory raster::rasterOptions(chunksize = 2e+09, maxmemory = 2e+10) dir.create(paste0(figures,"source_data/")) crop_GDD %$% cultivar %>% purrr::map(function(cultivar){ rasts <- readr::read_rds(paste0(derived_data,"recons/",cultivar,"_recons.rds")) %>% purrr::map_dfr(function(x){ # the_brick <- # x %>% # magrittr::extract2(which(.@z$`Years BP` > 1000)) mean.temporal <- raster::cellStats(x, mean, na.rm = T) %>% round(digits = 2) ci.temporal <- raster::cellStats(x, stats::quantile, probs = c(0.25, 0.5, 0.75), na.rm = T) tibble::tibble(`Years BP` = x@z$`Years BP`, `Spatial Mean` = mean.temporal, `Spatial Lower IQR` = ci.temporal[1,], `Spatial Median` = ci.temporal[2,], `Spatial Upper IQR` = ci.temporal[3,]) }, .id = "Marcott et al. 2013 Reconstruction") %>% dplyr::mutate(`Marcott et al. 2013 Reconstruction` = `Marcott et al. 2013 Reconstruction` %>% factor(levels = c("Z","Z_Lower","Z_Upper"), ordered = TRUE) %>% forcats::fct_recode("Mean" = "Z", "1σ Lower" = "Z_Lower", "1σ Upper" = "Z_Upper")) %>% dplyr::select(`Years BP`, dplyr::everything()) }) %>% magrittr::set_names(crop_GDD$cultivar_long) %>% magrittr::extract(.,sort(names(.))) %>% writexl::write_xlsx(paste0(figures,"source_data/figure_3e_cultivar_graph_data.xlsx")) ## Export raster data for Figure 3 readr::read_rds(paste0(derived_data,"recons/tropical_japonica_120_recons.rds")) %$% Z %>% magrittr::extract2(paste0("X", c(4410, 3550))) %>% raster::unstack() %>% magrittr::set_names(.,c(4410, 3550)) %>% purrr::iwalk(~raster::writeRaster(.x, paste0(figures,"source_data/figure_3_raster_data_",.y,".asc")))
This report was generated on r Sys.time()
using the following computational environment and dependencies:
# which R packages and versions? devtools::session_info()
The current Git commit details are:
# what commit is this file at? You may need to change the path value # if your Rmd is not in analysis/paper/ git2r::repository("..")
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.