Skip to content

Commit ba0e61a

Browse files
authored
Merge pull request #8 from blasif/main
a
2 parents 61d1e2f + 7422928 commit ba0e61a

3 files changed

Lines changed: 134 additions & 11 deletions

File tree

‎R/getFunctions.R‎

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,13 @@ getCovMatrix <- function(coco.object, type = "global", index = NULL){
3838

3939
par.pos <- getDesignMatrix(coco.object@model.list, data = coco.object@data)$par.pos
4040

41+
theta_list <- cocons::getModelLists(coco.object@output$par,par.pos = par.pos,
42+
type = "diff")
43+
4144
if(coco.object@type == "dense"){
4245

4346
if(type == "global"){
44-
theta_list <- cocons::getModelLists(coco.object@output$par,par.pos = par.pos,
45-
type = "diff")
46-
47+
4748
return(cocons::cov_rns(theta = theta_list,
4849
locs = coco.object@locs,
4950
x_covariates = x_covs,
@@ -59,10 +60,7 @@ getCovMatrix <- function(coco.object, type = "global", index = NULL){
5960
if(coco.object@type == "sparse"){
6061

6162
if(type == "global"){
62-
63-
theta_list <- cocons::getModelLists(coco.object@output$par,par.pos = par.pos,
64-
type = "diff")
65-
63+
6664
# taper
6765
ref_taper <- coco.object@info$taper(
6866
spam::nearest.dist(coco.object@locs, delta = coco.object@info$delta, upper = NULL),
@@ -143,7 +141,7 @@ getDensityFromDelta <- function(coco.object, delta){
143141

144142
coco.object@info$delta <- delta
145143

146-
return(summary(getCovMatrix(coco.object))$density)
144+
return(summary(getCovMatrix(coco.object))$density / 100)
147145

148146
}
149147

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ For a brief introduction:
2323

2424
or you can check the vignette directly [here](https://github.com/blasif/cocons/blob/main/inst/doc/cocons.pdf).
2525

26-
For a description of the class of modular covariate-based covariance functions implemented in this package, please check the following [article](https://arxiv.org/abs/2410.16716#).
26+
**UPDATE!** Our article has been published in Environmetrics! Learn more about the type of modular and flexible Gaussian Process models you can fit here [article](https://doi.org/10.1002/env.70038)
2727

2828
**Bugs and/or errors?:** feel free to add new issues on [https://github.com/blasif/cocons/issues](https://github.com/blasif/cocons/issues).

‎tests/coco_test.R‎

Lines changed: 127 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
# tests/coco_test.R
22

3-
# Load your package
4-
library(cocons)
3+
## --- Load package ----------------------------------------------------------
4+
5+
suppressPackageStartupMessages({
6+
library(cocons)
7+
})
8+
9+
## Optional: check version at least 0.1.5
10+
if (packageVersion("cocons") < "0.1.5") {
11+
stop("cocons >= 0.1.5 required for these checks.", call. = FALSE)
12+
}
13+
14+
## --------
515

616
data_test <- cocons::holes$training[1:50,]
717

@@ -190,3 +200,118 @@ stopifnot(all(eigen(cmat)$values > 0))
190200

191201
predss <- cocoPredict(test_optim, newdataset = cocons::holes$test[1:200,1:4],newlocs = as.matrix(holes$test[1:200,1:2]))
192202
stopifnot(all(!is.na(predss$stochastic)))
203+
204+
aeq <- function(a, b, tol = 1e-8) {
205+
if (!isTRUE(all.equal(a, b, tolerance = tol))) {
206+
stop(sprintf("Numeric mismatch:\nexpected: %s\ngot: %s",
207+
paste0(head(b,10), collapse=", "),
208+
paste0(head(a,10), collapse=", ")),
209+
call. = FALSE)
210+
}
211+
invisible(TRUE)
212+
}
213+
214+
expect_error <- function(expr, pattern = NULL) {
215+
err <- NULL
216+
tryCatch(eval.parent(substitute(expr)), error = function(e) err <<- e)
217+
if (is.null(err)) stop("Expected an error, but none was thrown.", call. = FALSE)
218+
if (!is.null(pattern) && !grepl(pattern, conditionMessage(err))) {
219+
stop(sprintf("Error did not match /%s/; got: %s",
220+
pattern, conditionMessage(err)), call. = FALSE)
221+
}
222+
invisible(TRUE)
223+
}
224+
225+
set.seed(1)
226+
locs <- expand.grid(seq(0, 1, length.out = 5),
227+
seq(0, 1, length.out = 5))
228+
toydata <- data.frame(x = locs[, 1])
229+
z <- rnorm(nrow(locs))
230+
231+
model.list <- list(
232+
mean = 0,
233+
std.dev = formula(~ 1),
234+
scale = formula(~ 1 + x),
235+
aniso = 0,
236+
tilt = 0,
237+
smooth = 3/2,
238+
nugget = -Inf
239+
)
240+
241+
coco_dense <- coco(
242+
type = "dense",
243+
data = toydata,
244+
locs = as.matrix(locs),
245+
z = z,
246+
model.list = model.list
247+
)
248+
249+
## S4 class + slots
250+
stopifnot(isS4(coco_dense))
251+
stopifnot(methods::is(coco_dense, "coco"))
252+
needed_slots <- c("type","data","locs","z","model.list","info","output")
253+
stopifnot(all(needed_slots %in% slotNames(coco_dense)))
254+
stopifnot(identical(coco_dense@type, "dense"))
255+
stopifnot(nrow(coco_dense@locs) == nrow(toydata))
256+
stopifnot(nrow(coco_dense@locs) == length(z))
257+
258+
## --- 2) invalid 'type' should error ---------------------------------------
259+
260+
expect_error(
261+
coco(type = "weird",
262+
data = toydata,
263+
locs = as.matrix(locs),
264+
z = z,
265+
model.list = model.list),
266+
pattern = "type|dense|sparse"
267+
)
268+
269+
## --- 3) is.formula() helper ------------------------------------------------
270+
271+
stopifnot(isTRUE( cocons::is.formula(~ 1) ))
272+
stopifnot(isTRUE(!cocons::is.formula(1)))
273+
stopifnot(isTRUE(!cocons::is.formula("~ 1 + x")))
274+
275+
## --- 4) Scoring rules: getLogScore / getCRPS -------------------------------
276+
277+
z.pred <- c(0.0, 1.0, -0.5)
278+
mean.pred <- c(0.1, 0.8, -0.4)
279+
sd.pred <- c(0.5, 1.2, 2.0)
280+
281+
## reference formulas (match package code)
282+
logscore_ref <- (log(2*pi) + ((z.pred - mean.pred)/sd.pred)^2)/2 + log(sd.pred)
283+
v <- (mean.pred - z.pred)/sd.pred
284+
crps_ref <- sd.pred * ( v * (2 * stats::pnorm(v) - 1) +
285+
2 * stats::dnorm(v) - 1 / sqrt(pi) )
286+
287+
aeq(cocons::getLogScore(z.pred, mean.pred, sd.pred), logscore_ref, tol = 1e-10)
288+
aeq(cocons::getCRPS(z.pred, mean.pred, sd.pred), crps_ref, tol = 1e-8)
289+
290+
## --- 5) getDensityFromDelta() behavior ------------------------------------
291+
292+
## Dense objects should error
293+
expect_error(cocons::getDensityFromDelta(coco_dense, delta = 0.2),
294+
pattern = "only for sparse coco objects")
295+
296+
## Optional: sparse path (skipped if 'spam' not available)
297+
if (requireNamespace("spam", quietly = TRUE)) {
298+
coco_sparse <- coco(
299+
type = "sparse",
300+
data = toydata,
301+
locs = as.matrix(locs),
302+
z = z,
303+
model.list = model.list,
304+
info = list(
305+
taper = spam::cov.wend1,
306+
delta = 0.15,
307+
smooth.limits = c(0.5, 2.5)
308+
)
309+
)
310+
311+
dens <- cocons::getDensityFromDelta(coco_sparse, delta = 0.20)
312+
stopifnot(is.numeric(dens), length(dens) == 1L, is.finite(dens))
313+
## For a 25x25 grid with short taper, density should be in (0, 1)
314+
stopifnot(dens > 0, dens < 1)
315+
} else {
316+
message("Skipping sparse/taper density check (package 'spam' not available).")
317+
}

0 commit comments

Comments
 (0)