diff --git a/.gitignore b/.gitignore index 0a5e2c4725a863d459043309adcb93ff47e39dbe..a7238c3e95046e503e3fe8fe99d464368d8da83d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ .RData .Ruserdata .RProfile -.Renvironment +.Renviron .DS_Store 1_fetch/out/* 1_fetch/in/* diff --git a/00_config.R b/00_config.R new file mode 100644 index 0000000000000000000000000000000000000000..efc9ef6a833b3ee06407b9a72799d5be7d4edd05 --- /dev/null +++ b/00_config.R @@ -0,0 +1,7 @@ +source("0_config/src/sb_cache.R") + +initialize_and_cache_sb( + sb_username = rstudioapi::showPrompt("Username", "SB Username"), + renviron_file = ".Renviron", + override_login = FALSE +) diff --git a/0_config/src/sb_cache.R b/0_config/src/sb_cache.R new file mode 100644 index 0000000000000000000000000000000000000000..ac889e3697c53f6fb36b3cd9e27d492c598b60cd --- /dev/null +++ b/0_config/src/sb_cache.R @@ -0,0 +1,99 @@ +" Initialize ScienceBase login and cache token in .Renviron +#" +#' @param sb_username chr; ScienceBase username. The default prompts the user to +#' enter the username in the console. +#' @param renviron_file chr; path to .Renviron file +#' @param override_login lgl; should ScienceBase be re-initialized if already +#' logged in? +#' +#' @return lgl; result of `sbtools::is_logged_in()` +#' +initialize_and_cache_sb <- function(sb_username = NULL, + renviron_file = ".Renviron", + override_login = FALSE) { + # Give error if already logged in and `override_login = FALSE` + tryCatch( + sbtools:::token_refresh(), + warning = function(x) {}, + error = function(x) FALSE + ) + + if (sbtools::is_logged_in()) { + if (override_login) { + # If logged in and overriding login: warn and re-initialize SB + cli::cli_warn(c( + "!" = "You are already logged into ScienceBase and re-initialization + anyways.", + "i" = "If you would not like to re-initialize, abort and re-run with + {.arg override_login = FALSE}" + )) + sbtools::initialize_sciencebase_session(username = sb_username) + } + } else { + # If not logged into SB, initialize SB + sbtools::initialize_sciencebase_session(username = sb_username) + } + + # Grab token and update it in .Renviron + update_renviron( + sb_username = sb_username, + sb_token = jsonlite::toJSON( + sbtools::current_session()[c("access_token", "refresh_token")] + ), + renviron_file + ) + + # Output if currently logged into SB + if (sbtools::is_logged_in()) { + return(TRUE) + } else { + cli::cli_abort(c( + "!" = "You are not logged into ScienceBase after attempting it.", + "i" = "Try running {.fun initialize_and_cache_sb} again." + )) + } +} + +#' Create/update .Renviron with ScienceBase token +#' +#' @param sb_token chr; token used to initialize a ScienceBase session +#' @param renviron_file chr; path to .Renviron file +#' +#' @return chr; path to .Renviron file +#' +update_renviron <- function(sb_username, sb_token, renviron_file) { + if (file.exists(renviron_file)) { + # If there is an existing .Renviron file... + # Read in existing .Renviron file and check if there is an "sb_token" value + existing <- readLines(renviron_file) + sb_token_idx <- which(startsWith(existing, "sb_token=")) + sb_username_idx <- which(startsWith(existing, "sb_username=")) + + # If there is already a value for sb_token update it; if not, create one. + if (length(sb_token_idx) > 0) { + existing[sb_token_idx] <- paste0("sb_token=", sb_token) + writeLines(existing, con = renviron_file) + } else { + write(paste0("sb_token=", sb_token), file = renviron_file, append = TRUE) + } + + # If there is already a value for sb_username update it; if not, create one + if (length(sb_username_idx) > 0) { + existing[sb_username_idx] <- paste0("sb_username=", sb_username) + writeLines(existing, con = renviron_file) + } else { + write( + paste0("sb_username=", sb_username), + file = renviron_file, append = TRUE + ) + } + } else { + # If there isn't an .Renviron file, create one with an "sb_token" value + write( + paste0("sb_token=", sb_token, "\n", "sb_username=", sb_username), + file = renviron_file + ) + } + + return(renviron_file) +} diff --git a/1_fetch.R b/1_fetch.R index 1a8f5af2b117055fdba139fd675e2a898528fd49..2e43036cf171b6487a61023d191e52415b2e854f 100644 --- a/1_fetch.R +++ b/1_fetch.R @@ -2,19 +2,21 @@ source("1_fetch/src/fetch_utils.R") p1_targets <- list( ##### Vulnerability indicators data ##### + tar_target(p1_out_data, + "1_fetch/out/"), tar_target(p1_sb_id, '63f79d49d34e4f7eda456572'), ##### Vulnerability indicators metadata ##### tar_target(p1_vul_ind_xml, - download_from_sb(sb_id = p1_sb_id, - filename = 'Uncertainty_Summary.xml', - dest_dir = '1_fetch/out'), + sb_initialize_and_download(sb_id = p1_sb_id, + names = 'Uncertainty_Summary.xml', + destinations = paste0(p1_out_data, "Uncertainty_Summary.xml")), format = 'file'), ##### Uncertainty statistics for the indicators ##### tar_target(p1_unc_stats_csv, - download_from_sb(sb_id = p1_sb_id, - filename = 'Uncertainty_Summary.csv', - dest_dir = '1_fetch/out'), + sb_initialize_and_download(sb_id = p1_sb_id, + names = 'Uncertainty_Summary.csv', + destinations = paste0(p1_out_data, "Uncertainty_Summary.csv")), format = 'file'), tar_target(p1_unc_stats, readr::read_csv(p1_unc_stats_csv) |> @@ -39,5 +41,25 @@ p1_targets <- list( )) |> filter(group %in% c('CONUS')) |> rmapshaper::ms_simplify(keep = 0.2) |> - filter(NAME %in% p1_census_states)) - ) \ No newline at end of file + filter(NAME %in% p1_census_states)), + # raster data for population density + tar_target(p1_pop_density_raster_zip, + '1_fetch/in/gpw-v4-population-count-rev11_2020_30_sec_tif.zip'), + tar_target(p1_pop_density_raster_tif, + {unzip(p1_pop_density_raster_zip, 'gpw_v4_population_count_rev11_2020_30_sec.tif', + exdir = p1_out_data) + file_name <- paste0(p1_out_data, "gpw_v4_population_count_rev11_2020_30_sec.tif") + return(file_name)}), + # raster data for impervious surfaces + tar_target(p1_imp_surf_zip, + sb_initialize_and_download(sb_id = "664e0da6d34e702fe8744579", + names = 'Annual_NLCD_FctImp_2022_CU_C1V0.zip', + destinations = paste0(p1_out_data, "Annual_NLCD_FctImp_2022_CU_C1V0.zip")), + format = 'file'), + tar_target(p1_imp_surf_tif, + {unzip(p1_imp_surf_zip, 'Annual_NLCD_FctImp_2022_CU_C1V0.tif', + exdir = p1_out_data) + file_name <- paste0(p1_out_data, "Annual_NLCD_FctImp_2022_CU_C1V0.tif") + return(file_name)}) + ) + \ No newline at end of file diff --git a/1_fetch/src/fetch_utils.R b/1_fetch/src/fetch_utils.R index fc3b8293b07fc6697766945f79c846d5b272e84b..b02e57d528dc73a536bad8001727033204c424fb 100644 --- a/1_fetch/src/fetch_utils.R +++ b/1_fetch/src/fetch_utils.R @@ -1,16 +1,93 @@ -#' @title Download file from ScienceBase -#' @description Download a file from ScienceBase and save it to a specified -#' directory -#' @param sb_id id for ScienceBase data release -#' @param filename filename of item in data release -#' @param dest_dir directory to which to download the file -#' @return the filepath of the saved file -download_from_sb <- function(sb_id, filename, dest_dir) { - filepath <- file.path(dest_dir, filename) - - sbtools::item_file_download(sb_id = sb_id, - names = filename, - destinations = filepath) - - return(filepath) -} \ No newline at end of file +#' Initialize ScienceBase session and download files +#' +#' @param sb_id chr; ScienceBase ID +#' @param names chr; names of files to download from ScienceBase +#' @param destinations chr; write path location for downloaded files +#' @param renviron_file chr; path to .Renviron file where credentials are cached +#' @param ... additional arguments passed to `sbtools::item_file_download()` +#' +#' @return chr; path to downloaded files +#' +sb_initialize_and_download <- function(sb_id, names, destinations, + renviron_file = ".Renviron", ...) { + # Initialize ScienceBase session + sb_login_cached(renviron_file = renviron_file) + + # Download SB files + sbtools::item_file_download( + sb_id = sb_id, + names = names, + destinations = destinations, + ... + ) + + return(destinations) +} + +#' Login to ScienceBase using cached credentials +#' +#' @param renviron_file chr; path to .Renviron file +#' +#' @return `TRUE` if logged in. Error if not. +#' +sb_login_cached <- function(renviron_file) { + # If logged in, return TRUE and skip the rest + if (sbtools::is_logged_in()) { + return(TRUE) + } + + # Try a token refresh + tryCatch( + sbtools:::token_refresh(), + warning = function(x) {}, + error = function(x) FALSE + ) + + if (sbtools::is_logged_in()) { + return(TRUE) + } + + # If .Renviron file does not exist, re-initialize + if (!file.exists(renviron_file)) { + cli::cli_abort(c( + "Could not find the specified file: {.file {renviron_file}}.", + "i" = "Follow the instructions in {.file README.md} to initalize and cache + ScienceBase login credentials." + )) + } + + # Read .Renviron file + existing <- readLines(renviron_file) + sb_token_idx <- which(startsWith(existing, "sb_token=")) + sb_username_idx <- which(startsWith(existing, "sb_username=")) + + # If SB credentials not found, throw error + if (any(length(sb_token_idx) == 0, length(sb_username_idx) == 0)) { + cli::cli_abort(c( + "Could not find the username or token in the specified file: + {.file {renviron_file}}.", + "i" = "Follow the instructions in {.file README.md} to re-initalize and + cache ScienceBase login credentials." + )) + } + + # Get ScienceBase credentials + sb_token <- stringr::str_remove(existing[sb_token_idx], "^sb_token=") + sb_username <- stringr::str_remove(existing[sb_username_idx], "^sb_username=") + + # Initialize ScienceBase session with cached credentials + sbtools::initialize_sciencebase_session( + username = sb_username, + token_text = sb_token + ) + + if (sbtools::is_logged_in()) { + return(TRUE) + } else { + cli::cli_abort(c( + "Could not login to ScienceBase using cached credentials.", + "i" = "Follow the instructions in {.file README.md} to re-initalize and + cache ScienceBase login credentials." + )) + } +} diff --git a/2_process.R b/2_process.R index 8dc7aaf94c274f192e9e7d7fd3af5955c13e7c45..9a25092d41d083104888fa3ef0ad8a1b304e1235 100644 --- a/2_process.R +++ b/2_process.R @@ -70,11 +70,12 @@ p2_targets <- list( # distinct(determinant, .keep_all = TRUE) |> readr::write_csv('public/determinant_uncertainty.csv') ), -tar_target(p2_unc_determinant_json, - read_csv(p2_unc_agg_summary_csv) |> - toJSON(pretty = TRUE) |> - write("public/determinant_uncertainty.json") - ), +# commented out for now so we don't overwrite spanish names +#tar_target(p2_unc_determinant_json, +# read_csv(p2_unc_agg_summary_csv) |> +# toJSON(pretty = TRUE) |> +# write("public/determinant_uncertainty.json") +# ), tar_target(`p2_unc_agg_summary_ind_csv`, p2_unc_agg_ind_summary |> left_join(p2_top_trend_ind_stats) |> @@ -241,5 +242,29 @@ tar_target(p2_census_acs5sub_disability_data, survey_var = "acs5", percent_rename = FALSE), pattern = map(p2_census_acs5_disability_layers), - iteration = "list") + iteration = "list"), +# prep for raster data processing and plotting +tar_target(p2_conus_sf, + fetch_conus_sf(states = p1_census_states)), +tar_target(p2_conus_sf_proj, + p2_conus_sf |> + st_transform(p1_proj)), +tar_target(p2_conus_inner, + rmapshaper::ms_innerlines(p2_conus_sf_proj)), +tar_target(p2_conus_counties_sf, + counties_sf <- tigris::counties(cb = TRUE, state = p1_census_states) |> + rmapshaper::ms_simplify(keep = 0.2) |> + st_transform('EPSG:5070')), +# process population density raster data +tar_target(p2_pop_density_processed, + process_pop_dens(in_raster = p1_pop_density_raster_tif, + conus_sf = p2_conus_sf, conus_proj = p2_conus_sf_proj, + outfile_path = "2_process/out/pop_density.tif"), + format = "file"), +# process impervious surfaces raster data +tar_target(p2_imp_surf_processed, + process_imp_surf(in_raster = p1_imp_surf_tif, conus_proj = p2_conus_sf_proj, + outfile_path = "2_process/out/imp_surfaces.tif"), + format = "file") + ) \ No newline at end of file diff --git a/2_process/src/data_utils.R b/2_process/src/data_utils.R index dd430c90b2b59cb330dcef6a616222b39cbca603..e7aeed9790d21cd1168fb96343f2c35a566e0261 100644 --- a/2_process/src/data_utils.R +++ b/2_process/src/data_utils.R @@ -47,4 +47,73 @@ process_perc <- function(tot_pop, tot_var){ return(joined_perc_df)} prep_tree_data <- function(data) { +} + +## data processing for population density raster map +#' @title Fetch conus for raster processing +#' @param states, chr string with long name of states of interest to filter by +fetch_conus_sf <- function(states){ + + conus_sf <- tigris::states(cb = TRUE) |> + dplyr::filter(NAME %in% states + ) |> + rmapshaper::ms_simplify(keep = 0.2) +} + +#' @title Process population density raster data for plotting +#' @param in_raster character string - .tif file path of raster data for specified variable of interest +#' @param conus_sf, sf of conus states outline +#' @param conus_proj, projected sf of conus states outline +#' @param outfile_path, outfile path for processed tifs +process_pop_dens <- function(in_raster, conus_sf, conus_proj, outfile_path){ + + raw_data <- rast(in_raster) + + # crop population data to area of interest + terra::window(raw_data) <- terra::ext(conus_sf) + + # project population data + conus_sf_rast <- rast(conus_proj, resolution = c(1000, 1000)) + pop_usa_proj <- project(raw_data, conus_sf_rast) + # match boundaries of population data to conus data + pop_usa_mask <- terra::mask(pop_usa_proj, terra::vect(conus_proj)) + + # change to tibble using tidy terra for processing into log scale + usa_dat <- as_tibble(pop_usa_mask, xy = TRUE) + usa_dat$pop <- ifelse(usa_dat$gpw_v4_population_count_rev11_2020_30_sec < 1 + & usa_dat$gpw_v4_population_count_rev11_2020_30_sec > 0, 0.1, + usa_dat$gpw_v4_population_count_rev11_2020_30_sec) + usa_dat$pop_log10 <- log10(usa_dat$pop) + usa_dat <- usa_dat |> + dplyr::select(-gpw_v4_population_count_rev11_2020_30_sec, -pop) + # convert back into raster + usa_dat_rast <- as_spatraster(usa_dat) + + writeRaster(usa_dat_rast, filename = outfile_path, overwrite=TRUE) + + return(outfile_path) +} + + +#' @title Process impervous surfaces raster data for plotting +#' @param in_raster character string - .tif file path of raster data for specified variable of interest +#' @param conus_proj, projected sf of conus states outline +#' @param outfile_path, outfile path for processed tifs +process_imp_surf <- function(in_raster, conus_proj, outfile_path){ + + imp_surf_raw <- rast(in_raster) + + # crop population data to area of interest + terra::window(imp_surf_raw) <- terra::ext(conus_proj) + + # project population data + conus_sf_rast <- rast(conus_proj, resolution = c(1000, 1000)) + imp_surf_proj <- project(imp_surf_raw, conus_sf_rast) + + # match boundaries of population data to conus data + imp_surf_mask <- terra::mask(imp_surf_proj, terra::vect(conus_proj)) + + writeRaster(imp_surf_mask, filename = outfile_path, overwrite=TRUE) + + return(outfile_path) } \ No newline at end of file diff --git a/3_visualize.R b/3_visualize.R index 6a043398b3d345f56ae414e6377478c9bf658fa5..15ce7edbaf6b48950160cb50c424081de5e45d3e 100644 --- a/3_visualize.R +++ b/3_visualize.R @@ -93,139 +93,183 @@ p3_targets <- list( format = "file" ), tar_target( - p3_perc_disable_png_en, - plot_census_map( - census_data = p2_census_acs5sub_disability_data[[1]], - percent_leg = TRUE, - dollar_leg = FALSE, - lim_vals = c(0, 50), - break_vals = c(0, 10, 20, 30, 40, 50), - var = 'estimate', - conus_sf = p1_conus_sf, - outfile_path = "3_visualize/out/perc_disabled_census_2022_en.png", - leg_title = "Percent disabled, 2022", - viz_config_df = p0_viz_config_df, - viz_config_pal = p0_viz_config_pal$demographic_characteristics, - width = p0_viz_config_df$width_desktop, - height = p0_viz_config_df$height_desktop, - font_size = p0_viz_config_df$font_size_desktop, - barwidth = 20, - barheight = 1, - low_ramp_col = "#eef0ff" + p3_perc_disable_png_en, + plot_census_map( + census_data = p2_census_acs5sub_disability_data[[1]], + percent_leg = TRUE, + dollar_leg = FALSE, + lim_vals = c(0, 50), + break_vals = c(0, 10, 20, 30, 40, 50), + var = 'estimate', + conus_sf = p1_conus_sf, + outfile_path = "3_visualize/out/perc_disabled_census_2022_en.png", + leg_title = "Percent disabled, 2022", + viz_config_df = p0_viz_config_df, + viz_config_pal = p0_viz_config_pal$demographic_characteristics, + width = p0_viz_config_df$width_desktop, + height = p0_viz_config_df$height_desktop, + font_size = p0_viz_config_df$font_size_desktop, + barwidth = 20, + barheight = 1, + low_ramp_col = "#eef0ff" ), - format = "file" -), -# Spanish version's of maps ----------------------------------------------- -tar_target( - p3_med_income_png_es, - plot_census_map( - census_data = p2_perc_census_acs5_layers_sf[[2]], - lim_vals = c(0, 155000), - percent_leg = FALSE, - dollar_leg = TRUE, - var = 'estimate', - conus_sf = p1_conus_sf, - outfile_path = "3_visualize/out/med_income_census_2022_es.png", - leg_title = "Media de ingresos por hogar, 2022", - viz_config_df = p0_viz_config_df, - viz_config_pal = p0_viz_config_pal$socioeconomic_status, - width = p0_viz_config_df$width_desktop, - height = p0_viz_config_df$height_desktop, - font_size = p0_viz_config_df$font_size_desktop, - barwidth = 20, - barheight = 1, - low_ramp_col = "#fef1f1" + format = "file" ), - format = "file" -), -tar_target( - p3_perc_latino_png_es, - plot_census_map( - census_data = p2_perc_census_acs5_layers_sf[[4]], - percent_leg = TRUE, - dollar_leg = FALSE, - lim_vals = c(0, 100), - break_vals = c(0, 25, 50, 75, 100), - var = 'percent', - conus_sf = p1_conus_sf, - outfile_path = "3_visualize/out/perc_hispanic_census_2022_es.png", - leg_title = "Porcentaje de Hispanos, 2022", - viz_config_df = p0_viz_config_df, - viz_config_pal = p0_viz_config_pal$demographic_characteristics, - width = p0_viz_config_df$width_desktop, - height = p0_viz_config_df$height_desktop, - font_size = p0_viz_config_df$font_size_desktop, - barwidth = 20, - barheight = 1, - low_ramp_col = "#eef0ff" + # population density raster plot + tar_target( + p3_pop_density_png, + plot_raster(in_raster = p2_pop_density_processed, + conus_sf = p2_conus_sf_proj, + conus_inner = p2_conus_inner, + counties_sf = p2_conus_counties_sf, + viz_config_df = p0_viz_config_df, + viz_config_pal = "#38837a", + rast_type = "pop_density", + low_ramp_col = "#E8F4F4", + base_conus_fill = "#E8F4F4", + base_conus_color = "#E8F4F4", + border_color = p0_viz_config_df$counties_outline_col, + leg_title = expression(paste(bold("Population per 1 "), bold(km^2), bold(", 2020"))), + font_size = p0_viz_config_df$font_size_desktop, + barheight = 1, + barwidth = 20, + outfile_path = "3_visualize/out/pop_density_rast_2020_en.png", + width = p0_viz_config_df$width_desktop, + height = p0_viz_config_df$height_desktop), + format = "file"), + # impervious surfaces raster plot + tar_target( + p3_imp_surf_png, + plot_raster(in_raster = p2_imp_surf_processed, + conus_sf = p2_conus_sf_proj, + conus_inner = p2_conus_inner, + counties_sf = p2_conus_counties_sf, + viz_config_df = p0_viz_config_df, + viz_config_pal = "#38837a", + rast_type = "imp_surfaces", + low_ramp_col = "white", + base_conus_fill = NA, + base_conus_color = "#E8F4F4", + border_color = "gray90", + leg_title = "Percent impervious surface, 2022", + font_size = p0_viz_config_df$font_size_desktop, + barheight = 1, + barwidth = 20, + outfile_path = "3_visualize/out/imp_surface_rast_2022_en.png", + width = p0_viz_config_df$width_desktop, + height = p0_viz_config_df$height_desktop), + format = "file"), + # Spanish version's of maps ----------------------------------------------- + tar_target( + p3_med_income_png_es, + plot_census_map( + census_data = p2_perc_census_acs5_layers_sf[[2]], + lim_vals = c(0, 155000), + percent_leg = FALSE, + dollar_leg = TRUE, + var = 'estimate', + conus_sf = p1_conus_sf, + outfile_path = "3_visualize/out/med_income_census_2022_es.png", + leg_title = "Media de ingresos por hogar, 2022", + viz_config_df = p0_viz_config_df, + viz_config_pal = p0_viz_config_pal$socioeconomic_status, + width = p0_viz_config_df$width_desktop, + height = p0_viz_config_df$height_desktop, + font_size = p0_viz_config_df$font_size_desktop, + barwidth = 20, + barheight = 1, + low_ramp_col = "#fef1f1" + ), + format = "file" ), - format = "file" -), -tar_target( - p3_avg_household_size_png_es, - plot_census_map( - census_data = p2_census_acs5sub_household_data[[1]], - percent_leg = FALSE, - dollar_leg = FALSE, - lim_vals = c(1, 5), - var = 'estimate', - conus_sf = p1_conus_sf, - outfile_path = "3_visualize/out/avg_household_size_2022_es.png", - leg_title = "Tamaño promedio de los hogares, 2022", - viz_config_df = p0_viz_config_df, - viz_config_pal = p0_viz_config_pal$demographic_characteristics, - width = p0_viz_config_df$width_desktop, - height = p0_viz_config_df$height_desktop, - font_size = p0_viz_config_df$font_size_desktop, - barwidth = 20, - barheight = 1, - low_ramp_col = "#eef0ff" + tar_target( + p3_perc_latino_png_es, + plot_census_map( + census_data = p2_perc_census_acs5_layers_sf[[4]], + percent_leg = TRUE, + dollar_leg = FALSE, + lim_vals = c(0, 100), + break_vals = c(0, 25, 50, 75, 100), + var = 'percent', + conus_sf = p1_conus_sf, + outfile_path = "3_visualize/out/perc_hispanic_census_2022_es.png", + leg_title = "Porcentaje de Hispanos, 2022", + viz_config_df = p0_viz_config_df, + viz_config_pal = p0_viz_config_pal$demographic_characteristics, + width = p0_viz_config_df$width_desktop, + height = p0_viz_config_df$height_desktop, + font_size = p0_viz_config_df$font_size_desktop, + barwidth = 20, + barheight = 1, + low_ramp_col = "#eef0ff" + ), + format = "file" ), - format = "file" -), -tar_target( - p3_median_rent_png_es, - plot_census_map( - census_data = p2_census_acs5sub_household_data[[2]], - percent_leg = FALSE, - dollar_leg = TRUE, - lim_vals = c(0, 3000), - var = 'estimate', - conus_sf = p1_conus_sf, - outfile_path = "3_visualize/out/median_rent_2022_es.png", - leg_title = "Alquiler bruto medio, 2022", - viz_config_df = p0_viz_config_df, - viz_config_pal = p0_viz_config_pal$land_tenure, - width = p0_viz_config_df$width_desktop, - height = p0_viz_config_df$height_desktop, - font_size = p0_viz_config_df$font_size_desktop, - barwidth = 20, - barheight = 1, - low_ramp_col = "#ebfaf8" + tar_target( + p3_avg_household_size_png_es, + plot_census_map( + census_data = p2_census_acs5sub_household_data[[1]], + percent_leg = FALSE, + dollar_leg = FALSE, + lim_vals = c(1, 5), + var = 'estimate', + conus_sf = p1_conus_sf, + outfile_path = "3_visualize/out/avg_household_size_2022_es.png", + leg_title = "Tamaño promedio de los hogares, 2022", + viz_config_df = p0_viz_config_df, + viz_config_pal = p0_viz_config_pal$demographic_characteristics, + width = p0_viz_config_df$width_desktop, + height = p0_viz_config_df$height_desktop, + font_size = p0_viz_config_df$font_size_desktop, + barwidth = 20, + barheight = 1, + low_ramp_col = "#eef0ff" + ), + format = "file" ), - format = "file" -), -tar_target( - p3_perc_disable_png_es, - plot_census_map( - census_data = p2_census_acs5sub_disability_data[[1]], - percent_leg = TRUE, - dollar_leg = FALSE, - lim_vals = c(0, 50), - break_vals = c(0, 10, 20, 30, 40, 50), - var = 'estimate', - conus_sf = p1_conus_sf, - outfile_path = "3_visualize/out/perc_disabled_census_2022_es.png", - leg_title = "Porcentaje de discapacitados, 2022", - viz_config_df = p0_viz_config_df, - viz_config_pal = p0_viz_config_pal$demographic_characteristics, - width = p0_viz_config_df$width_desktop, - height = p0_viz_config_df$height_desktop, - font_size = p0_viz_config_df$font_size_desktop, - barwidth = 20, - barheight = 1, - low_ramp_col = "#eef0ff" + tar_target( + p3_median_rent_png_es, + plot_census_map( + census_data = p2_census_acs5sub_household_data[[2]], + percent_leg = FALSE, + dollar_leg = TRUE, + lim_vals = c(0, 3000), + var = 'estimate', + conus_sf = p1_conus_sf, + outfile_path = "3_visualize/out/median_rent_2022_es.png", + leg_title = "Alquiler bruto medio, 2022", + viz_config_df = p0_viz_config_df, + viz_config_pal = p0_viz_config_pal$land_tenure, + width = p0_viz_config_df$width_desktop, + height = p0_viz_config_df$height_desktop, + font_size = p0_viz_config_df$font_size_desktop, + barwidth = 20, + barheight = 1, + low_ramp_col = "#ebfaf8" + ), + format = "file" ), - format = "file" -) + tar_target( + p3_perc_disable_png_es, + plot_census_map( + census_data = p2_census_acs5sub_disability_data[[1]], + percent_leg = TRUE, + dollar_leg = FALSE, + lim_vals = c(0, 50), + break_vals = c(0, 10, 20, 30, 40, 50), + var = 'estimate', + conus_sf = p1_conus_sf, + outfile_path = "3_visualize/out/perc_disabled_census_2022_es.png", + leg_title = "Porcentaje de discapacitados, 2022", + viz_config_df = p0_viz_config_df, + viz_config_pal = p0_viz_config_pal$demographic_characteristics, + width = p0_viz_config_df$width_desktop, + height = p0_viz_config_df$height_desktop, + font_size = p0_viz_config_df$font_size_desktop, + barwidth = 20, + barheight = 1, + low_ramp_col = "#eef0ff" + ), + format = "file" + ) ) \ No newline at end of file diff --git a/3_visualize/src/plot_utils.R b/3_visualize/src/plot_utils.R index 270e09f2edb5170d5ab2fd97b54c84c0bd6fc328..fb311d1c194b04a8ffd94ce8c5c8f71741993996 100644 --- a/3_visualize/src/plot_utils.R +++ b/3_visualize/src/plot_utils.R @@ -17,7 +17,7 @@ #' @param break_vals, set legend breaks #' @param low_ramp_col, assign color to low end of color ramp for legend plot_census_map <- function(census_data, conus_sf, leg_title, outfile_path, var, - percent_leg, viz_config_df, viz_config_pal, width, height, + percent_leg, viz_config_df, viz_config_pal, width, height, font_size, barwidth, barheight, lim_vals, break_vals, dollar_leg, low_ramp_col){ @@ -105,4 +105,132 @@ plot_census_map <- function(census_data, conus_sf, leg_title, outfile_path, var, ggsave(outfile_path, final_map, width = width, height = height, dpi = viz_config_df$dpi, bg = viz_config_df$bg_col, units = "in") return(outfile_path) +} + + +# Map raster data +#' +#' @param in_raster character string - .tif file path of raster data for specified variable of interest +#' @param conus_sf, sf of conus states outline +#' @param conus_inner, sf of conus states outline not including US borders +#' @param counties_sf, sf of counties outline +#' @param viz_config_df `data.frame` width, height, counties outline color, conus outline color, background color, font nam, and font size +#' @param viz_config_pal `data.frame` assign colors for postively and negatively correlated dimensions for census maps +#' @param rast_type character string - choice of "pop_density" or "imp_surfaces" to indicate which map is being made +#' @param low_ramp_col, color for low end of color ramp +#' @param base_conus_fill, base fill used for conus background +#' @param base_conus_color, color used for state outlines +#' @param border_color, color used for inner state outlines and county outlines +#' @param leg_title, title to be used for the legend +#' @param font_size, set font size +#' @param barheight, set colorbar bar height +#' @param barwidth, set colorbar bar width +#' @param outfile_path, outfile path for pngs +#' @param width, set figure width dimension +#' @param height, set figure height dimension +plot_raster <- function(in_raster, conus_sf, conus_inner, counties_sf, + viz_config_df, viz_config_pal, rast_type, low_ramp_col, + base_conus_fill, base_conus_color, border_color, + leg_title, font_size, barheight, barwidth, outfile_path, + width, height){ + + raster_data <- rast(in_raster) + + # plot + font_legend <- viz_config_df$load_font + font_add_google(font_legend) + showtext_opts(dpi = 300, regular.wt = 200, bold.wt = 700) + showtext_auto(enable = TRUE) + + rast_map <- ggplot() + + geom_sf(data = conus_sf, fill = base_conus_fill, color = base_conus_color, linewidth = 0.9) + + geom_spatraster(data = raster_data)+ + geom_sf(data = conus_inner, fill = NA, color = border_color, linewidth = 0.5) + + geom_sf(data = counties_sf, fill = NA, color = border_color, linewidth = 0.1) + + labs(fill = leg_title) + + theme(plot.background = element_rect(fill = "white", color = "white"), + panel.background = element_rect(fill = "white", color = "white"), + text = element_text(family = viz_config_df$font_legend, size = font_size), + axis.title = element_blank(), + axis.text = element_blank(), + axis.ticks = element_blank(), + panel.grid = element_blank(), + legend.background = element_blank(), + legend.direction = "horizontal", + legend.margin = margin(t = 5, b = 5), + legend.position = "bottom", + legend.title.align = 0.5) + + guides(fill = guide_colorbar( + title.position = "top", + title.theme = element_text(face = 'bold', family = font_legend, size = font_size), + direction = "horizontal", + position = "bottom", + barwidth = barwidth, + barheight = barheight + )) + + if(rast_type == "pop_density"){ + rast_map <- rast_map + + scale_fill_gradientn( + colors = colorRampPalette(c(low_ramp_col, viz_config_pal))(100), + name = leg_title, + labels = c(1, 10, 100, '1k', '10k', '100k'), + na.value=NA + ) + + } else if(rast_type == "imp_surfaces") { + rast_map <- rast_map + + scale_fill_gradientn( + colors = colorRampPalette(c(low_ramp_col, viz_config_pal))(100), + name = leg_title, + limits = c(0, 100), + breaks = c(0, 25, 50, 75, 100), + labels = c("0%", "25%", "50%", "75%", "100%"), + na.value=NA + ) + } + + background_color = "white" + plot_margin = 0.025 + + # cowplot to get map sizes larger + canvas <- grid::rectGrob( + x = 0, y = 0, + width = 6, height = 6, + gp = grid::gpar(fill = background_color, alpha = 1, col = background_color + ) + ) + rast_map_legend <- get_plot_component(rast_map, 'guide-box', return_all = TRUE) + # compose final plot + final_map <- ggdraw(ylim = c(0,1), + xlim = c(0,1)) + + # White background + draw_grob(canvas, + x = 0, y = 1, + height = 6, width = 6, + hjust = 0, vjust = 1) + + # Add main plot + draw_plot(rast_map + theme(legend.position="none"), + x = -0.01, + y = 0.08, + height = 0.98, + width = (1-plot_margin)*1.03) + # Add legend + + final_map <- final_map + + if(rast_type == "pop_density"){ + draw_plot(rast_map_legend[[3]], + x = 0.48, + y = 0.03, + height = 0.09 , + width = 0.1 - plot_margin) + } else if(rast_type == "imp_surfaces") { + draw_plot(rast_map_legend[[3]], + x = 0.48, + y = 0.02, + height = 0.09 , + width = 0.1 - plot_margin) + } + + ggsave(outfile_path, final_map, width = width, height = height, dpi = viz_config_df$dpi, bg = viz_config_df$bg_col, units = "in") } \ No newline at end of file diff --git a/README.md b/README.md index e0d62529ff9da2c04136e9bae0cae91c9d9bf6e9..ccb4194f471728d602ffab89fc2125763380a4d7 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ This project: ## Running the targets pipeline in R -Clone the repo. In RStudio, run `library(targets)` and `tar_make()`. This will require `tidycensus` credentialing to run, see instructions below. +Clone the repo. In RStudio, run `library(targets)` and `tar_make()`. This will require `tidycensus`, `sciencebase`, and `NASA Earthdata` credentialing to run, see instructions below. ## `tidycensus` set up @@ -36,6 +36,28 @@ census_api_key("YOUR API KEY GOES HERE", install = TRUE) readRenviron("~/.Renviron") ``` +## ScienceBase login +To access controlled ScienceBase items, an additional step must be completed to authenticate a ScienceBase session before the targets pipeline is run. + +1. Ensure `.gitignore` includes a line for ".Renviron" to prevent credentials from being committed the the repository by git. +2. Run the entire contents of `00_config.R` either (1) interactively (i.e., line by line) or (2) by running `source("00_config.R")`. +3. You will be prompted to enter the token text by R/Rstudio. A browser window should pop-up directing you to <https://sciencebase.usgs.gov/manager/> to login. +4. Once logged in, copy your API token: click the account drop down button (person shaped icon) and click **Copy API Token**. +5. Paste the API token into the RStudio popup. + +Once the above steps are complete, `initialize_and_cache_sb()` will cache your username and token into the .Renviron file. From here, the pipeline should be able to use those cached credentials to re-initialize and refresh ScienceBase sessions in different R sessions for up to 10 hours. + +## NASA Earthdata +Population density data must be manually downloaded from <https://sedac.ciesin.columbia.edu/data/set/gpw-v4-population-count-rev11/data-download>. You will be prompted to login to a NASA Earthdata account. If you do not have one, you will need to create one. Once logged in, use these selections: + +- Temporal: Single Year +- FileFormat: GeoTiff +- Resolution: 30 second +- File Select: Year 2020 + +Download the zip in the `1_process/in/` folder. + + ## Building the website locally Clone the repo. In the directory, run `npm install` to install the required modules. Once the dependencies have been installed, run `npm run dev` to run locally from your browser. diff --git a/_targets.R b/_targets.R index 99ea25fbfec38c9ad6cf16b43f0214523ef47039..1f606075799269ffed33bb53de7e5a97fd24875d 100644 --- a/_targets.R +++ b/_targets.R @@ -15,7 +15,10 @@ tar_option_set(packages = c('tidyverse', 'readr', 'cowplot', 'rmapshaper', - 'jsonlite')) + 'jsonlite', + 'terra', + 'tidyterra', + 'raster')) # Phase target makefiles source("0_config.R")