forked from rspatial/raster
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsummarize-raster.R
72 lines (60 loc) · 2.2 KB
/
summarize-raster.R
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
is_integer <- function(x) {
is.integer(x) || (is.numeric(x) && all(x == as.integer(x)))
}
make_block <- function(x, n = nlayers(x), chunksize = 1, n_rows = NULL) {
stopifnot(inherits(x, "Raster"))
stopifnot(is.numeric(chunksize), length(chunksize) == 1, chunksize > 0.01)
stopifnot(is_integer(n), length(n) == 1, n > 0)
# convert to gb
chunksize <- chunksize * 1e9
# calculate rows per chunksize
if (!is.null(n_rows)) {
stopifnot(is_integer(n_rows), length(n_rows) == 1, n_rows > 0)
n_rows <- min(n_rows, nrow(x))
rows_per_block <- n_rows
} else {
row_bytes <- 8 * n * ncol(x)
rows_per_block <- floor(chunksize / row_bytes)
}
# always process full rows, limit to rows in input raster
rows_per_block <- min(nrow(x), max(rows_per_block, 1))
# create blocks
start_row <- seq(1, nrow(x), by = rows_per_block)
n_blocks <- length(start_row)
n_rows <- rep(rows_per_block, n_blocks)
# correct size of final block
dif <- n_blocks * rows_per_block - nrow(x)
n_rows[length(n_rows)] <- n_rows[length(n_rows)] - dif
return(list(start_row = start_row, n_rows = n_rows, n = n_blocks))
}
summarize_raster <- function(x, fun = c("mean", "sum"),
chunksize = 1, n_rows = NULL,
filename = rasterTmpFile(),
...) {
stopifnot(inherits(x, "Raster"))
stopifnot(is.numeric(chunksize), length(chunksize) == 1, chunksize > 0.01)
if (!is.null(n_rows)) {
stopifnot(is_integer(n_rows), length(n_rows) == 1, n_rows > 0)
}
stopifnot(is.character(filename), length(filename) == 1)
fun <- match.arg(fun)
out <- raster(x)
if (fun == "mean") {
fun = rowMeans
} else if (fun == "sum") {
fun = rowSums
}
x <- readStart(x)
out <- writeStart(out, filename = filename, ...)
b <- make_block(out, n = 2 * (nlayers(x) + 1),
chunksize = chunksize, n_rows = n_rows)
message(paste("Using", b$n, "blocks of", b$n_rows[1], "rows."))
for (i in seq_along(b$start_row)) {
v <- getValues(x, row = b$start_row[i], nrows = b$n_rows[i])
v <- fun(v, na.rm = TRUE)
out <- writeValues(out, v, b$start_row[i])
}
out <- writeStop(out)
x <- readStop(x)
return(out)
}