88# ' @param polygon_id_col the name of a column in the `polygons` object with a
99# ' unique identifier for each polygon
1010# ' @param grid a raster layer with the same spatial resolution as the data
11+ # ' (must use geographic coordinates)
1112# ' @param secondary_weights an optional table of secondary weights, output from
1213# ' the `secondary_weights()` function
1314# '
1617# '
1718# ' @examples
1819# ' overlay_output_with_secondary_weights <- overlay_weights(
19- # ' polygons = nj_counties , # Polygons outlining the 21 counties of New Jersey
20+ # ' polygons = tigris::counties("nj") , # Polygons outlining the 21 counties of New Jersey
2021# ' polygon_id_col = "COUNTYFP", # The name of the column with the unique
2122# ' # county identifiers
2223# ' grid = era5_grid, # The grid to use when extracting area weights (era5_grid is the
3233# '
3334# '
3435# ' overlay_output_without_secondary_weights <- overlay_weights(
35- # ' polygons = nj_counties , # Polygons outlining the 21 counties of New Jersey
36+ # ' polygons = tigris::counties("nj") , # Polygons outlining the 21 counties of New Jersey
3637# ' polygon_id_col = "COUNTYFP" # The name of the column with the unique county
3738# ' # identifiers
3839# ' )
4344# ' @export
4445overlay_weights <- function (polygons , polygon_id_col , grid = era5_grid , secondary_weights = NULL ){
4546
46- # Create raster (Putting terra::rast() here creates, for unknown reasons,
47- # issues with devtools::check())
48- clim_raster <- as(grid , " SpatRaster" ) # only reads the first band
47+ # # check to make sure climate raster is a spatraster, change if not
48+ if (! inherits(grid , " SpatRaster" )) {
49+ clim_raster <- terra :: rast(grid )
50+ } else {
51+
52+ clim_raster <- grid
4953
54+ }
5055
5156 # # Raster cell area
5257 # # -----------------------------------------------
@@ -62,6 +67,12 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
6267 rast_xmax <- terra :: ext(clim_area_raster )$ xmax
6368 rast_res <- terra :: xres(clim_area_raster )
6469
70+ # # check if SpatRaster is in geographic coodrinates
71+ if (! terra :: is.lonlat(clim_raster )) {
72+ stop(crayon :: red(' Grid does not have geographic coordinates.' ))
73+
74+ }
75+
6576 # # stop if polygons are not in standard coordinate system
6677 if (poly_xmax > 180 ) {
6778
@@ -70,7 +81,13 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
7081 }
7182
7283 # # check if coordinate systems match, if no shift raster to -180 to 180
73- if (rast_xmax > 180 + rast_res / 2 ) {
84+ if (rast_xmax > 180 + rast_res ) {
85+
86+ # Make sure the cell widths aren't peculiar otherwise the rotate function will
87+ # mess things up
88+ if (360 %% terra :: xres(clim_raster ) != 0 ){
89+ 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.' ))
90+ }
7491
7592 message(crayon :: yellow(' Aligning longitudes to standard coordinates.' ))
7693
@@ -91,8 +108,13 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
91108 # # rotate
92109 clim_area_raster <- terra :: rotate(clim_area_raster )
93110
94- }
111+ }
95112
113+ # Extend the grid to cover all polygons consistent with the extended rotate
114+ # above. exact_extract already does this in the background to a certain
115+ # degree, so this just allows us to be explicit about how we handle NAs later
116+ # on.
117+ clim_area_raster <- terra :: extend(clim_area_raster , terra :: ext(polygons ), snap = ' out' )
96118
97119 # # Match raster and polygon crs
98120 crs_raster <- terra :: crs(clim_area_raster )
@@ -122,11 +144,11 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
122144 s_weight_max <- max(weights_dt $ x )
123145
124146 # # if secondary_weights is in 0-360, adjust x val
125- if (s_weight_max > 180 + rast_res ) {
147+ if (s_weight_max > 180 + rast_res / 2 ) {
126148
127149 message(crayon :: yellow(' Adjusting secondary weights longitude to standard coordinates.' ))
128150
129- weights_dt [, x : = data.table :: fifelse(x > 180 + rast_res , x - 360 , x )]
151+ weights_dt [, x : = data.table :: fifelse(x > 180 + rast_res / 2 , x - 360 , x )]
130152
131153 }
132154
@@ -165,25 +187,19 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
165187 w_merged [, weight : = weight * w_area ]
166188
167189 # Create column that determines if entire polygon has a weight == 0
168- zero_polys <- data.frame (w_merged ) | >
169- dplyr :: group_by(poly_id ) | >
170- dplyr :: summarise(sum_weight = sum(weight )) | >
171- dplyr :: ungroup() | >
172- dplyr :: filter(sum_weight == 0 ) | >
173- dplyr :: select(poly_id ) | >
174- dplyr :: distinct()
190+ zero_polys <- w_merged [, .(sum_weight = sum(weight )),
191+ by = .(poly_id )]
192+
193+ zero_polys <- unique(zero_polys [sum_weight == 0 , .(poly_id )])
175194
176- if (nrow(zero_polys > 0 ) ) {
195+ if (nrow(zero_polys ) > 0 ) {
177196
178197 warning(crayon :: red(" Warning: weight = 0 for all pixels in some of your polygons; NAs will be returned for weights" ))
179198
180199 }
181200
182201 # List any polygons with NA values in 1 or more grid cells
183- na_polys <- data.frame (w_merged ) | >
184- dplyr :: filter(is.na(weight )) | >
185- dplyr :: select(poly_id ) | >
186- dplyr :: distinct()
202+ na_polys <- unique(w_merged [is.na(weight ), .(poly_id )])
187203
188204 # # Warning if there are polygons with NA weight values
189205 # if(nrow(na_polys > 0)) {
@@ -193,12 +209,8 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
193209 # }
194210
195211 # Update the weight to NA for all grid cells in na_polys
196- w_merged <- w_merged | >
197- dplyr :: mutate(weight = ifelse(poly_id %in% c(na_polys $ poly_id , zero_polys $ poly_id ), NA , weight )) | >
198- data.table :: as.data.table()
199-
200- # # this doesn't work with dt... figure out or delete and use above
201- # w_merged[, weight := data.table::fifelse(poly_id %in% c(na_polys$poly_id, zero_polys$poly_id), NA, weight)]
212+ w_merged <- w_merged [, weight : = ifelse(poly_id %in% c(na_polys $ poly_id ,
213+ zero_polys $ poly_id ), NA , weight )]
202214
203215 }
204216
@@ -231,7 +243,7 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
231243 # Check that polygon weights sum to 1 or 0 if all weights are NA
232244 if (! is.null(secondary_weights )){
233245
234- for (i in nrow(check_weights )){
246+ for (i in seq_len( nrow(check_weights ) )){
235247
236248 if (! dplyr :: near(check_weights $ w_area [i ], 1 , tol = 0.001 )) {
237249
@@ -246,7 +258,7 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
246258
247259 } else {
248260
249- for (i in nrow(check_weights )){
261+ for (i in seq_len( nrow(check_weights ) )){
250262
251263 if (! dplyr :: near(check_weights $ w_sum [i ], 1 , tol = 0.001 )){
252264
@@ -262,10 +274,15 @@ overlay_weights <- function(polygons, polygon_id_col, grid = era5_grid, secondar
262274 # If it doesn't error out then all weight sums = 1
263275 message(crayon :: green(' All weights sum to 1.' ))
264276
265- # # Convert back to 0-360
266- # # -----------------------------------------------
277+ # # Return table in coordinate system that matches that of the climate data
278+ # # ------------------------------------------------------------------------
279+
280+ if (rast_xmax > 180 + rast_res ) {
281+
282+ w_norm [, x : = data.table :: fifelse(x < 0 + rast_res / 2 , x + 360 , x )]
283+
284+ }
267285
268- w_norm [, x : = data.table :: fifelse(x < 0 , x + 360 , x )]
269286
270287 return (w_norm )
271288
0 commit comments