Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
12 changes: 6 additions & 6 deletions models/sipnet/R/write_segmented_configs.R
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,12 @@ 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) {
PEcAn.logger::logger.info(
"no crop cycle segments fall within the run window; running unsegmented"
)
return(segments)
}
segments[1, "start_date"] <- run_start
}

Expand Down
99 changes: 99 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,102 @@ 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_named(
result,
c("start_date", "crop_code", "end_date")
)
})

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