-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RXR-1926 implement infusion duration scaling #92
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
9836b87
implement infusion duration scaling
roninsightrx 86f2413
rm lines not needed; add test
roninsightrx 449f4e6
add test for multi length scale
jasmineirx ccb7003
misc fixes
roninsightrx 3802a03
Merge branch 'RXR-1926-duration-scale' of github.com:InsightRX/PKPDsi…
roninsightrx 620815a
clean up
roninsightrx 262fc38
Merge branch 'master' into RXR-1926-duration-scale
roninsightrx 5069aca
add tests, plus to multiplication
jasmineirx 95a5cb0
fix test; clean up unrelated warnings in other test
roninsightrx e1cdc84
minor cleanup
jasmineirx 3623967
Merge branch 'RXR-1926-duration-scale' into RXR-1926-duration-scale-t…
jasmineirx b13ef0f
Merge pull request #94 from InsightRX/RXR-1926-duration-scale-tests
jasmineirx File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#' Apply infusion duration scale to a regimen | ||
#' | ||
#' E.g. see Centanni et al. Clin Pharmacokinet 2024. An estimated scaling factor | ||
#' for the length of the infusion was applied there in a model for vincristine. | ||
#' This is likely most relevant for very short infusions. | ||
#' | ||
#' Implementation is similar to handling of `lagtime`, i.e. the regimen that is the | ||
#' input for the simulation function is updated. | ||
#' | ||
#' @param regimen PKPDsim regimen | ||
#' @param duration_scale infusion length scale. | ||
#' @param parameters parameter list, required if the duration scale is | ||
#' specified as a parameter. | ||
#' @param cmt_mapping map of administration types to compartments, e.g. | ||
#' `list("oral" = 1, "infusion" = 2, "bolus" = 2)`. | ||
#' | ||
#' @export | ||
#' | ||
#' @return Original regimen with infusion lengths scaled by a factor | ||
#' | ||
apply_duration_scale <- function( | ||
regimen, | ||
duration_scale = NULL, | ||
parameters = NULL, | ||
cmt_mapping = NULL | ||
) { | ||
if(is.null(regimen$t_inf) || all(regimen$t_inf == 0)) { | ||
warning("`duration_scale` is only relevant for infusion regimens with an infusion length > 0.") | ||
return(regimen) | ||
} | ||
if(!is.null(duration_scale)) { | ||
if(class(duration_scale) %in% c("numeric", "integer")) { | ||
if(length(duration_scale) == 1) { | ||
regimen$t_inf <- regimen$t_inf * duration_scale | ||
} else { | ||
regimen$t_inf <- regimen$t_inf * duration_scale[regimen$cmt] | ||
} | ||
} else if(class(duration_scale) %in% c("character")) { | ||
if(is.null(regimen$cmt)) { | ||
if(!is.null(cmt_mapping)) { | ||
regimen$cmt <- as.numeric(cmt_mapping[regimen$type]) | ||
} else { | ||
regimen$cmt <- rep(1, length(regimen$dose_times)) | ||
} | ||
} | ||
if(length(duration_scale) == 1) { | ||
regimen$t_inf <- regimen$t_inf * parameters[[duration_scale]] | ||
} else { | ||
regimen$t_inf <- regimen$t_inf * as.numeric(unlist(parameters[duration_scale[regimen$cmt]])) | ||
} | ||
} | ||
} else { | ||
warning("Please specify `duration_scale` to apply to regimen.") | ||
} | ||
return(regimen) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
reg_oral <- new_regimen( | ||
amt = 1000, | ||
n = 12, | ||
interval = 12, | ||
type = "oral" | ||
) | ||
reg_iv <- new_regimen( | ||
amt = 1000, | ||
n = 12, | ||
interval = 12, | ||
type = "infusion", | ||
t_inf = 1, | ||
cmt = c(1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2) | ||
) | ||
|
||
reg_combo <- new_regimen( | ||
amt = 1000, | ||
n = 4, | ||
interval = 12, | ||
type = c("drug1", "drug2", "oral", "oral"), | ||
cmt = c(2, 3, 1, 1), | ||
t_inf = c(1, 1, 0, 0) | ||
) | ||
|
||
## null / error checks | ||
test_that("infusion length NULL warning", { | ||
expect_warning( | ||
dur0 <- apply_duration_scale( | ||
regimen = reg_oral | ||
) | ||
) | ||
expect_equal(dur0, reg_oral) | ||
}) | ||
test_that("duration scale NULL warning", { | ||
expect_warning( | ||
dur1 <- apply_duration_scale( | ||
regimen = reg_iv | ||
) | ||
) | ||
expect_equal(dur1, reg_iv) | ||
}) | ||
|
||
## Check functionality | ||
test_that("infusion length scaled", { | ||
dur2 <- apply_duration_scale( | ||
regimen = reg_iv, | ||
duration_scale = 1.5 | ||
) | ||
expect_equal(dur2$t_inf, rep(1.5, 12)) | ||
}) | ||
|
||
test_that("infusion length scaled using vector", { | ||
dur3 <- apply_duration_scale( | ||
regimen = reg_iv, | ||
duration_scale = c(1.5, 1.0) # scale oral "infusions", but not "iv" | ||
) | ||
expect_equal(dur3$t_inf, rep(c(1.5, 1.0), 6)) | ||
}) | ||
|
||
test_that("infusion length scaled using parameter", { | ||
dur4 <- apply_duration_scale( | ||
regimen = reg_iv, | ||
duration_scale = "SCALE", | ||
parameters = list(CL = 5, V = 50, SCALE = 1.6) | ||
) | ||
expect_equal(dur4$t_inf, rep(1.6, 12)) | ||
}) | ||
|
||
test_that("infusion length scaled, multiple cmts", { | ||
dur4 <- apply_duration_scale( | ||
regimen = reg_combo, | ||
duration_scale = c(1, 1.5, 2) | ||
) | ||
expect_equal(dur4$t_inf, c(1.5, 2, 0, 0)) | ||
}) | ||
|
||
test_that("infusion length scaled, multiple cmts, no cmt", { | ||
reg_combo$cmt <- NULL | ||
dur5 <- apply_duration_scale( | ||
regimen = reg_combo, | ||
duration_scale = "SCALE", | ||
parameters = list(CL = 5, V = 50, SCALE = 1.6), | ||
cmt_mapping = c("drug1" = 2, "drug2" = 3, "oral" = 1) | ||
) | ||
dur6 <- apply_duration_scale( | ||
regimen = reg_combo, | ||
duration_scale = c("SCALE1", "SCALE2", "SCALE3"), | ||
parameters = list(CL = 5, V = 50, SCALE1 = 1.6, SCALE2 = 1.7, SCALE3 = 1.8), | ||
cmt_mapping = c("drug1" = 2, "drug2" = 3, "oral" = 1) | ||
) | ||
expect_equal(dur5$t_inf, c(1.6, 1.6, 0, 0)) | ||
expect_equal(dur6$t_inf, c(1.7, 1.8, 0, 0)) | ||
}) | ||
|
||
test_that("infusion length scaled, no cmt, no cmt_mapping", { | ||
reg_combo$cmt <- NULL | ||
dur7 <- apply_duration_scale( | ||
regimen = reg_combo, | ||
duration_scale = c("SCALE1", "SCALE2", "SCALE3"), | ||
parameters = list(CL = 5, V = 50, SCALE1 = 1.6, SCALE2 = 1.7, SCALE3 = 1.8), | ||
cmt_mapping = NULL | ||
) | ||
expect_equal(dur7$t_inf, c(1.6, 1.6, 0, 0)) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it make more sense to use the
type
argument since i think that is how we tend to differentiate doses of different types (which go to different compartments)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I misread my earlier code. That 5 lines of code I removed is actually useful, at least when we're using a vector of duration scales that matches
cmt
s, which we do. The removed code ensures there is always acmt
in the regimen, even when not specified by the user. So will bring that code back. I think it is OK where it is, and doesn't need to go on top of the function, since we only want to make a modification to the regimen if its actually needed, IMO.Regarding your 2nd question whether we should link it to
type
rather thancmt
: I think it's less consistent to link it totype
: we now have "lagtime" also linked to a specificcmt
, not to an observation type. I see lagtime and duration scale as two very similar features. Also in NONMEM durations and infusion lengths are linked to compartments, so for most users more intuitive. An option for a future ticket could be thatlagtime
andduration_scale
could also be specified as a list, where they then indeed can be mapped to observation types.