Skip to content

fix: trying to fix loading results from the old pmetrics (not to be merged)#299

Open
Siel wants to merge 1 commit intomainfrom
fix/load-legacy-results
Open

fix: trying to fix loading results from the old pmetrics (not to be merged)#299
Siel wants to merge 1 commit intomainfrom
fix/load-legacy-results

Conversation

@Siel
Copy link
Copy Markdown
Member

@Siel Siel commented Mar 4, 2026

No description provided.

Copilot AI review requested due to automatic review settings March 4, 2026 11:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR attempts to restore compatibility when loading results produced by older Pmetrics output formats, by preserving raw NPAG/IT2B run data and adding upgrade logic during PM_result reconstruction.

Changes:

  • Added NPdata / ITdata fields to PM_result and populated them during initialization when present in loaded output.
  • Implemented upgrade paths in PM_result$initialize() for non-R6 (older) saved objects, including a rust-object fallback.
  • Made PM_load() load .Rdata into an isolated environment and modernized iteration with seq_along().

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread R/PM_result.R
Comment on lines 102 to +107
if (!inherits(out[[x]], "R6")) { # older save
cli::cli_abort(c("x" = "The object was saved in an older format. Please re-run the analysis."))
if (inherits(out[[x]], paste0("PM", x)) || inherits(out[[x]], "PMmatrix")) {
self[[x]] <- get(paste0("PM_", x))$new(out[[x]]) # ...make the R6 from old PMxxx
} else {
self[[x]] <- get(paste0("PM_", x))$new(out[[allData]]) # ...make the R6 from raw
}
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

allData is only set when out$NPdata, out$ITdata, or the rust-object fallback is detected, but it is later used unconditionally in the older-save branch (out[[allData]]). For files that don't include NPdata/ITdata (or when the rust fallback doesn’t trigger), this will error with “object 'allData' not found” and prevent loading. Initialize allData defensively and either avoid the out[[allData]] fallback when it’s unset or emit a clear cli_abort() explaining what format is required.

Copilot uses AI. Check for mistakes.
Comment thread R/PM_result.R
Comment on lines +103 to 109
if (inherits(out[[x]], paste0("PM", x)) || inherits(out[[x]], "PMmatrix")) {
self[[x]] <- get(paste0("PM_", x))$new(out[[x]]) # ...make the R6 from old PMxxx
} else {
self[[x]] <- get(paste0("PM_", x))$new(out[[allData]]) # ...make the R6 from raw
}
} else {
if(x == "model"){
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the non-R6/older-save branch, model is treated the same as other fields; if out$model is not an R6 and doesn’t inherit PMmodel, the code falls back to building PM_model from out[[allData]] (NPdata/ITdata). That input is unlikely to be a valid model spec and can create the wrong object or error; model should be special-cased so that older formats (e.g., character model file, list spec) are upgraded from out$model itself (with a clear error if it can’t be upgraded).

Suggested change
if (inherits(out[[x]], paste0("PM", x)) || inherits(out[[x]], "PMmatrix")) {
self[[x]] <- get(paste0("PM_", x))$new(out[[x]]) # ...make the R6 from old PMxxx
} else {
self[[x]] <- get(paste0("PM_", x))$new(out[[allData]]) # ...make the R6 from raw
}
} else {
if(x == "model"){
if (x == "model") {
# For legacy saves, upgrade the model from out$model itself.
tryCatch({
args <- list(x = out[[x]], compile = FALSE)
self[[x]] <- do.call(get(paste0("PM_", x))$new, args = args)
}, error = function(e) {
cli::cli_abort(c(
"!" = "Failed to upgrade legacy {.field model} object from saved results.",
"i" = "The saved 'model' field is not in a supported legacy format.",
"x" = conditionMessage(e)
))
})
} else if (inherits(out[[x]], paste0("PM", x)) || inherits(out[[x]], "PMmatrix")) {
self[[x]] <- get(paste0("PM_", x))$new(out[[x]]) # ...make the R6 from old PMxxx
} else {
self[[x]] <- get(paste0("PM_", x))$new(out[[allData]]) # ...make the R6 from raw
}
} else {
if (x == "model") {

Copilot uses AI. Check for mistakes.
Comment thread R/PM_result.R
Comment on lines +72 to +85
if (!is.null(out$NPdata)) {
self$NPdata <- out$NPdata
class(self$NPdata) <- c("NPAG", "list")
allData <- "NPdata"
} else {
self$NPdata <- NULL
}
if (!is.null(out$ITdata)) {
self$ITdata <- out$ITdata
class(self$ITdata) <- c("IT2B", "list")
allData <- "ITdata"
} else {
self$ITdata <- NULL
}
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If both out$NPdata and out$ITdata are present, allData will be overwritten by the second block and the upgrade path will use whichever one ran last. Since a run should be either NPAG or IT2B, consider detecting the “both present” case and failing fast (or selecting deterministically based on an explicit field) to avoid silently rebuilding objects from the wrong raw data.

Copilot uses AI. Check for mistakes.
Comment thread R/PM_result.R

env <- new.env()
obj_names <- load(found, envir = env)
result <- output2List(Out = get(obj_names, envir = env))
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

load() can return multiple object names from an .Rdata file; get(obj_names, envir = env) will error if obj_names has length > 1. Since this PR targets loading older Pmetrics outputs (which may plausibly save multiple objects), add handling for multiple loaded objects (e.g., select the expected one by name, or use mget() and validate) and emit a clear error message if the file format is unsupported.

Suggested change
result <- output2List(Out = get(obj_names, envir = env))
if (length(obj_names) == 0L) {
cli::cli_abort(c(
"x" = "The file {.path {found}} did not contain any objects.",
"i" = "This does not appear to be a valid Pmetrics output file."
))
}
if (length(obj_names) == 1L) {
Out <- get(obj_names, envir = env)
} else {
# Multiple objects were loaded; try to select the expected one
objs <- mget(obj_names, envir = env, inherits = FALSE)
if ("Out" %in% obj_names && is.list(objs[["Out"]])) {
Out <- objs[["Out"]]
} else {
cli::cli_abort(c(
"x" = "The file {.path {found}} contains multiple objects and the expected Pmetrics output object could not be identified.",
"i" = "Objects found: {.val {obj_names}}.",
"i" = "This file format is not supported by {.fn PM_load}."
))
}
}
result <- output2List(Out = Out)

Copilot uses AI. Check for mistakes.
@Siel Siel changed the title fix: trying to fix loading results from the old pmetrics fix: trying to fix loading results from the old pmetrics (not to be merged) Mar 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants