-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathlocal-functions.R
More file actions
195 lines (135 loc) · 4.56 KB
/
local-functions.R
File metadata and controls
195 lines (135 loc) · 4.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
## query / aggregate each chunk
#' @param i integer vector of mukey
#' @param vars character vector of variable names
#' @param top top depth (cm)
#' @param bottom bottom depth (cm)
getDataByChunk <- function(i, vars, top, bottom) {
p <- try(
suppressMessages(
get_SDA_property(
property = vars,
method = "Weighted Average",
mukeys = as.integer(i),
top_depth = top,
bottom_depth = bottom,
include_minors = TRUE,
miscellaneous_areas = FALSE,
dsn = local.tabularDB
)
), silent = TRUE
)
if (inherits(p, 'try-error')) {
message('SDA query failed')
}
# TODO: any other error conditions?
return(p)
}
getUniqueValues <- function(i, files) {
r <- rast(files[i])
v <- unique(values(r, mat = FALSE, dataframe = FALSE, na.rm = TRUE))
v <- data.table(mukey = v)
return(v)
}
## TODO: sync aggregation functions with output data type
mosaicProperty <- function(i, input.dir, output.dir, do.aggregate = TRUE, agg.fact = 9, agg.fun = c('modal', 'mean')) {
# current tile set
fl <- list.files(path = input.dir, pattern = i, full.names = TRUE)
# assemble pieces
x <- vrt(fl)
# output file name
f <- file.path(output.dir, sprintf("%s-lowres.tif", i))
f.highres <- file.path(output.dir, sprintf("%s.tif", i))
# convert VRT -> single raster
writeRaster(x, filename = f.highres, overwrite = TRUE)
# optionally aggregate directly to file
if(do.aggregate) {
aggregate(x, fact = agg.fact, fun = agg.fun, na.rm = TRUE, filename = f, overwrite = TRUE)
}
rm(x)
gc(reset = TRUE)
return(NULL)
}
## TODO: what do 0's in the grid represent?
makeThematicTile <- function(i, tiles, vars, output.dir) {
# current tile
x <- rast(tiles[i])
# init grid of IDs + RAT
x <- as.factor(x)
# set layer name in object
names(x) <- 'mukey'
# extract RAT for thematic mapping
# will be NULL if all cells are NA
rat <- cats(x)[[1]]
# check for an entirely NULL tile (STATSGO 300m, tile 90)
if(is.null(rat)) {
# write blank tiles
for (.var in vars) {
# automatic use of LZW compression
writeRaster(x, filename = file.path(output.dir, sprintf('%s_%03d.tif', .var, i)), overwrite = TRUE)
}
# next tile
return(NULL)
}
# re-name mukey column for consistency across input grids
names(rat)[2] <- 'mukey'
# subset LUT to current set of mukey
# ensure LUT only contains columns of interest
p <- lut[which(lut$mukey %in% rat$mukey), c('mukey', vars)]
# merge aggregate data into RAT
rat <- merge(rat, p, by.x = 'mukey', by.y = 'mukey', sort = FALSE, all.x = TRUE)
# re-pack RAT
# `ID` must be the first column in the RAT
levels(x) <- rat[, c('ID', 'mukey', vars)]
# ~ 20 minutes per tile, when using 10x10 tiles
# ~ 2 minutes per tile, when using 20x20 tiles
# grid + RAT -> stack of numerical grids
# 35 seconds
# system.time(x.stack <- catalyze(x))
# 4.8 seconds / variable
# system.time(x.stack <- as.numeric(x, index = vars[1]))
# 2025-12-20: as.numeric() is the slowest part of this function - why?
#
# as.numeric(): 9.24 seconds / variable
# catalyze(): 9.4 seconds / variable
# continuous properties
for (.var in vars) {
# automatic use of LZW compression
.x <- as.numeric(x, index = .var)
writeRaster(.x, filename = file.path(output.dir, sprintf('%s_%03d.tif', .var, i)), overwrite = TRUE)
}
## TODO: categorical properties
## consider removing terra objects and garbage-collecting
rm(x, .x)
gc(reset = TRUE)
# TODO: trap and return errors?
}
#' @title Create temporary tiles of a mukey grid
#'
#' @param mu map unit key grid, `SpatRaster`
#' @param tg tile system, `sf` polygons
#' @param output.dir output directory path
#'
tileMukeyGrid <- function(mu, tg, output.dir) {
# start fresh
unlink(output.dir, recursive = TRUE)
dir.create(output.dir)
# iterate over vector tiles
n <- nrow(tg)
pb <- progress_bar$new(format = '[:bar] :percent (:eta)', total = n)
# save -> mukey grid tiles
for (i in 1:n) {
# crop to current tile
x <- crop(mu, tg[i, ])
## TODO: consider converting into a factor here
# save tile as UInt32
fn <- file.path(output.dir, sprintf('tile-%03d.tif', i))
writeRaster(x, filename = fn, overwrite = TRUE, datatype = 'INT4U')
# double-check output is correct
# gdal_utils(util = 'info', source = fn)
# remove temporary terra objects and garbage-collecting
rm(x)
gc(reset = TRUE)
pb$tick()
}
pb$terminate()
}