Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c94077d
Add files via upload
blesson-07 Apr 5, 2025
6f09efe
Merge branch 'PecanProject:develop' into develop
blesson-07 May 10, 2025
6d1e32c
Merge branch 'PecanProject:develop' into develop
blesson-07 May 17, 2025
9519f47
Merge branch 'PecanProject:develop' into develop
blesson-07 May 29, 2025
e4d0284
Fix input sampling validation
Mar 27, 2025
7026682
Improve pkgdown build process and fix documentation generation
divine7022 Feb 24, 2025
6056493
Fixed the missing separator issue by replacing space indentation with…
divine7022 Mar 20, 2025
a3978f3
Removed the redundant document target from .PHONY, as it was listed t…
divine7022 Mar 20, 2025
385d398
Updated package documentation setup: modified .github/workflows/pkgdo…
divine7022 Mar 21, 2025
43483e2
changed according to the review
Apr 5, 2025
df75210
added test file
blesson-07 May 9, 2025
1ff2168
Delete wait
blesson-07 May 9, 2025
495614a
Added previous test file in the correct place
blesson-07 May 10, 2025
aebdcf3
Update dependencies and add the package detection codes.
Mar 20, 2025
38a17e0
changed the Indentation
blesson-07 May 10, 2025
7e460a7
added incomplete test file
blesson-07 May 11, 2025
159dd70
updated test
blesson-07 May 15, 2025
e4d6adc
Update modules/uncertainty/tests/testthat/test_ensemble.R
mdietze May 28, 2025
49dd66a
Update modules/data.remote/DESCRIPTION
mdietze May 29, 2025
124a884
Update docker/depends/pecan_package_dependencies.csv
mdietze May 29, 2025
d16fd19
updated pecan package dependencies
blesson-07 May 30, 2025
8b523a9
removed lib imports
blesson-07 May 30, 2025
6a73c75
Revert "Improve pkgdown build process and fix documentation generation"
blesson-07 May 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docker/depends/pecan_package_dependencies.csv
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@
"mockery","*","base/workflow","Suggests",FALSE
"mockery","*","modules/data.atmosphere","Suggests",FALSE
"mockery","*","modules/meta.analysis","Suggests",FALSE
"mockery","*","modules/uncertainty","Suggests",FALSE
"mockery",">= 0.3.0","models/biocro","Suggests",FALSE
"mockery",">= 0.4.3","base/db","Suggests",FALSE
"MODISTools",">= 1.1.0","modules/data.remote","Imports",FALSE
Expand Down
4 changes: 2 additions & 2 deletions models/sipnet/R/write.configs.SIPNET.R
Original file line number Diff line number Diff line change
Expand Up @@ -602,8 +602,8 @@ write.config.SIPNET <- function(defaults, trait.values, settings, run.id, inputs

else if (length(settings$run$inputs$poolinitcond$path)>0) {
ICs_num <- length(settings$run$inputs$poolinitcond$path)
IC.path <- settings$run$inputs$poolinitcond$path[[sample(1:ICs_num, 1)]]

IC.path <- settings$run$inputs$poolinitcond$path[[1]]
IC.pools <- PEcAn.data.land::prepare_pools(IC.path, constants = list(sla = SLA))

if(!is.null(IC.pools)){
Expand Down
1 change: 1 addition & 0 deletions modules/uncertainty/DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Imports:
rlang
Suggests:
testthat (>= 1.0.2),
mockery
License: BSD_3_clause + file LICENSE
Copyright: Authors
LazyLoad: yes
Expand Down
43 changes: 43 additions & 0 deletions modules/uncertainty/R/ensemble.R
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,29 @@ get.ensemble.samples <- function(ensemble.size, pft.samples, env.samples,
write.ensemble.configs <- function(defaults, ensemble.samples, settings, model,
clean = FALSE, write.to.db = TRUE, restart = NULL, samples = NULL, rename = FALSE) {


# Check if there are NO inputs

for (input_tag in names(settings$run$inputs)) {
input <- settings$run$inputs[[input_tag]]
input_paths <- input$path

# Check for required paths
if (is.null(input_paths) || length(input_paths) == 0) {
PEcAn.logger::logger.error("Input", sQuote(input_tag), "has no paths specified")
}

# Check for unsampled multi-path inputs
if (length(input_paths) > 1 &&
!(input_tag %in% names(settings$ensemble$samplingspace))) {
PEcAn.logger::logger.error(
"Input", sQuote(input_tag), "has", length(input_paths), "paths but no sampling method.",
"Add <samplingspace> for this input in pecan.xml")
}
}



con <- NULL
my.write.config <- paste("write.config.", model, sep = "")
my.write_restart <- paste0("write_restart.", model)
Expand Down Expand Up @@ -414,7 +437,26 @@ write.ensemble.configs <- function(defaults, ensemble.samples, settings, model,
"rundir : ", file.path(settings$host$rundir, run.id), "\n",
"outdir : ", file.path(settings$host$outdir, run.id), "\n",
file = file.path(settings$rundir, run.id, "README.txt"))



#changing the structure of input tag to what the models are expecting
for (input_i in seq_along(settings$run$inputs)) {
input_tag <- names(settings$run$inputs)[[input_i]]
input <- settings$run$inputs[[input_tag]]


if (!input_tag %in% names(samples)) {
# Use first path (already validated as single path)
settings$run$inputs[[input_tag]]$path <- input$path[1] }
else {
# Use sampled path
settings$run$inputs[[input_tag]]$path <- samples[[input_tag]][["samples"]][[i]]
}

}



do.call(my.write.config, args = list( defaults = defaults,
trait.values = lapply(samples$parameters$samples, function(x, n) { x[n, , drop=FALSE] }, n=i), # this is the params
Expand Down Expand Up @@ -540,3 +582,4 @@ input.ens.gen <- function(settings, input, method = "sampling", parent_ids = NUL

return(samples)
}

132 changes: 132 additions & 0 deletions modules/uncertainty/tests/testthat/test_ensemble.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
context("input validation for write.ensemble.configs")

# Mock a model write.configs function to avoid model-specific errors
write.configs.SIPNET <- function(...) TRUE

# Helper: make input with correct structure
make_input_sets <- function(paths) {
lapply(paths, function(p) list(path = p))
}

# Helper: make ensemble.samples with the correct structure
make_samples <- function(samples) {
lapply(paths, function(p) list(path = p))
}

# 1. One input, no samples → should pass
test_that("1 input, no samples: passes", {
settings <- list(run = list(inputs = list(input = list(path = "IC1"))))
ensemble.samples <- NULL
defaults <- list()

expect_silent(write.ensemble.configs(
defaults = defaults,
ensemble.samples = ensemble.samples,
settings = settings,
model = "SIPNET",
write.to.db = FALSE
))
})



test_that("no input error", {
settings <- list(run = list(inputs = list(input = NULL)))
ensemble.samples <- NULL
defaults <- list()

# Capture logger message
expect_silent(write.ensemble.configs(
defaults = defaults,
ensemble.samples = ensemble.samples,
settings = settings,
model = "SIPNET",
write.to.db = FALSE
))
})








test_that("multiple inputs and multiple samples", {
# Mock the SIPNET config writer
mockery::stub(write.ensemble.configs, "write.config.SIPNET", function(...) TRUE)

# Create temp directories
temp_rundir <- tempfile()
temp_modeloutdir <- tempfile()
dir.create(temp_rundir)
dir.create(temp_modeloutdir)
on.exit({
unlink(temp_rundir, recursive = TRUE)
unlink(temp_modeloutdir, recursive = TRUE)
}, add = TRUE)

# Complete settings
settings <- list(
run = list(
inputs = list(input = list(path = "IC1")),
site = list(id = 1, name = "Test Site"),
start.date = "2000-01-01",
end.date = "2000-12-31",
outdir = temp_modeloutdir
),
ensemble = list(size = 5),
database = NULL,
rundir = temp_rundir,
modeloutdir = temp_modeloutdir,
host = list(
rundir = temp_rundir,
outdir = temp_modeloutdir
),
model = list(id = "SIPNET", type = "SIPNET"),
pfts = list(
list(name = "temperate",
constants = list(1),
posteriorid = 1)
)
)

# Sample parameters
ensemble.samples <- list(
temperate = data.frame(
SLA = c(15.2, 16.8, 14.7, 18.1, 17.5),
Vm0 = c(45.0, 50.3, 47.8, 49.1, 51.0)
)
)

# Default PFT settings
defaults <- list(
list(
name = "temperate",
constants = list(1),
posteriorid = 1
)
)

# Run test - should create directories and configs
result <- expect_silent(
write.ensemble.configs(
defaults = defaults,
ensemble.samples = ensemble.samples,
settings = settings,
model = "SIPNET",
write.to.db = FALSE
)
)

# Verify outputs
expect_type(result, "list")
expect_named(result, c("runs", "ensemble.id", "samples"))
expect_equal(nrow(result$runs), settings$ensemble$size)
})






Loading