Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
f75e222
Modifying the reverse rotate portion of daily_aggregation (from -180_…
Sep 30, 2024
0caf40f
Renaming clim_raster to clim_stack
Oct 2, 2024
d5b0c8c
Replaced user level rasters and raster stacks with spatRasters. Compl…
Oct 4, 2024
32422e4
More information on how world wide datasets were generated
Oct 4, 2024
e59ffa1
Resaved era5_grid cause it wasn't working
Oct 4, 2024
ded3796
Reverted data files back to raster package because usethis::use_data(…
Oct 4, 2024
a15fcc2
Finished staggregate raster to terra conversion
Oct 14, 2024
1261aab
Ran use_this::use_pkgdown() and added .githhub to the .Rbuildignore
tliddell4 Nov 6, 2024
070d55b
Finalized terra conversion and removed nj_counties from data to reduc…
tliddell4 Nov 6, 2024
b255f29
Updated R and RStudio which assigned a ProjectId
tliddell4 Jan 19, 2025
e152db5
Implemented user defined tolerance for joining overlay_weights and cl…
tliddell4 Feb 21, 2025
09a4ca0
Fully integrated weights_join_tolerance argument into the package and…
tliddell4 Feb 21, 2025
7ea8a0e
Fixed reference issue wherin we were overwriting user's overlay_weigh…
tliddell4 Feb 24, 2025
cf7e219
modify so that the coordinate syste for the final table matches that …
traceybit Feb 26, 2025
0a06b9c
Merge pull request #45 from tcarleton/weights_fns_optimization
traceybit Feb 26, 2025
44586cb
Merge pull request #44 from tcarleton/37-weird_cell_widths
tliddell4 Mar 1, 2025
70ab8e9
Removed rotate from staggregate
tliddell4 Mar 2, 2025
3e1e7e9
Being consistent about how we're evaluating climate vs standard coord…
tliddell4 Mar 2, 2025
16dd094
Updating data to all be -180 to 180
tliddell4 Mar 2, 2025
329dc94
Throw an error if rotating a spatrast that shouldn't be rotated.
tliddell4 Mar 12, 2025
248df0b
Correction to weird cell width check
tliddell4 Mar 12, 2025
7f2329e
Merge pull request #46 from tcarleton/remove_rotate_from_staggregate
tliddell4 Mar 12, 2025
701ebee
Made sure the climate data covers the polygons regardless of whether …
tliddell4 Mar 14, 2025
a4b4cfe
Added na_rm argument
tliddell4 Mar 15, 2025
6d06902
Merge pull request #47 from tcarleton/42-remove_na_option
tliddell4 Mar 15, 2025
67be65e
updated to make sure climate raster is read in as spatraster; adjuste…
traceybit Mar 15, 2025
73f8627
Changed is to inherits
tliddell4 Mar 15, 2025
fe3fb94
Merge branch 'terra_conversion' of https://github.com/tcarleton/stagg…
tliddell4 Mar 15, 2025
3c930a6
added check for peculiar cell widths in 0-360 coordiant format for bo…
traceybit Mar 15, 2025
a5bfe7c
adjusted to read cliamte data in as spat raster; adjusted resolutions…
traceybit Mar 15, 2025
1741c95
Merge branch 'terra_conversion' of https://github.com/tcarleton/stagg…
tliddell4 Mar 15, 2025
d60c00f
ERA5 data update
tliddell4 Mar 15, 2025
3d3f06e
incorporate updates based on cullen's suggestions for code review
traceybit Apr 16, 2025
153c6de
change position in code
traceybit Apr 16, 2025
afcc2c9
format spacing
traceybit Apr 17, 2025
82c3171
flipped back
traceybit Apr 22, 2025
98389b7
update proj id
traceybit Apr 22, 2025
ab61213
Updated documentation
tliddell4 Apr 30, 2025
c78730b
Further implementation of Cullen's suggestions
tliddell4 Apr 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@
^data-raw$
^doc$
^Meta$
^_pkgdown\.yml$
^docs$
^pkgdown$
^\.github$
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
inst/doc
/doc/
/Meta/
docs
9 changes: 6 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,19 @@ Imports:
lubridate,
magrittr,
methods,
raster,
sf,
stringr,
terra
Suggests:
climateR (>= 0.3.5),
knitr,
raster,
rmarkdown,
testthat (>= 3.0.0),
tidyr,
tigris,
usethis
usethis,
tigris
Config/testthat/edition: 3
VignetteBuilder: knitr
Remotes:
mikejohnson51/climateR
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ importFrom(magrittr,"%>%")
importFrom(methods,as)
importFrom(methods,setMethod)
importFrom(methods,signature)
importFrom(stats,na.omit)
7 changes: 6 additions & 1 deletion R/data_cropland_world_2015_era5.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#' Global cropland weights
#'
#' A data.table with ERA5 resolution returned by running secondary_weights() with cropland data from
#' 2015
#' 2015 from https://glad.umd.edu/dataset/croplands
#'
#' Dataset Reference: P. Potapov, S. Turubanova, M.C. Hansen, A. Tyukavina, V.
# Zalles, A. Khan, X.-P. Song, A. Pickens, Q. Shen, J. Cortez. (2021) Global
# maps of cropland extent and change show accelerated cropland expansion in the
# twenty-first century. Nature Food. https://doi.org/10.1038/s43016-021-00429-z
#'
"cropland_world_2015_era5"
6 changes: 0 additions & 6 deletions R/data_nj_counties.R

This file was deleted.

31 changes: 28 additions & 3 deletions R/global_variables.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,31 @@
# This is because we are referencing column names in dplyr / data.table objects which use
# Non-Standard Evaluation.

globalVariables(c("cell_area_km2", "coverage_fraction", "day", "era5_grid",
"hour", "month", "poly_id", "sum_weight", "value", "w_area",
"w_sum", "weight", "x", "y", "year", "."))
globalVariables(
c(
"cell_area_km2",
"coverage_fraction",
"day",
"era5_grid",
"hour",
"month",
"minute",
"poly_id",
"sum_weight",
"value",
"w_area",
"w_sum",
"weight",
"x",
"y",
"year",
".",
"is_right_xmin",
"is_left_xmax",
"x_low",
"x_high",
"y_low",
"y_high",
"..cols_to_keep"
)
)
81 changes: 49 additions & 32 deletions R/overlay_weights.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#' @param polygon_id_col the name of a column in the `polygons` object with a
#' unique identifier for each polygon
#' @param grid a raster layer with the same spatial resolution as the data
#' (must use geographic coordinates)
#' @param secondary_weights an optional table of secondary weights, output from
#' the `secondary_weights()` function
#'
Expand All @@ -16,7 +17,7 @@
#'
#' @examples
#' overlay_output_with_secondary_weights <- overlay_weights(
#' polygons = nj_counties, # Polygons outlining the 21 counties of New Jersey
#' polygons = tigris::counties("nj"), # Polygons outlining the 21 counties of New Jersey
#' polygon_id_col = "COUNTYFP", # The name of the column with the unique
#' # county identifiers
#' grid = era5_grid, # The grid to use when extracting area weights (era5_grid is the
Expand All @@ -32,7 +33,7 @@
#'
#'
#' overlay_output_without_secondary_weights <- overlay_weights(
#' polygons = nj_counties, # Polygons outlining the 21 counties of New Jersey
#' polygons = tigris::counties("nj"), # Polygons outlining the 21 counties of New Jersey
#' polygon_id_col = "COUNTYFP" # The name of the column with the unique county
#' # identifiers
#' )
Expand All @@ -43,10 +44,14 @@
#' @export
overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondary_weights = NULL){

# Create raster (Putting terra::rast() here creates, for unknown reasons,
# issues with devtools::check())
clim_raster <- as(grid, "SpatRaster") # only reads the first band
## check to make sure climate raster is a spatraster, change if not
if (!inherits(grid, "SpatRaster")) {
clim_raster <- terra::rast(grid)
} else {

clim_raster <- grid

}

## Raster cell area
## -----------------------------------------------
Expand All @@ -62,6 +67,12 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
rast_xmax <- terra::ext(clim_area_raster)$xmax
rast_res <- terra::xres(clim_area_raster)

## check if SpatRaster is in geographic coodrinates
if(!terra::is.lonlat(clim_raster)) {
stop(crayon::red('Grid does not have geographic coordinates.'))

}

## stop if polygons are not in standard coordinate system
if(poly_xmax > 180) {

Expand All @@ -70,7 +81,13 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
}

## check if coordinate systems match, if no shift raster to -180 to 180
if(rast_xmax > 180 + rast_res / 2) {
if(rast_xmax > 180 + rast_res) {

# Make sure the cell widths aren't peculiar otherwise the rotate function will
# mess things up
if(360 %% terra::xres(clim_raster) != 0){
stop(crayon::red('Grid is in climate coordinate system (longitude 0 to 360) and grid cell width does not divide 360 evenly, making accurate alignment impossible.'))
}

message(crayon::yellow('Aligning longitudes to standard coordinates.'))

Expand All @@ -91,8 +108,13 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
## rotate
clim_area_raster <- terra::rotate(clim_area_raster)

}
}

# Extend the grid to cover all polygons consistent with the extended rotate
# above. exact_extract already does this in the background to a certain
# degree, so this just allows us to be explicit about how we handle NAs later
# on.
clim_area_raster <- terra::extend(clim_area_raster, terra::ext(polygons), snap = 'out')

## Match raster and polygon crs
crs_raster <- terra::crs(clim_area_raster)
Expand Down Expand Up @@ -122,11 +144,11 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
s_weight_max <- max(weights_dt$x)

## if secondary_weights is in 0-360, adjust x val
if(s_weight_max > 180 + rast_res) {
if(s_weight_max > 180 + rast_res / 2) {

message(crayon::yellow('Adjusting secondary weights longitude to standard coordinates.'))

weights_dt[, x := data.table::fifelse(x > 180 + rast_res, x - 360, x)]
weights_dt[, x := data.table::fifelse(x > 180 + rast_res / 2, x - 360, x)]

}

Expand Down Expand Up @@ -165,25 +187,19 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
w_merged[, weight := weight * w_area]

# Create column that determines if entire polygon has a weight == 0
zero_polys <- data.frame(w_merged) |>
dplyr::group_by(poly_id) |>
dplyr::summarise(sum_weight = sum(weight)) |>
dplyr::ungroup() |>
dplyr::filter(sum_weight == 0) |>
dplyr::select(poly_id) |>
dplyr::distinct()
zero_polys <- w_merged[, .(sum_weight = sum(weight)),
by = .(poly_id)]

zero_polys <- unique(zero_polys[sum_weight == 0, .(poly_id)])

if(nrow(zero_polys > 0)) {
if(nrow(zero_polys) > 0) {

warning(crayon::red("Warning: weight = 0 for all pixels in some of your polygons; NAs will be returned for weights"))

}

# List any polygons with NA values in 1 or more grid cells
na_polys <- data.frame(w_merged) |>
dplyr::filter(is.na(weight)) |>
dplyr::select(poly_id) |>
dplyr::distinct()
na_polys <- unique(w_merged[is.na(weight), .(poly_id)])

# # Warning if there are polygons with NA weight values
# if(nrow(na_polys > 0)) {
Expand All @@ -193,12 +209,8 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
# }

# Update the weight to NA for all grid cells in na_polys
w_merged <- w_merged |>
dplyr::mutate(weight = ifelse(poly_id %in% c(na_polys$poly_id, zero_polys$poly_id), NA, weight)) |>
data.table::as.data.table()

## this doesn't work with dt... figure out or delete and use above
# w_merged[, weight := data.table::fifelse(poly_id %in% c(na_polys$poly_id, zero_polys$poly_id), NA, weight)]
w_merged <- w_merged[, weight := ifelse(poly_id %in% c(na_polys$poly_id,
zero_polys$poly_id), NA, weight)]

}

Expand Down Expand Up @@ -231,7 +243,7 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
# Check that polygon weights sum to 1 or 0 if all weights are NA
if (!is.null(secondary_weights)){

for(i in nrow(check_weights)){
for(i in seq_len(nrow(check_weights))){

if(!dplyr::near(check_weights$w_area[i], 1, tol=0.001)) {

Expand All @@ -246,7 +258,7 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar

} else {

for(i in nrow(check_weights)){
for(i in seq_len(nrow(check_weights))){

if(!dplyr::near(check_weights$w_sum[i], 1, tol=0.001)){

Expand All @@ -262,10 +274,15 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
# If it doesn't error out then all weight sums = 1
message(crayon::green('All weights sum to 1.'))

## Convert back to 0-360
## -----------------------------------------------
## Return table in coordinate system that matches that of the climate data
## ------------------------------------------------------------------------

if(rast_xmax > 180 + rast_res) {

w_norm[, x := data.table::fifelse(x < 0 + rast_res / 2, x + 360, x)]

}

w_norm[, x := data.table::fifelse(x < 0, x + 360, x)]

return(w_norm)

Expand Down
42 changes: 34 additions & 8 deletions R/secondary_weights.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#' @param secondary_raster a raster of a secondary variable, for example
#' cropland coverage or population
#' @param grid a raster layer with the same spatial resolution as the climate
#' data
#' data (must use geographic coordinates)
#' @param extent an optional extent to crop the secondary_raster to for faster
#' processing. Format must be compatible with raster::crop(). The default is "full", which
#' resamples the whole secondary raster without cropping.
Expand All @@ -32,7 +32,7 @@ secondary_weights <- function(secondary_raster, grid = era5_grid, extent = "full
## Return error if terra::extent can't inherit from the value supplied
## won't be able to check if secondary raster fully overlaps if
## this input isn't compatible with terra::extent()
if(!is.character(extent) | length(extent) > 1){
if(!is.character(extent) || length(extent) > 1){
tryCatch({
terra::ext(extent)
message(crayon::green("User-defined extent compatible with raster"))
Expand Down Expand Up @@ -72,12 +72,26 @@ secondary_weights <- function(secondary_raster, grid = era5_grid, extent = "full

}

## check to make sure climate raster is a spatraster, change if not
if (!inherits(grid, "SpatRaster")) {
clim_raster <- terra::rast(grid)
} else {

clim_raster <- grid

}

## check if SpatRaster is in geographic coodrinates
if(!terra::is.lonlat(clim_raster)) {
stop(crayon::red('Grid does not have geographic coordinates.'))

}

# Create climate raster from input raster
clim_raster <- terra::rast(grid) # only reads the first band
clim_raster <- clim_raster[[1]] # only reads the first band

## climate raster information for creating buffer and doing checks/rotations
c_rast_xmax <- terra::ext(clim_raster)$xmax
# c_rast_xmin <- raster::extent(clim_raster)@xmin

## find xy resolution for rasters
c_rast_xres <- terra::xres(clim_raster)
Expand Down Expand Up @@ -137,7 +151,13 @@ secondary_weights <- function(secondary_raster, grid = era5_grid, extent = "full


## if secondary raster in -180 to 180 and clim raster 0-360, rotate clim raster
if(s_rast_xmax <= (180 + s_rast_xres / 2) & c_rast_xmax >= (180 + c_rast_xres / 2)) {
if(s_rast_xmax < (180 + s_rast_xres) & c_rast_xmax > (180 + c_rast_xres)) {

# Make sure the cell widths aren't peculiar otherwise the rotate function will
# mess things up
if(360 %% c_rast_xres != 0){
stop(crayon::red('Grid is in climate coordinate system (longitude 0 to 360) and grid cell width does not divide 360 evenly, making accurate alignment impossible.'))
}

message(crayon::yellow('Longitude coordinates do not match. Aligning longitudes to standard coordinates.'))

Expand All @@ -160,7 +180,13 @@ secondary_weights <- function(secondary_raster, grid = era5_grid, extent = "full
}

## if secondary raster in 0-360 and clim raster -180 to 180, rotate secondary raster
if(s_rast_xmax >= (180 + s_rast_xres / 2) & c_rast_xmax <= (180 + c_rast_xres / 2)) {
if(s_rast_xmax > (180 + s_rast_xres) & c_rast_xmax < (180 + c_rast_xres)) {

# Make sure the cell widths aren't peculiar otherwise the rotate function will
# mess things up
if(360 %% s_rast_xres != 0){
stop(crayon::red('Grid is in climate coordinate system (longitude 0 to 360) and grid cell width does not divide 360 evenly, making accurate alignment impossible.'))
}

message(crayon::yellow('Longitude coordinates do not match. Aligning longitudes to standard coordinates.'))

Expand All @@ -186,14 +212,14 @@ secondary_weights <- function(secondary_raster, grid = era5_grid, extent = "full
## crop the ERA/climate raster to the appropriate extent
## use the extent of the previously user-cropped secondary raster
## -----------------------------------------------

# Find the difference between the climate raster resolution and secondary raster resolution
clim_raster <- terra::crop(clim_raster, terra::ext(secondary_raster), snap="out")

## set crs of secondary raster to match climate data
## -----------------------------------------------
terra::crs(secondary_raster) <- terra::crs(clim_raster)


## check if the cropped secondary raster contains NA values
if(isTRUE(any(is.na(terra::values(secondary_raster, na.rm=FALSE))))) {

Expand All @@ -206,7 +232,7 @@ secondary_weights <- function(secondary_raster, grid = era5_grid, extent = "full
## -----------------------------------------------
message(crayon::green("Resampling secondary_raster"))

resampled_raster = terra::resample(secondary_raster, clim_raster, method="bilinear")
resampled_raster <- terra::resample(secondary_raster, clim_raster, method="bilinear")

## Make a data.table of the values of the resampled raster with lat/lon
## -----------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions R/stagg-package.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#' @importFrom data.table .NGRP
#' @importFrom data.table .SD
#' @importFrom data.table data.table
#' @importFrom stats na.omit
#' @importFrom magrittr %>%
#' @importFrom methods as
#' @importFrom methods setMethod
Expand Down
Loading
Loading