Nothing
library(data.table)
library(terra)
SIG_DIGS <- 4
DESIRED_ROWS <- 5000
DAY <- seq(0, 366)
PERCENT <- seq(0, 100)
RADIANS <- seq(-360, 360, by = 0.1) * pi / 180
ZERO_OR_ONE <- list(0, 1)
ACCEL <- ZERO_OR_ONE
ASPECT <- RADIANS
BOOL <- c(TRUE, FALSE)
BUI <- seq(0, 1000, by = 0.1)
BUIEFF <- ZERO_OR_ONE
CBH <- seq(0, 200, by = 0.1)
CC <- PERCENT
CFB <- seq(-1, 2, by = 0.01)
CFL <- seq(-10, 4000, by = 0.1)
D0 <- DAY
DC <- seq(0, 1000, by = 0.1)
DMC <- seq(0, 1000, by = 0.1)
DJ <- DAY
ELV <- seq(0, 10000)
FC <- seq(-10, 20000)
FFMC <- seq(0, 101, by = 0.1)
FMC <- seq(0, 500, by = 0.1)
FRACTION <- seq(0, 1, by = 0.05)
FUELTYPE <- c(
"NF", "WA", "C1", "C2", "C3", "C4", "C5", "C6", "C7",
"D1", "M1", "M2", "M3", "M4", "S1", "S2",
"S3", "O1A", "O1B"
)
GFL <- seq(0, 100)
GS <- seq(0, 200)
HR <- seq(0, 366 * 24) * 60
HOURS <- seq(0, 23)
ISI <- seq(0, 300, by = 0.1)
LAT <- seq(-90, 90, by = 0.1)
LB <- seq(-1, 1.1, by = 0.01)
# FIX: for some reason the original package just makes negatives positive
LONG <- abs(seq(-180, 360, by = 0.1))
MON <- seq(1, 12)
PC <- PERCENT
PDF <- PERCENT
PREC <- seq(-10, 300, by = 0.01)
RH <- seq(-10, 110, by = 0.01)
ROS <- seq(0, 600, by = 0.01)
SAZ <- RADIANS + pi
SAZ <- ifelse(SAZ > 2 * pi, SAZ - 2 * pi, SAZ)
SD <- unlist(append(list(-999), seq(0, 100)))
SFC <- seq(0, 20000)
SH <- seq(-10, 110)
TEMP <- seq(-30, 60, by = 0.1)
WD <- RADIANS
WS <- seq(0, 300, by = 0.1)
THETA <- seq(-360, 360, by = 0.01)
WSV <- seq(-10, 500, by = 0.1)
WAZ <- RADIANS + pi
WAZ <- ifelse(WAZ > 2 * pi, WAZ - 2 * pi, WAZ)
FBP_ARGS <- list(
data.table(ID = 1),
data.table(FUELTYPE = FUELTYPE),
data.table(FFMC = FFMC),
data.table(BUI = BUI),
data.table(WS = WS),
data.table(WD = WD),
data.table(FMC = FMC),
data.table(GS = GS),
data.table(LAT = LAT),
data.table(LONG = LONG),
data.table(ELV = ELV),
data.table(DJ = DJ),
data.table(D0 = D0),
data.table(SD = SD),
data.table(SH = SH),
data.table(HR = HR),
data.table(PC = PC),
data.table(PDF = PDF),
data.table(GFL = GFL),
data.table(CC = CC),
data.table(THETA = THETA),
data.table(ACCEL = ACCEL),
data.table(ASPECT = ASPECT),
data.table(BUIEFF = BUIEFF),
data.table(CBH = CBH),
data.table(CFL = CFL),
data.table(ISI = ISI)
)
get_data_path <- function(name, suffix="csv") {
return(test_path("data", sprintf("%s.%s", name, suffix)))
}
read_data <- function(name) {
return(read.csv(get_data_path(name)))
}
get_raster_path <- function(name) {
return(get_data_path(name, "tif"))
}
read_raster <- function(name) {
return(rast(get_raster_path(name)))
}
pickRows <- function(d1, num_rows = DESIRED_ROWS) {
d1 <- data.table(d1)
# print(d1)
# print(nrow(d1))
# print(MAX_ROWS)
old_names <- colnames(d1)
while (nrow(d1) > num_rows) {
# print('loop')
# print(seq(1, nrow(d1), by=3))
# print(d1[seq(1, nrow(d1), by=3), ])
# print('assign')
d1 <- data.table(d1[seq(1, nrow(d1), by = 3), ])
# print('end loop')
# print(nrow(d1))
stopifnot(!is.null(nrow(d1)))
colnames(d1) <- old_names
}
# print('return')
return(d1)
}
makeInput <- function(arguments) {
# print(arguments)
d1 <- pickRows(arguments[[1]])
if (1 < length(arguments)) {
for (n in 2:length(arguments))
{
# print(n)
# print(arguments[[n]])
d2 <- pickRows(arguments[[n]], ceiling(3 * DESIRED_ROWS / nrow(d1)))
d1 <- pickRows(merge(data.frame(d1), data.frame(d2), by = NULL))
}
}
return(data.table(d1))
}
makeDataFromInput <- function(name, fct, input, split_args, with_input = FALSE) {
if (!split_args) {
stopifnot(is.data.table(input))
values <- fct(input)
input[, c(name)] <- values
return(input)
}
n0 <- nrow(input)
# input[, c(name)] <- do.call(fct, input)
r <- list(do.call(fct, input[1, ]))
isRow <- length(r[[1]]) > 1
if (isRow) {
r <- r[[1]]
for (n in 2:nrow(input)) {
r2 <- do.call(fct, input[n, ])
r <- rbind(r, r2)
}
stopifnot(nrow(input) == n0)
if (with_input) {
r <- cbind(input, r)
}
return(r)
} else {
for (n in 2:nrow(input)) {
r <- append(r, do.call(fct, input[n, ]))
}
input[, c(name)] <- unlist(r)
stopifnot(nrow(input) == n0)
return(input)
}
}
makeData <- function(name, fct, arguments, split_args, with_input = FALSE) {
return(makeDataFromInput(name, fct, makeInput(arguments), split_args, with_input))
}
# want to apply to each individual number
significant <- Vectorize(function(data) {
# keep at least 2 decimal places
return(signif(
data,
pmax(
ceiling(log10(abs(data))) + 2,
SIG_DIGS
)
))
})
roundData <- function(data) {
data <- as.data.table(data)
for (col in names(data)) {
# don't round integers
if (is.numeric(data[[col]]) && !is.integer(data[[col]])) {
data[[col]] <- significant(data[[col]])
}
}
return(data)
}
roundRaster <- function(data) {
return(signif(data, SIG_DIGS))
}
checkResults <- function(name, df1) {
df1 <- roundData(df1)
df2 <- as.data.table(read_data(name))
expect_equal(df1, df2)
}
checkData <- function(name, fct, arguments, split_args = TRUE, with_input = FALSE) {
checkResults(name, makeData(name, fct, arguments, split_args, with_input))
}
fctOnInput <- function(fct) {
return(function(ID, FUELTYPE, FFMC, BUI, WS, WD, FMC, GS, LAT, LONG, ELV, DJ, D0,
SD, SH, HR, PC, PDF, GFL, CC, THETA, ACCEL, ASPECT, BUIEFF,
CBH, CFL, ISI) {
input <- data.frame(
ID = ID,
FUELTYPE = FUELTYPE,
FFMC = FFMC,
BUI = BUI,
WS = WS,
WD = WD,
FMC = FMC,
GS = GS,
LAT = LAT,
LONG = LONG,
ELV = ELV,
DJ = DJ,
D0 = D0,
SD = SD,
SH = SH,
HR = HR,
PC = PC,
PDF = PDF,
GFL = GFL,
CC = CC,
THETA = THETA,
ACCEL = ACCEL,
ASPECT = ASPECT,
BUIEFF = BUIEFF,
CBH = CBH,
CFL = CFL,
ISI = ISI
)
return(fct(input = input, output = "S"))
})
}
test_raster <- function(name, input, fct) {
# only comparing to significant digits specified
actual <- roundRaster(fct(input))
expected <- read_raster(name)
out_cols <- setdiff(names(actual), toupper(names(input)))
# we don't actually know the names of the columns from the file, so assign from output
names(expected) <- names(actual)
expect_equal(names(expected), names(actual))
# # nc seems to prefer negative longitudes
# ext(actual) <- ext(expected)
m <- minmax(actual[[out_cols]] - expected[[out_cols]])
expect_true(all(abs(m) < (10^-SIG_DIGS)))
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.