context("soil depth estimation") ## sample data d <- rbind( data.frame( id = c(1, 1, 1), top = c(0, 20, 35), bottom = c(20, 35, 110), name = c('A', 'Bt', 'C') ), data.frame( id = c(2, 2, 2), top = c(0, 20, 55), bottom = c(20, 55, 80), name = c('A', 'Bt', 'Cr') ), data.frame( id = c(3, 3, 3), top = c(0, 20, 48), bottom = c(20, 48, 130), name = c('A', 'Bt', 'Cd') ), data.frame( id = c(4, 4), top = c(0, 20), bottom = c(20, 180), name = c('A', 'R') )) depths(d) <- id ~ top + bottom hzdesgnname(d) <- "name" ## tests test_that("error conditions", { # function will only accept a single profile expect_error(estimateSoilDepth(d, name='name')) hzdesgnname(d) <- "" # not specified -> error expect_error(profileApply(d, estimateSoilDepth)) # not in horizonNames() -> error expect_error(profileApply(d, estimateSoilDepth, name='goo')) }) test_that("basic soil depth evaluation, based on pattern matching of hz designation", { # setting hz desgn by argument works res <- profileApply(d, estimateSoilDepth, name = 'name') expect_equivalent(res, c(110, 55, 48, 20)) # use hzdesgnname(x) hzdesgnname(d) <- "name" res <- estimateSoilDepth(d[1,]) expect_equivalent(res, 110) }) test_that("application of reasonable depth assumption of 150, given threshold of 100", { res <- profileApply(d, estimateSoilDepth, name = 'name', no.contact.depth=100, no.contact.assigned=150) expect_equivalent(res, c(150, 55, 48, 20)) }) test_that("depth to feature using REGEX on hzname: [Bt]", { # example from manual page, NA used when there is no 'Bt' found res <- profileApply(d, estimateSoilDepth, name = 'name', p = 'Bt', no.contact.depth=0, no.contact.assigned=NA) expect_equivalent(res, c(20, 20, 20, NA)) }) test_that("depthOf - simple match", { expect_equal(depthOf(d[1,], "Cr|R|Cd"), NA_real_) expect_equal(depthOf(d[2,], "Cr|R|Cd"), 55) expect_equal(minDepthOf(d[2,], "Cr|R|Cd"), 55) expect_equal(maxDepthOf(d[2,], "Cr|R|Cd"), 55) expect_equal(maxDepthOf(d[2,], "Cr|R|Cd", top = FALSE), 80) }) test_that("depthOf - multiple match", { expect_equal(depthOf(d[1,], "A|B|C"), c(0,20,35)) expect_equal(depthOf(d[1,], "A|B|C", top = FALSE), c(20,35,110)) expect_equal(minDepthOf(d[1,], "A|B|C"), 0) expect_equal(maxDepthOf(d[1,], "A|B|C"), 35) expect_equal(minDepthOf(d[1,], "A|B|C", top = FALSE), 20) expect_equal(maxDepthOf(d[1,], "A|B|C", top = FALSE), 110) }) test_that("depthOf - no match", { expect_equal(depthOf(d[1,], "X"), NA_real_) expect_equal(depthOf(d[2,], "Cr|R|Cd", no.contact.depth = 50), NA_real_) # multiple SPC return data.frame expect_true(inherits(depthOf(d, "X"), 'data.frame')) # one match -- other pedons no match d$name[1] <- "X" expect_equal(maxDepthOf(d, "X")$top, c(0, NA_real_, NA_real_, NA_real_)) # two matches, more than one NA depth d$name[2] <- "X" d$top[1:2] <- NA # first profile has two matches; all NA expect_equal(depthOf(d, "X")$top, c(NA_real_, NA_real_, NA_real_, NA_real_, NA_real_)) # using functional (1 value per profile) expect_equal(maxDepthOf(d, "X")$top, c(NA_real_, NA_real_, NA_real_, NA_real_)) d2 <- d d2$name <- NULL expect_error(depthOf(d2[1,], "A|B|C")) }) test_that("soil depth class assignment, using USDA-NRCS class breaks", { res <- getSoilDepthClass(d, name = 'name') # result should be a data.frame with as many rows as profiles in input expect_true(inherits(res, 'data.frame')) expect_equal(nrow(res), length(d)) # depths, should be the same as prior tests using estimateSoilDepth expect_equivalent(res$depth, c(110, 55, 48, 20)) # depth classes are returned as a factor sorted from shallow -> deep dc <- factor(c('deep', 'mod.deep', 'shallow', 'very.shallow'), levels=c('very.shallow', 'shallow', 'mod.deep', 'deep', 'very.deep')) expect_equivalent(res$depth.class, dc) }) test_that("data.table safety", { d <- rbind( data.frame( id = c(1, 1, 1), top = c(0, 20, 35), bottom = c(20, 35, 110), name = c('A', 'Bt', 'C') ), data.frame( id = c(2, 2, 2), top = c(0, 20, 55), bottom = c(20, 55, 80), name = c('A', 'Bt', 'Cr') ), data.frame( id = c(3, 3, 3), top = c(0, 20, 48), bottom = c(20, 48, 130), name = c('A', 'Bt', 'Cd') ), data.frame( id = c(4, 4), top = c(0, 20), bottom = c(20, 180), name = c('A', 'R') )) d <- data.table(d) depths(d) <- id ~ top + bottom res <- profileApply(d, estimateSoilDepth, name = 'name', no.contact.depth=100, no.contact.assigned=150) expect_equivalent(res, c(150, 55, 48, 20)) sdc <- getSoilDepthClass(d, name = 'name', no.contact.depth=100, no.contact.assigned=150) expect_equivalent(sdc$depth, c(150, 55, 48, 20)) }) test_that("really deep", { d <- rbind( data.frame( id = c(1, 1, 1), top = c(0, 20, 35), bottom = c(20, 35, 2000), name = c('A', 'Bt', 'C') )) depths(d) <- id ~ top + bottom res <- profileApply(d, estimateSoilDepth, name = 'name') expect_equivalent(res, 2000) sdc <- getSoilDepthClass(d, name = 'name') expect_equivalent(sdc$depth, 2000) expect_equivalent(as.character(sdc$depth.class), 'very.deep') })