Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ For more information about this file see also [Keep a Changelog](http://keepacha
- Added note to DEV-INTRO.md documenting Traefik workaround for Apple Silicon (ARM64) Macs: use `traefik:v2.11` with `platform: linux/arm64` to fix 404 errors (#3910)
- Fixed `web/08-finished.php`: show database info instead of "Still running" when workflow folder doesn't exist locally (#3501).
- `PEcAn.utils::transformstats()`: corrected the LSD-to-SE conversion. The previous implementation included an extra `sqrt(n)` factor, causing SE estimates derived from LSD to appear `sqrt(n)` times smaller than they should be, non-conservatively over-weighting those observations in meta-analysis. (#3998)
- `segment_dataframe()` now returns an empty dataframe when date filtering removes all crop-cycle segments, instead of a single row with NA columns that caused downstream segment config errors (#4007).

### Changed
- `PEcAn.uncertainty::get.parameter.samples()`: replaced the `save_to_disk` flag (from #3860) with an `outdir` argument (default `settings$outdir`) controlling whether `samples.Rdata` is written; `outdir = NULL` skips the save. Existing callers are unaffected (@omkarrr2533, #4016)
Expand Down
1 change: 1 addition & 0 deletions models/sipnet/NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
Sipnet version `sipnet.unk`.
* Added trait to parameter mappings for 13 nitrogen cycle parameters in `write.config.SIPNET`,
including tissue C:N ratios, N volatilization/leaching, fixation, and methane rates.
* `segment_dataframe()` now returns an empty dataframe when date filtering removes all crop-cycle segments, instead of a single row with NA columns that caused downstream segment config errors (#4007).


# PEcAn.SIPNET 1.10.0
Expand Down
7 changes: 2 additions & 5 deletions models/sipnet/R/write_segmented_configs.R
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,8 @@ segment_dataframe <- function(run_settings) {
# Also clip the end date to avoid edge cases where run_start == end_date
.data$end_date > .env$run_start
)
if (nrow(segments) < 1) {
PEcAn.logger::logger.error(
"Filtering resulted in no segments. ",
"This is an invalid state; check settings and events.json."
)
if (nrow(segments) == 0) {
return(segments)
}
Comment thread
infotroph marked this conversation as resolved.
Outdated
segments[1, "start_date"] <- run_start
}
Expand Down
96 changes: 96 additions & 0 deletions models/sipnet/tests/testthat/test-write_segmented_configs.R
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,99 @@ test_that("write_segmented_configs", {
expect_match(jobsh, "bash .*segment_002/run/1/job.sh", all = FALSE)
expect_match(jobsh, "bash .*segment_003/run/1/job.sh", all = FALSE)
})

test_that("segment_dataframe returns empty when run start is after all crop cycles", {
pth <- withr::local_tempdir()
crp_chg_path <- file.path(pth, "cycles-a.csv")
c("date,crop_code", "2025-01-02,D12", "2025-01-05,G6") |>
writeLines(crp_chg_path)

run_settings <- PEcAn.settings::as.Settings(list(
run = list(
site = list(id = "a", site.pft = list(veg = "pft1")),
inputs = list(crop_changes = list(path = crp_chg_path)),
start.date = "2025-01-10",
end.date = "2025-01-20"
)
))

result <- PEcAn.SIPNET:::segment_dataframe(run_settings)

expect_equal(nrow(result), 0)
expect_gt(ncol(result), 0)
Comment thread
infotroph marked this conversation as resolved.
Outdated
})

test_that("write_segment_configs returns unaltered job.sh when no segments remain", {
pth <- withr::local_tempdir()

event_lines <- "2025 1 irrig 0 1"
event_src_path <- file.path(pth, "events-a.in")
met_path <- file.path(pth, "a.clim")
crp_chg_path <- file.path(pth, "cycles-a.csv")
run_path <- file.path(pth, "run", "ENS-00001-a")
dir.create(run_path, recursive = TRUE)

event_lines |>
writeLines(con = event_src_path)
c("date,crop_code", "2025-01-02,D12", "2025-01-05,G6") |>
writeLines(crp_chg_path)
c("run_id,site_id", "ENS-00001-a,a") |>
writeLines(file.path(pth, "runs_manifest.csv"))
data.frame(
year = 2025,
day = rep(1:31, each = 4),
hour = rep(c(0, 6, 12, 18), 31),
c4 = NA, c5 = NA, c6 = NA, c7 = NA, c8 = NA, c9 = NA, c10 = NA, c11 = NA,
c12 = NA
) |>
write.table(
file = met_path, quote = FALSE,
row.names = FALSE, col.names = FALSE
)
ens.samples <- list(
pft1 = data.frame(Amax = 1, SLA = 2),
soil = data.frame(Rd = 0)
)
save(ens.samples, file = file.path(pth, "ensemble.samples.testid.Rdata"))

s <- PEcAn.settings::as.Settings(
list(
outdir = file.path(pth),
rundir = file.path(pth, "run"),
modeloutdir = file.path(pth, "out"),
pfts = list(pft1 = list(), soil = list()),
ensemble = list(ensemble.id = "testid"),
model = list(binary = "", revision = "2.1.0"),
run = list(
site = list(id = "a", name = "site1", lat = 40, lon = -88,
site.pft = list(veg = "pft1", soil = "soil")),
inputs = list(
met = list(path = met_path),
events = list(path = event_src_path),
crop_changes = list(path = crp_chg_path)
),
start.date = "2025-01-10",
end.date = "2025-01-20"
),
host = list(
name = "localhost",
outdir = file.path(pth),
rundir = file.path(pth, "run")
)
)
)

write.config.SIPNET(
defaults = s$pfts,
trait.values = ens.samples["pft1"],
IC = list(soil = 3.14),
settings = s,
run.id = "ENS-00001-a"
)

seg_res <- write_segmented_configs.SIPNET(settings = s)

expect_equal(seg_res, file.path(run_path, "job.sh"))
expect_false(file.exists(file.path(run_path, "job_segmented.sh")))
expect_false(dir.exists(file.path(run_path, "segments")))
})
Loading