├── .github ├── .gitignore └── workflows │ └── R-CMD-check.yaml ├── vignettes ├── .gitignore └── articles │ ├── multiple_endpoints.Rmd │ ├── patient_data.Rmd │ ├── route_of_administration.Rmd │ ├── a_posteriori_dosing.Rmd │ ├── a_priori_dosing.Rmd │ └── auc_based_dosing.Rmd ├── docs ├── logo.png ├── favicon.ico ├── favicon-16x16.png ├── favicon-32x32.png ├── apple-touch-icon.png ├── reference │ ├── Rplot001.png │ ├── figures │ │ ├── logo.png │ │ ├── logo_120.png │ │ └── README-map_plot-1.png │ ├── posologyr_error_lines.t.html │ ├── posologyr_error_lines.default.html │ ├── posologyr_error_lines.norm.html │ └── posologyr_error_lines.rxUi.html ├── apple-touch-icon-120x120.png ├── apple-touch-icon-152x152.png ├── apple-touch-icon-180x180.png ├── apple-touch-icon-60x60.png ├── apple-touch-icon-76x76.png ├── deps │ ├── font-awesome-6.4.2 │ │ └── webfonts │ │ │ ├── fa-brands-400.ttf │ │ │ ├── fa-solid-900.ttf │ │ │ ├── fa-brands-400.woff2 │ │ │ ├── fa-regular-400.ttf │ │ │ ├── fa-regular-400.woff2 │ │ │ ├── fa-solid-900.woff2 │ │ │ ├── fa-v4compatibility.ttf │ │ │ └── fa-v4compatibility.woff2 │ ├── font-awesome-6.5.2 │ │ └── webfonts │ │ │ ├── fa-brands-400.ttf │ │ │ ├── fa-solid-900.ttf │ │ │ ├── fa-brands-400.woff2 │ │ │ ├── fa-regular-400.ttf │ │ │ ├── fa-regular-400.woff2 │ │ │ ├── fa-solid-900.woff2 │ │ │ ├── fa-v4compatibility.ttf │ │ │ └── fa-v4compatibility.woff2 │ ├── headroom-0.11.0 │ │ ├── jQuery.headroom.min.js │ │ └── headroom.min.js │ ├── data-deps.txt │ └── bootstrap-toc-1.0.1 │ │ └── bootstrap-toc.min.js ├── articles │ ├── a_priori_dosing_files │ │ ├── figure-html │ │ │ ├── prior_plot-1.png │ │ │ └── unnamed-chunk-3-1.png │ │ └── accessible-code-block-0.0.1 │ │ │ └── empty-anchor.js │ ├── auc_based_dosing_files │ │ ├── figure-html │ │ │ ├── map_plot_tdm-1.png │ │ │ └── unnamed-chunk-2-1.png │ │ └── accessible-code-block-0.0.1 │ │ │ └── empty-anchor.js │ ├── a_posteriori_dosing_files │ │ ├── figure-html │ │ │ └── map_plot_tdm-1.png │ │ └── accessible-code-block-0.0.1 │ │ │ └── empty-anchor.js │ ├── route_of_administration_files │ │ ├── figure-html │ │ │ └── plot_map-1.png │ │ └── accessible-code-block-0.0.1 │ │ │ └── empty-anchor.js │ ├── multiple_endpoints_files │ │ ├── figure-html │ │ │ ├── unnamed-chunk-5-1.png │ │ │ └── unnamed-chunk-6-1.png │ │ └── accessible-code-block-0.0.1 │ │ │ └── empty-anchor.js │ ├── articles │ │ ├── patient_data.html │ │ ├── a_priori_dosing.html │ │ ├── auc_based_dosing.html │ │ ├── population_models.html │ │ ├── multiple_endpoints.html │ │ ├── a_posteriori_dosing.html │ │ ├── route_of_administration.html │ │ └── classic_posologyr_models.html │ ├── patient_data_files │ │ └── accessible-code-block-0.0.1 │ │ │ └── empty-anchor.js │ ├── population_models_files │ │ └── accessible-code-block-0.0.1 │ │ │ └── empty-anchor.js │ ├── classic_posologyr_models_files │ │ └── accessible-code-block-0.0.1 │ │ │ └── empty-anchor.js │ └── index.html ├── katex-auto.js ├── pkgdown.yml ├── link.svg ├── bootstrap-toc.css ├── docsearch.js ├── sitemap.xml ├── lightswitch.js ├── pkgdown.js ├── bootstrap-toc.js └── 404.html ├── man ├── figures │ ├── logo.png │ ├── logo_120.png │ └── README-map_plot-1.png ├── posologyr_error_lines.Rd ├── poso_simu_pop.Rd ├── poso_replace_et.Rd ├── poso_estim_map.Rd ├── poso_estim_sir.Rd ├── poso_estim_mcmc.Rd ├── poso_inter_cmin.Rd ├── poso_dose_conc.Rd ├── poso_dose_auc.Rd └── poso_time_cmin.Rd ├── pkgdown └── favicon │ ├── favicon.ico │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── apple-touch-icon.png │ ├── apple-touch-icon-60x60.png │ ├── apple-touch-icon-76x76.png │ ├── apple-touch-icon-120x120.png │ ├── apple-touch-icon-152x152.png │ └── apple-touch-icon-180x180.png ├── tests ├── testthat.R └── testthat │ ├── test_issue_52.R │ ├── test_issue_29.R │ ├── test_issue_28.R │ ├── test_issue_30.R │ ├── test_map_nlmixr.R │ ├── test_issue_10.R │ ├── test_map_nm.R │ ├── test_issue_32.R │ ├── test_map_iov.R │ ├── test_map_mlx.R │ ├── test_multi_outputs.R │ └── test_doseoptim_cmt.R ├── .Rbuildignore ├── R ├── zzz.R ├── iov.R ├── input_validation.R ├── ofv.R ├── posologyr.R └── et.R ├── inst └── CITATION ├── NAMESPACE ├── DESCRIPTION ├── _pkgdown.yml ├── README.Rmd └── README.md /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | -------------------------------------------------------------------------------- /docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/logo.png -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/favicon.ico -------------------------------------------------------------------------------- /man/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/man/figures/logo.png -------------------------------------------------------------------------------- /docs/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/favicon-16x16.png -------------------------------------------------------------------------------- /docs/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/favicon-32x32.png -------------------------------------------------------------------------------- /docs/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/apple-touch-icon.png -------------------------------------------------------------------------------- /man/figures/logo_120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/man/figures/logo_120.png -------------------------------------------------------------------------------- /docs/reference/Rplot001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/reference/Rplot001.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/pkgdown/favicon/favicon.ico -------------------------------------------------------------------------------- /docs/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /docs/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /docs/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /docs/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /docs/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /docs/reference/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/reference/figures/logo.png -------------------------------------------------------------------------------- /man/figures/README-map_plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/man/figures/README-map_plot-1.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/pkgdown/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/pkgdown/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /docs/reference/figures/logo_120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/reference/figures/logo_120.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/pkgdown/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/pkgdown/favicon/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/pkgdown/favicon/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /docs/reference/figures/README-map_plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/reference/figures/README-map_plot-1.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/pkgdown/favicon/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/pkgdown/favicon/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/pkgdown/favicon/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /docs/deps/font-awesome-6.4.2/webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/deps/font-awesome-6.4.2/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /docs/deps/font-awesome-6.4.2/webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/deps/font-awesome-6.4.2/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /docs/deps/font-awesome-6.5.2/webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/deps/font-awesome-6.5.2/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /docs/deps/font-awesome-6.5.2/webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/deps/font-awesome-6.5.2/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /docs/deps/font-awesome-6.4.2/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/deps/font-awesome-6.4.2/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /docs/deps/font-awesome-6.4.2/webfonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/deps/font-awesome-6.4.2/webfonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /docs/deps/font-awesome-6.4.2/webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/deps/font-awesome-6.4.2/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /docs/deps/font-awesome-6.4.2/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/deps/font-awesome-6.4.2/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /docs/deps/font-awesome-6.5.2/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/deps/font-awesome-6.5.2/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /docs/deps/font-awesome-6.5.2/webfonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/deps/font-awesome-6.5.2/webfonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /docs/deps/font-awesome-6.5.2/webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/deps/font-awesome-6.5.2/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /docs/deps/font-awesome-6.5.2/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/deps/font-awesome-6.5.2/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /docs/deps/font-awesome-6.4.2/webfonts/fa-v4compatibility.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/deps/font-awesome-6.4.2/webfonts/fa-v4compatibility.ttf -------------------------------------------------------------------------------- /docs/deps/font-awesome-6.5.2/webfonts/fa-v4compatibility.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/deps/font-awesome-6.5.2/webfonts/fa-v4compatibility.ttf -------------------------------------------------------------------------------- /docs/deps/font-awesome-6.4.2/webfonts/fa-v4compatibility.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/deps/font-awesome-6.4.2/webfonts/fa-v4compatibility.woff2 -------------------------------------------------------------------------------- /docs/deps/font-awesome-6.5.2/webfonts/fa-v4compatibility.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/deps/font-awesome-6.5.2/webfonts/fa-v4compatibility.woff2 -------------------------------------------------------------------------------- /docs/articles/a_priori_dosing_files/figure-html/prior_plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/articles/a_priori_dosing_files/figure-html/prior_plot-1.png -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(rxode2) 2 | library(posologyr) 3 | library(testthat) 4 | setRxThreads(2L) #for CRAN, following the advice of mattfidler 5 | 6 | test_check("posologyr") 7 | -------------------------------------------------------------------------------- /docs/articles/auc_based_dosing_files/figure-html/map_plot_tdm-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/articles/auc_based_dosing_files/figure-html/map_plot_tdm-1.png -------------------------------------------------------------------------------- /docs/articles/a_posteriori_dosing_files/figure-html/map_plot_tdm-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/articles/a_posteriori_dosing_files/figure-html/map_plot_tdm-1.png -------------------------------------------------------------------------------- /docs/articles/a_priori_dosing_files/figure-html/unnamed-chunk-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/articles/a_priori_dosing_files/figure-html/unnamed-chunk-3-1.png -------------------------------------------------------------------------------- /docs/articles/auc_based_dosing_files/figure-html/unnamed-chunk-2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/articles/auc_based_dosing_files/figure-html/unnamed-chunk-2-1.png -------------------------------------------------------------------------------- /docs/articles/route_of_administration_files/figure-html/plot_map-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/articles/route_of_administration_files/figure-html/plot_map-1.png -------------------------------------------------------------------------------- /docs/articles/multiple_endpoints_files/figure-html/unnamed-chunk-5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/articles/multiple_endpoints_files/figure-html/unnamed-chunk-5-1.png -------------------------------------------------------------------------------- /docs/articles/multiple_endpoints_files/figure-html/unnamed-chunk-6-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levenc/posologyr/HEAD/docs/articles/multiple_endpoints_files/figure-html/unnamed-chunk-6-1.png -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^posologyr\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^LICENSE\.md$ 4 | ^README\.Rmd$ 5 | ^data-raw$ 6 | ^_pkgdown\.yml$ 7 | ^docs$ 8 | ^pkgdown$ 9 | ^doc$ 10 | ^Meta$ 11 | ^\.github$ 12 | ^CRAN-SUBMISSION$ 13 | ^cran-comments\.md$ 14 | ^vignettes/articles$ 15 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | .onLoad <- function(libname, pkgname) { 2 | rxode2::.s3register("rxode2::rxUiGet", "posologyr") 3 | rxode2::.s3register("rxode2::rxUiGet", "posologyr_ppk_model") 4 | rxode2::.s3register("rxode2::rxUiGet", "posologyr_error_model") 5 | rxode2::.s3register("rxode2::rxUiGet", "posologyr_sigma") 6 | } 7 | -------------------------------------------------------------------------------- /docs/articles/articles/patient_data.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/articles/articles/a_priori_dosing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/articles/articles/auc_based_dosing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/articles/articles/population_models.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/articles/articles/multiple_endpoints.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/articles/articles/a_posteriori_dosing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/reference/posologyr_error_lines.t.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/reference/posologyr_error_lines.default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/reference/posologyr_error_lines.norm.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/reference/posologyr_error_lines.rxUi.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/articles/articles/route_of_administration.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/articles/articles/classic_posologyr_models.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | bibentry( 2 | key = "posologyrpaper", 3 | bibtype = "Article", 4 | title = "Free and Open-Source Posologyr Software for Bayesian Dose Individualization: An Extensive Validation on Simulated Data", 5 | author = "Cyril Leven, Anne Coste and Camille Mané", 6 | journal="Pharmaceutics", 7 | year = "2022", 8 | volume = "14", 9 | pages = "442", 10 | number = "2", 11 | doi = "10.3390/pharmaceutics14020442", 12 | publisher = "MDPI", 13 | url="https://europepmc.org/article/pmc/8879752" 14 | ) 15 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(posologyr_error_lines,default) 4 | S3method(posologyr_error_lines,norm) 5 | S3method(posologyr_error_lines,rxUi) 6 | S3method(posologyr_error_lines,t) 7 | export(poso_dose_auc) 8 | export(poso_dose_conc) 9 | export(poso_estim_map) 10 | export(poso_estim_mcmc) 11 | export(poso_estim_sir) 12 | export(poso_inter_cmin) 13 | export(poso_replace_et) 14 | export(poso_simu_pop) 15 | export(poso_time_cmin) 16 | export(posologyr_error_lines) 17 | import(data.table) 18 | importFrom(stats,setNames) 19 | -------------------------------------------------------------------------------- /docs/deps/headroom-0.11.0/jQuery.headroom.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * headroom.js v0.9.4 - Give your page some headroom. Hide your header until you need it 3 | * Copyright (c) 2017 Nick Williams - http://wicky.nillia.ms/headroom.js 4 | * License: MIT 5 | */ 6 | 7 | !function(a){a&&(a.fn.headroom=function(b){return this.each(function(){var c=a(this),d=c.data("headroom"),e="object"==typeof b&&b;e=a.extend(!0,{},Headroom.options,e),d||(d=new Headroom(this,e),d.init(),c.data("headroom",d)),"string"==typeof b&&(d[b](),"destroy"===b&&c.removeData("headroom"))})},a("[data-headroom]").each(function(){var b=a(this);b.headroom(b.data())}))}(window.Zepto||window.jQuery); -------------------------------------------------------------------------------- /docs/katex-auto.js: -------------------------------------------------------------------------------- 1 | // https://github.com/jgm/pandoc/blob/29fa97ab96b8e2d62d48326e1b949a71dc41f47a/src/Text/Pandoc/Writers/HTML.hs#L332-L345 2 | document.addEventListener("DOMContentLoaded", function () { 3 | var mathElements = document.getElementsByClassName("math"); 4 | var macros = []; 5 | for (var i = 0; i < mathElements.length; i++) { 6 | var texText = mathElements[i].firstChild; 7 | if (mathElements[i].tagName == "SPAN") { 8 | katex.render(texText.data, mathElements[i], { 9 | displayMode: mathElements[i].classList.contains("display"), 10 | throwOnError: false, 11 | macros: macros, 12 | fleqn: false 13 | }); 14 | }}}); 15 | -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: 3.1.11.1 2 | pkgdown: 2.1.1 3 | pkgdown_sha: ~ 4 | articles: 5 | articles/a_posteriori_dosing: a_posteriori_dosing.html 6 | articles/a_priori_dosing: a_priori_dosing.html 7 | articles/auc_based_dosing: auc_based_dosing.html 8 | articles/classic_posologyr_models: classic_posologyr_models.html 9 | articles/multiple_endpoints: multiple_endpoints.html 10 | articles/patient_data: patient_data.html 11 | articles/population_models: population_models.html 12 | articles/route_of_administration: route_of_administration.html 13 | last_built: 2025-03-10T16:07Z 14 | urls: 15 | reference: https://levenc.github.io/posologyr/reference 16 | article: https://levenc.github.io/posologyr/articles 17 | -------------------------------------------------------------------------------- /docs/articles/a_priori_dosing_files/accessible-code-block-0.0.1/empty-anchor.js: -------------------------------------------------------------------------------- 1 | // Hide empty tag within highlighted CodeBlock for screen reader accessibility (see https://github.com/jgm/pandoc/issues/6352#issuecomment-626106786) --> 2 | // v0.0.1 3 | // Written by JooYoung Seo (jooyoung@psu.edu) and Atsushi Yasumoto on June 1st, 2020. 4 | 5 | document.addEventListener('DOMContentLoaded', function() { 6 | const codeList = document.getElementsByClassName("sourceCode"); 7 | for (var i = 0; i < codeList.length; i++) { 8 | var linkList = codeList[i].getElementsByTagName('a'); 9 | for (var j = 0; j < linkList.length; j++) { 10 | if (linkList[j].innerHTML === "") { 11 | linkList[j].setAttribute('aria-hidden', 'true'); 12 | } 13 | } 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /docs/articles/patient_data_files/accessible-code-block-0.0.1/empty-anchor.js: -------------------------------------------------------------------------------- 1 | // Hide empty tag within highlighted CodeBlock for screen reader accessibility (see https://github.com/jgm/pandoc/issues/6352#issuecomment-626106786) --> 2 | // v0.0.1 3 | // Written by JooYoung Seo (jooyoung@psu.edu) and Atsushi Yasumoto on June 1st, 2020. 4 | 5 | document.addEventListener('DOMContentLoaded', function() { 6 | const codeList = document.getElementsByClassName("sourceCode"); 7 | for (var i = 0; i < codeList.length; i++) { 8 | var linkList = codeList[i].getElementsByTagName('a'); 9 | for (var j = 0; j < linkList.length; j++) { 10 | if (linkList[j].innerHTML === "") { 11 | linkList[j].setAttribute('aria-hidden', 'true'); 12 | } 13 | } 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /docs/articles/a_posteriori_dosing_files/accessible-code-block-0.0.1/empty-anchor.js: -------------------------------------------------------------------------------- 1 | // Hide empty tag within highlighted CodeBlock for screen reader accessibility (see https://github.com/jgm/pandoc/issues/6352#issuecomment-626106786) --> 2 | // v0.0.1 3 | // Written by JooYoung Seo (jooyoung@psu.edu) and Atsushi Yasumoto on June 1st, 2020. 4 | 5 | document.addEventListener('DOMContentLoaded', function() { 6 | const codeList = document.getElementsByClassName("sourceCode"); 7 | for (var i = 0; i < codeList.length; i++) { 8 | var linkList = codeList[i].getElementsByTagName('a'); 9 | for (var j = 0; j < linkList.length; j++) { 10 | if (linkList[j].innerHTML === "") { 11 | linkList[j].setAttribute('aria-hidden', 'true'); 12 | } 13 | } 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /docs/articles/auc_based_dosing_files/accessible-code-block-0.0.1/empty-anchor.js: -------------------------------------------------------------------------------- 1 | // Hide empty tag within highlighted CodeBlock for screen reader accessibility (see https://github.com/jgm/pandoc/issues/6352#issuecomment-626106786) --> 2 | // v0.0.1 3 | // Written by JooYoung Seo (jooyoung@psu.edu) and Atsushi Yasumoto on June 1st, 2020. 4 | 5 | document.addEventListener('DOMContentLoaded', function() { 6 | const codeList = document.getElementsByClassName("sourceCode"); 7 | for (var i = 0; i < codeList.length; i++) { 8 | var linkList = codeList[i].getElementsByTagName('a'); 9 | for (var j = 0; j < linkList.length; j++) { 10 | if (linkList[j].innerHTML === "") { 11 | linkList[j].setAttribute('aria-hidden', 'true'); 12 | } 13 | } 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /docs/articles/multiple_endpoints_files/accessible-code-block-0.0.1/empty-anchor.js: -------------------------------------------------------------------------------- 1 | // Hide empty tag within highlighted CodeBlock for screen reader accessibility (see https://github.com/jgm/pandoc/issues/6352#issuecomment-626106786) --> 2 | // v0.0.1 3 | // Written by JooYoung Seo (jooyoung@psu.edu) and Atsushi Yasumoto on June 1st, 2020. 4 | 5 | document.addEventListener('DOMContentLoaded', function() { 6 | const codeList = document.getElementsByClassName("sourceCode"); 7 | for (var i = 0; i < codeList.length; i++) { 8 | var linkList = codeList[i].getElementsByTagName('a'); 9 | for (var j = 0; j < linkList.length; j++) { 10 | if (linkList[j].innerHTML === "") { 11 | linkList[j].setAttribute('aria-hidden', 'true'); 12 | } 13 | } 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /docs/articles/population_models_files/accessible-code-block-0.0.1/empty-anchor.js: -------------------------------------------------------------------------------- 1 | // Hide empty tag within highlighted CodeBlock for screen reader accessibility (see https://github.com/jgm/pandoc/issues/6352#issuecomment-626106786) --> 2 | // v0.0.1 3 | // Written by JooYoung Seo (jooyoung@psu.edu) and Atsushi Yasumoto on June 1st, 2020. 4 | 5 | document.addEventListener('DOMContentLoaded', function() { 6 | const codeList = document.getElementsByClassName("sourceCode"); 7 | for (var i = 0; i < codeList.length; i++) { 8 | var linkList = codeList[i].getElementsByTagName('a'); 9 | for (var j = 0; j < linkList.length; j++) { 10 | if (linkList[j].innerHTML === "") { 11 | linkList[j].setAttribute('aria-hidden', 'true'); 12 | } 13 | } 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /docs/articles/classic_posologyr_models_files/accessible-code-block-0.0.1/empty-anchor.js: -------------------------------------------------------------------------------- 1 | // Hide empty tag within highlighted CodeBlock for screen reader accessibility (see https://github.com/jgm/pandoc/issues/6352#issuecomment-626106786) --> 2 | // v0.0.1 3 | // Written by JooYoung Seo (jooyoung@psu.edu) and Atsushi Yasumoto on June 1st, 2020. 4 | 5 | document.addEventListener('DOMContentLoaded', function() { 6 | const codeList = document.getElementsByClassName("sourceCode"); 7 | for (var i = 0; i < codeList.length; i++) { 8 | var linkList = codeList[i].getElementsByTagName('a'); 9 | for (var j = 0; j < linkList.length; j++) { 10 | if (linkList[j].innerHTML === "") { 11 | linkList[j].setAttribute('aria-hidden', 'true'); 12 | } 13 | } 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /docs/articles/route_of_administration_files/accessible-code-block-0.0.1/empty-anchor.js: -------------------------------------------------------------------------------- 1 | // Hide empty tag within highlighted CodeBlock for screen reader accessibility (see https://github.com/jgm/pandoc/issues/6352#issuecomment-626106786) --> 2 | // v0.0.1 3 | // Written by JooYoung Seo (jooyoung@psu.edu) and Atsushi Yasumoto on June 1st, 2020. 4 | 5 | document.addEventListener('DOMContentLoaded', function() { 6 | const codeList = document.getElementsByClassName("sourceCode"); 7 | for (var i = 0; i < codeList.length; i++) { 8 | var linkList = codeList[i].getElementsByTagName('a'); 9 | for (var j = 0; j < linkList.length; j++) { 10 | if (linkList[j].innerHTML === "") { 11 | linkList[j].setAttribute('aria-hidden', 'true'); 12 | } 13 | } 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /docs/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /man/posologyr_error_lines.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rxui.R 3 | \name{posologyr_error_lines} 4 | \alias{posologyr_error_lines} 5 | \alias{posologyr_error_lines.norm} 6 | \alias{posologyr_error_lines.t} 7 | \alias{posologyr_error_lines.default} 8 | \alias{posologyr_error_lines.rxUi} 9 | \title{This creates the posologyr error lines from a rxui model} 10 | \usage{ 11 | posologyr_error_lines(line) 12 | 13 | \method{posologyr_error_lines}{norm}(line) 14 | 15 | \method{posologyr_error_lines}{t}(line) 16 | 17 | \method{posologyr_error_lines}{default}(line) 18 | 19 | \method{posologyr_error_lines}{rxUi}(line) 20 | } 21 | \arguments{ 22 | \item{line}{line to parse} 23 | } 24 | \value{ 25 | error lines for posology 26 | } 27 | \description{ 28 | This creates the posologyr error lines from a rxui model 29 | } 30 | \author{ 31 | Matthew L. Fidler 32 | } 33 | \keyword{internal} 34 | -------------------------------------------------------------------------------- /docs/deps/data-deps.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tests/testthat/test_issue_52.R: -------------------------------------------------------------------------------- 1 | test_that("single IIV", { 2 | patient_data <- data.frame(ID=1, 3 | TIME=c(0.0,1.0,14.0), 4 | DV=c(NA,25.0,5.5), 5 | AMT=c(2000,0,0), 6 | DUR=c(0.5,NA,NA), 7 | EVID=c(1,0,0), 8 | CLCREAT=80, 9 | WT=65) 10 | 11 | mod_run001 <- function() { 12 | ini({ 13 | THETA_Cl <- 4.0 14 | THETA_Vc <- 70.0 15 | THETA_Ka <- 1.0 16 | ETA_Cl ~ 0.2 17 | prop.sd <- sqrt(0.05) 18 | }) 19 | model({ 20 | TVCl <- THETA_Cl 21 | TVVc <- THETA_Vc 22 | TVKa <- THETA_Ka 23 | 24 | Cl <- TVCl*exp(ETA_Cl) 25 | Vc <- TVVc 26 | Ka <- TVKa 27 | 28 | K20 <- Cl/Vc 29 | Cc <- centr/Vc 30 | 31 | d/dt(depot) = -Ka*depot 32 | d/dt(centr) = Ka*depot - K20*centr 33 | Cc ~ prop(prop.sd) 34 | }) 35 | } 36 | 37 | f <- poso_estim_map(patient_data, mod_run001) 38 | 39 | expect_equal(f$eta, c(ETA_Cl = 0.7299818),tolerance=1e-3) 40 | 41 | }) 42 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: R-CMD-check 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ${{ matrix.config.os }} 14 | 15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | config: 21 | - {os: macos-latest, r: 'release'} 22 | - {os: windows-latest, r: 'release'} 23 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 24 | - {os: ubuntu-latest, r: 'release'} 25 | - {os: ubuntu-latest, r: 'oldrel-1'} 26 | 27 | env: 28 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 29 | R_KEEP_PKG_SOURCE: yes 30 | 31 | steps: 32 | - uses: actions/checkout@v4 33 | 34 | - uses: r-lib/actions/setup-pandoc@v2 35 | 36 | - uses: r-lib/actions/setup-r@v2 37 | with: 38 | r-version: ${{ matrix.config.r }} 39 | http-user-agent: ${{ matrix.config.http-user-agent }} 40 | use-public-rspm: true 41 | 42 | - uses: r-lib/actions/setup-r-dependencies@v2 43 | with: 44 | extra-packages: any::rcmdcheck 45 | needs: check 46 | 47 | - uses: r-lib/actions/check-r-package@v2 48 | with: 49 | upload-snapshots: true 50 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: posologyr 2 | Title: Individual Dose Optimization using Population Pharmacokinetics 3 | Version: 1.2.8 4 | Authors@R: c( 5 | person("Cyril","Leven",role = c("aut", "cre","cph"), 6 | email = "cyril.leven@chu-brest.fr", 7 | comment = c(ORCID = "0000-0002-0697-4370")), 8 | person("Matthew","Fidler",role = c("ctb"), 9 | email="matthew.fidler@gmail.com", 10 | comment = c(ORCID = "0000-0001-8538-6691")), 11 | person("Emmanuelle","Comets",role = c("ctb")), 12 | person("Audrey","Lavenu",role = c("ctb")), 13 | person("Marc","Lavielle",role = c("ctb")) 14 | ) 15 | Description: Personalize drug regimens using individual pharmacokinetic (PK) and 16 | pharmacokinetic-pharmacodynamic (PK-PD) profiles. By combining therapeutic 17 | drug monitoring (TDM) data with a population model, 'posologyr' offers 18 | accurate posterior estimates and helps compute optimal individualized dosing 19 | regimens. The empirical Bayes estimates are computed following the method 20 | described by Kang et al. (2012) . 21 | License: AGPL-3 22 | Encoding: UTF-8 23 | Roxygen: list(markdown = TRUE) 24 | RoxygenNote: 7.3.2 25 | Depends: 26 | R (>= 3.5.0) 27 | Imports: 28 | rxode2, 29 | stats, 30 | mvtnorm, 31 | data.table 32 | Suggests: 33 | lotri, 34 | rmarkdown, 35 | testthat (>= 3.0.0), 36 | ggplot2, 37 | magrittr, 38 | tidyr 39 | URL: https://levenc.github.io/posologyr/, https://github.com/levenc/posologyr 40 | BugReports: https://github.com/levenc/posologyr/issues 41 | Config/testthat/edition: 3 42 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | url: https://levenc.github.io/posologyr/ 2 | template: 3 | bootstrap: 5 4 | reference: 5 | - title: "Dose optimization functions" 6 | - contents: 7 | - poso_dose_auc 8 | - poso_dose_conc 9 | - poso_time_cmin 10 | - poso_inter_cmin 11 | - title: "Estimation functions" 12 | desc: "Functions for estimating the pharmacokinetic parameters" 13 | - contents: 14 | - poso_estim_map 15 | - poso_estim_mcmc 16 | - poso_estim_sir 17 | - poso_simu_pop 18 | - title: "Post-processing" 19 | - contents: 20 | - poso_replace_et 21 | navbar: 22 | left: 23 | - text: Models & Data 24 | icon: fas fa-book 25 | menu: 26 | - text: "Getting started" 27 | - text: "Population models" 28 | href: articles/population_models.html 29 | - text: "Patient data" 30 | href: articles/patient_data.html 31 | - text: "--------------------------" 32 | - text: "Advanced models" 33 | - text: "Multiple endpoints models" 34 | href: articles/multiple_endpoints.html 35 | - text: "Classic posologyr models" 36 | href: articles/classic_posologyr_models.html 37 | - text: Dose selection 38 | icon: fas fa-pills 39 | menu: 40 | - text: "A priori dose selection" 41 | href: articles/a_priori_dosing.html 42 | - text: "A posteriori dose selection" 43 | href: articles/a_posteriori_dosing.html 44 | - text: "AUC-based dose selection" 45 | href: articles/auc_based_dosing.html 46 | - text: "Route of administration" 47 | href: articles/route_of_administration.html 48 | - text: Functions 49 | href: reference/index.html 50 | - text: Changelog 51 | href: news/index.html 52 | -------------------------------------------------------------------------------- /tests/testthat/test_issue_29.R: -------------------------------------------------------------------------------- 1 | # prior model 2 | mod_run202 <- list( 3 | ppk_model = rxode2::rxode({ 4 | depot(0) = 0; 5 | centr(0) = 0; 6 | 7 | TVVmax = THETA_Vmax; 8 | TVVc = THETA_Vc; 9 | TVKa = THETA_Ka; 10 | TVKm = THETA_Km; 11 | 12 | Vmax = TVVmax*exp(ETA_Vmax); 13 | Vc = TVVc*exp(ETA_Vc); 14 | Ka = TVKa*exp(ETA_Ka); 15 | Km = TVKm*exp(ETA_Km); 16 | Cc = centr/Vc; 17 | 18 | d/dt(depot) = - Ka*depot; 19 | d/dt(centr) = Ka*depot - Vmax*(centr/Vc)/(Km+(centr/Vc)); 20 | d/dt(AUC) = Cc; 21 | }), 22 | error_model = function(f,sigma){ 23 | dv <- cbind(f,1) 24 | g <- diag(dv%*%sigma%*%t(dv)) 25 | return(sqrt(g)) 26 | }, 27 | theta = c(THETA_Vmax=10000, THETA_Vc=70.0, THETA_Ka=1.0, THETA_Km=2500), 28 | omega = lotri::lotri({ETA_Vmax + ETA_Vc + ETA_Ka + ETA_Km ~ 29 | c(0.2 , 30 | 0 , 0.2, 31 | 0 , 0, 0, 32 | 0 , 0, 0, 0.2)}), 33 | sigma = lotri::lotri({prop + add ~ c(0.05,0.0,0.00)})) 34 | 35 | # patient data 36 | kmpat <- data.frame(ID=1, 37 | TIME=c(0,1.5,4.4,7.1,24.6,72), 38 | EVID=c(1,0,0,0,0,1), 39 | AMT=c(10000,0,0,0,0,10000), 40 | CMT=2,II=c(0,0,0,0,0,24), 41 | ADDL=c(0,0,0,0,0,6), 42 | RATE=c(10000,0,0,0,0,10000), 43 | MDV=c(1,0,0,0,0,1), 44 | DV=c(NA,111.57400,97.86790,64.29320,9.91143,NA)) 45 | 46 | set.seed(42) 47 | 48 | test_that("poso_estim_map provides estimates even when the IIV is zero", { 49 | expect_equal(poso_estim_map(kmpat,mod_run202,nocb=TRUE, 50 | return_ofv=TRUE, 51 | return_model=F)$eta, 52 | c(ETA_Vmax=0.3799632360,ETA_Vc=8.405155e-02, 53 | ETA_Ka=0.00000000,ETA_Km=-0.3684082160),tolerance=1e-3) 54 | }) 55 | -------------------------------------------------------------------------------- /tests/testthat/test_issue_28.R: -------------------------------------------------------------------------------- 1 | # prior model 2 | mod_run003 <- list( 3 | ppk_model = rxode2::rxode({ 4 | centr(0) = 0; 5 | depot(0) = 0; 6 | 7 | TVCl = THETA_Cl; 8 | TVVc = THETA_Vc; 9 | TVKa = THETA_Ka; 10 | TVALAG = THETA_ALAG; 11 | 12 | Cl = TVCl*exp(ETA_Cl); 13 | Vc = TVVc*exp(ETA_Vc); 14 | Ka = TVKa*exp(ETA_Ka); 15 | ALAG = TVALAG*exp(ETA_ALAG); 16 | 17 | K20 = Cl/Vc; 18 | Cc = centr/Vc; 19 | 20 | d/dt(depot) = -Ka*depot; 21 | d/dt(centr) = Ka*depot - K20*centr; 22 | d/dt(AUC) = Cc; 23 | 24 | alag(depot) = ALAG; 25 | 26 | }), 27 | error_model = function(f,sigma) { 28 | dv <- cbind(f,1) 29 | g <- diag(dv%*%sigma%*%t(dv)) 30 | return(sqrt(g)) 31 | }, 32 | theta = c(THETA_Cl=4.0, THETA_Vc=70.0, THETA_Ka=1.0, THETA_ALAG=1.0), 33 | omega = lotri::lotri({ETA_Cl + ETA_Vc + ETA_Ka + ETA_ALAG ~ 34 | c(0.2, 35 | 0, 0.2, 36 | 0, 0, 0.2, 37 | 0, 0, 0, 0.2)}), 38 | sigma = lotri::lotri({prop + add ~ c(0.05,0.0,0.00)}) 39 | ) 40 | 41 | #patient data 42 | lagpat <- data.frame(ID=1, 43 | TIME=c(0,1.5,4.4,7.1,24.6,72), 44 | EVID=c(1,0,0,0,0,1), 45 | AMT=c(10000,0,0,0,0,10000), 46 | CMT=c(1,2,2,2,2,1), 47 | II=c(0,0,0,0,0,24), 48 | ADDL=c(0,0,0,0,0,6), 49 | MDV=c(1,0,0,0,0,1), 50 | DV=c(NA,67.4275,115.4490,83.7768,21.8323,NA)) 51 | 52 | set.seed(42) 53 | 54 | test_that("poso_estim_map provides estimates even when predicted concentrations 55 | are zero", { 56 | expect_equal(poso_estim_map(lagpat,mod_run003,nocb=TRUE, 57 | return_ofv=TRUE, 58 | return_model=F)$eta, 59 | c(ETA_Cl=0.396185952,ETA_Vc=0.0370173441, 60 | ETA_Ka=0.0825083501,ETA_ALAG=-0.0967599813),tolerance=1e-3) 61 | }) 62 | -------------------------------------------------------------------------------- /tests/testthat/test_issue_30.R: -------------------------------------------------------------------------------- 1 | # model with a single IOV 2 | mod_MTXHD_joerger2011 <- list( 3 | ppk_model = rxode2::rxode({ 4 | centr(0) = 0; 5 | TVCl = THETA_Cl*(CLCREAT/95)^0.28*(BSA/1.75)^0.15; 6 | TVVc = THETA_Vc; 7 | TVVp = THETA_Vp; 8 | TVQ = THETA_Q; 9 | Cl = TVCl*exp(ETA_Cl+KAPPA_Cl); 10 | Vc = TVVc; 11 | Vp = TVVp*exp(ETA_Vp); 12 | Q = TVQ; 13 | ke = Cl/Vc; 14 | k12 = Q/Vc; 15 | k21 = Q/Vp; 16 | Cc = centr/Vc; 17 | d/dt(centr) = - ke*centr - k12*centr + k21*periph; 18 | d/dt(periph) = + k12*centr - k21*periph; 19 | d/dt(AUC) = Cc; 20 | }), 21 | error_model = function(f,sigma){ 22 | dv <- cbind(f,1) 23 | g <- diag(dv%*%sigma%*%t(dv)) 24 | return(sqrt(g)) 25 | }, 26 | theta = c(THETA_Cl=10.8, THETA_Vc=34, THETA_Vp=6.3,THETA_Q=0.35), 27 | omega = lotri::lotri({ETA_Cl + ETA_Vc + ETA_Vp + ETA_Q ~ 28 | c(0.10878, 29 | 0 , 0 , 30 | 0 , 0 , 0.116808, 31 | 0 , 0 , 0 , 0)}), 32 | pi_matrix = lotri::lotri({KAPPA_Cl ~ 33 | c(0.017)}), 34 | covariates = c("CLCREAT","BSA"), 35 | sigma = lotri::lotri({prop + add ~ c(0.318,0.0,0.00)})) 36 | 37 | # patient record 38 | df_patientA_tdm <-data.frame(ID=1, 39 | TIME=c(0,36,42,48), 40 | DV=c(NA,10.32,6.59,4.58), 41 | AMT=c(11723,0,0,0), 42 | DUR=c(3,NA,NA,NA), 43 | EVID=c(1,0,0,0), 44 | OCC=c(1,1,1,1), 45 | CLCREAT=c(59,175,175,175), 46 | BSA=2.049, 47 | OCC=1) 48 | 49 | # estimation 50 | patAmap <- poso_estim_map(df_patientA_tdm,mod_MTXHD_joerger2011) 51 | 52 | 53 | test_that("poso_estim_map provides estimates for models with a single IOV", { 54 | expect_equal(patAmap$eta, 55 | c(ETA_Cl=-0.78916725,ETA_Vc=0.0, 56 | ETA_Vp=0.05709275,ETA_Q=0.0),tolerance=1e-3) 57 | }) 58 | -------------------------------------------------------------------------------- /tests/testthat/test_map_nlmixr.R: -------------------------------------------------------------------------------- 1 | mod_amikacin_2cpt_Burdet2015 <- list( 2 | ppk_model = rxode2::rxode({ 3 | centr(0) = 0; 4 | TVCl = THETA_Cl*(CLCREAT4H/82)^0.7; 5 | TVVc = THETA_Vc*(TBW/78)^0.9*(PoverF/169)^0.4; 6 | TVVp = THETA_Vp; 7 | TVQ = THETA_Q; 8 | Cl = TVCl*exp(ETA_Cl); 9 | Vc = TVVc*exp(ETA_Vc); 10 | Vp = TVVp*exp(ETA_Vp); 11 | Q = TVQ *exp(ETA_Q); 12 | ke = Cl/Vc; 13 | k12 = Q/Vc; 14 | k21 = Q/Vp; 15 | Cc = centr/Vc; 16 | d/dt(centr) = - ke*centr - k12*centr + k21*periph; 17 | d/dt(periph) = + k12*centr - k21*periph; 18 | d/dt(AUC) = Cc; 19 | }), 20 | error_model = function(f,sigma){ 21 | g <- sigma[1]^2 + (sigma[2]^2)*(f^2) 22 | return(sqrt(g)) 23 | }, 24 | theta = c(THETA_Cl=4.3, THETA_Vc=15.9, THETA_Vp=21.4,THETA_Q=12.1), 25 | omega = lotri::lotri({ETA_Cl + ETA_Vc + ETA_Vp + ETA_Q ~ 26 | c(0.1, 27 | 0.01 , 0.05 , 28 | 0.01 , 0.02 , 0.2 , 29 | -0.06 , 0.004, 0.003, 0.08)}), 30 | covariates = c("CLCREAT4H","TBW","PoverF"), 31 | sigma = c(additive_a = 0.2, proportional_b = 0.1)) 32 | 33 | df_patient03_amik <- data.frame(ID=1,TIME=c(0,1,6), 34 | DV=c(NA,75,32), 35 | EVID=c(1,0,0), 36 | AMT=c(1600,0,0), 37 | DUR=c(0.5,NA,NA), 38 | CLCREAT4H=50,TBW=62,PoverF=169,AMS=1) 39 | 40 | patient03_amik_map <- poso_estim_map(dat=df_patient03_amik, 41 | prior_model=mod_amikacin_2cpt_Burdet2015, 42 | return_model=TRUE) 43 | 44 | test_that("MAP estimates match nlmixr posthoc estimates", { 45 | expect_equal(patient03_amik_map$model$Cl[1], 2.62, tolerance=1e-3) 46 | expect_equal(patient03_amik_map$model$Vc[1], 11.01, tolerance=1e-3) 47 | expect_equal(patient03_amik_map$model$Vp[1], 14.57, tolerance=1e-3) 48 | expect_equal(patient03_amik_map$model$Q[1], 11.96, tolerance=1e-3) 49 | }) 50 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | 6 | /* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ 7 | 8 | /* All levels of nav */ 9 | nav[data-toggle='toc'] .nav > li > a { 10 | display: block; 11 | padding: 4px 20px; 12 | font-size: 13px; 13 | font-weight: 500; 14 | color: #767676; 15 | } 16 | nav[data-toggle='toc'] .nav > li > a:hover, 17 | nav[data-toggle='toc'] .nav > li > a:focus { 18 | padding-left: 19px; 19 | color: #563d7c; 20 | text-decoration: none; 21 | background-color: transparent; 22 | border-left: 1px solid #563d7c; 23 | } 24 | nav[data-toggle='toc'] .nav > .active > a, 25 | nav[data-toggle='toc'] .nav > .active:hover > a, 26 | nav[data-toggle='toc'] .nav > .active:focus > a { 27 | padding-left: 18px; 28 | font-weight: bold; 29 | color: #563d7c; 30 | background-color: transparent; 31 | border-left: 2px solid #563d7c; 32 | } 33 | 34 | /* Nav: second level (shown on .active) */ 35 | nav[data-toggle='toc'] .nav .nav { 36 | display: none; /* Hide by default, but at >768px, show it */ 37 | padding-bottom: 10px; 38 | } 39 | nav[data-toggle='toc'] .nav .nav > li > a { 40 | padding-top: 1px; 41 | padding-bottom: 1px; 42 | padding-left: 30px; 43 | font-size: 12px; 44 | font-weight: normal; 45 | } 46 | nav[data-toggle='toc'] .nav .nav > li > a:hover, 47 | nav[data-toggle='toc'] .nav .nav > li > a:focus { 48 | padding-left: 29px; 49 | } 50 | nav[data-toggle='toc'] .nav .nav > .active > a, 51 | nav[data-toggle='toc'] .nav .nav > .active:hover > a, 52 | nav[data-toggle='toc'] .nav .nav > .active:focus > a { 53 | padding-left: 28px; 54 | font-weight: 500; 55 | } 56 | 57 | /* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ 58 | nav[data-toggle='toc'] .nav > .active > ul { 59 | display: block; 60 | } 61 | -------------------------------------------------------------------------------- /docs/deps/bootstrap-toc-1.0.1/bootstrap-toc.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v1.0.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | !function(a){"use strict";window.Toc={helpers:{findOrFilter:function(e,t){var n=e.find(t);return e.filter(t).add(n).filter(":not([data-toc-skip])")},generateUniqueIdBase:function(e){return a(e).text().trim().replace(/\'/gi,"").replace(/[& +$,:;=?@"#{}|^~[`%!'<>\]\.\/\(\)\*\\\n\t\b\v]/g,"-").replace(/-{2,}/g,"-").substring(0,64).replace(/^-+|-+$/gm,"").toLowerCase()||e.tagName.toLowerCase()},generateUniqueId:function(e){for(var t=this.generateUniqueIdBase(e),n=0;;n++){var r=t;if(0')},createChildNavList:function(e){var t=this.createNavList();return e.append(t),t},generateNavEl:function(e,t){var n=a('');n.attr("href","#"+e),n.text(t);var r=a("
  • ");return r.append(n),r},generateNavItem:function(e){var t=this.generateAnchor(e),n=a(e),r=n.data("toc-text")||n.text();return this.generateNavEl(t,r)},getTopLevel:function(e){for(var t=1;t<=6;t++){if(1 2 | https://levenc.github.io/posologyr/404.html 3 | https://levenc.github.io/posologyr/LICENSE.html 4 | https://levenc.github.io/posologyr/articles/a_posteriori_dosing.html 5 | https://levenc.github.io/posologyr/articles/a_priori_dosing.html 6 | https://levenc.github.io/posologyr/articles/auc_based_dosing.html 7 | https://levenc.github.io/posologyr/articles/classic_posologyr_models.html 8 | https://levenc.github.io/posologyr/articles/index.html 9 | https://levenc.github.io/posologyr/articles/multiple_endpoints.html 10 | https://levenc.github.io/posologyr/articles/patient_data.html 11 | https://levenc.github.io/posologyr/articles/patient_data_input.html 12 | https://levenc.github.io/posologyr/articles/population_models.html 13 | https://levenc.github.io/posologyr/articles/posologyr_user_defined_models.html 14 | https://levenc.github.io/posologyr/articles/route_of_administration.html 15 | https://levenc.github.io/posologyr/authors.html 16 | https://levenc.github.io/posologyr/index.html 17 | https://levenc.github.io/posologyr/news/index.html 18 | https://levenc.github.io/posologyr/reference/error_model_comb1.html 19 | https://levenc.github.io/posologyr/reference/error_model_comb2.html 20 | https://levenc.github.io/posologyr/reference/error_model_mixednm.html 21 | https://levenc.github.io/posologyr/reference/index.html 22 | https://levenc.github.io/posologyr/reference/poso_dose_auc.html 23 | https://levenc.github.io/posologyr/reference/poso_dose_conc.html 24 | https://levenc.github.io/posologyr/reference/poso_estim_map.html 25 | https://levenc.github.io/posologyr/reference/poso_estim_mcmc.html 26 | https://levenc.github.io/posologyr/reference/poso_estim_sir.html 27 | https://levenc.github.io/posologyr/reference/poso_inter_cmin.html 28 | https://levenc.github.io/posologyr/reference/poso_replace_et.html 29 | https://levenc.github.io/posologyr/reference/poso_simu_pop.html 30 | https://levenc.github.io/posologyr/reference/poso_time_cmin.html 31 | https://levenc.github.io/posologyr/reference/posologyr_error_lines.html 32 | 33 | 34 | -------------------------------------------------------------------------------- /man/poso_estim_map.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/param_estim.R 3 | \name{poso_estim_map} 4 | \alias{poso_estim_map} 5 | \title{Estimate the Maximum A Posteriori individual parameters} 6 | \usage{ 7 | poso_estim_map( 8 | dat = NULL, 9 | prior_model = NULL, 10 | return_model = TRUE, 11 | return_ofv = FALSE, 12 | nocb = FALSE 13 | ) 14 | } 15 | \arguments{ 16 | \item{dat}{Dataframe. An individual subject dataset following the 17 | structure of NONMEM/rxode2 event records.} 18 | 19 | \item{prior_model}{A \code{posologyr} prior population pharmacokinetics 20 | model, a list of six objects.} 21 | 22 | \item{return_model}{A boolean. Returns a rxode2 model using the estimated 23 | ETAs if set to \code{TRUE}.} 24 | 25 | \item{return_ofv}{A boolean. Returns a the Objective Function Value (OFV) 26 | if set to \code{TRUE}.} 27 | 28 | \item{nocb}{A boolean. for time-varying covariates: the next observation 29 | carried backward (nocb) interpolation style, similar to NONMEM. If 30 | \code{FALSE}, the last observation carried forward (locf) style will be used. 31 | Defaults to \code{FALSE}.} 32 | } 33 | \value{ 34 | A named list consisting of one or more of the following elements 35 | depending on the input parameters of the function: \verb{$eta} a named vector 36 | of the MAP estimates of the individual values of ETA, \verb{$model} an rxode2 37 | model using the estimated ETAs, \verb{$event} the \code{data.table} used to solve the 38 | returned rxode2 model. 39 | } 40 | \description{ 41 | Estimates the Maximum A Posteriori (MAP) individual parameters, 42 | also known as Empirical Bayes Estimates (EBE). 43 | } 44 | \examples{ 45 | rxode2::setRxThreads(1) # limit the number of threads 46 | 47 | # model 48 | mod_run001 <- function() { 49 | ini({ 50 | THETA_Cl <- 4.0 51 | THETA_Vc <- 70.0 52 | THETA_Ka <- 1.0 53 | ETA_Cl ~ 0.2 54 | ETA_Vc ~ 0.2 55 | ETA_Ka ~ 0.2 56 | prop.sd <- sqrt(0.05) 57 | }) 58 | model({ 59 | TVCl <- THETA_Cl 60 | TVVc <- THETA_Vc 61 | TVKa <- THETA_Ka 62 | 63 | Cl <- TVCl*exp(ETA_Cl) 64 | Vc <- TVVc*exp(ETA_Vc) 65 | Ka <- TVKa*exp(ETA_Ka) 66 | 67 | K20 <- Cl/Vc 68 | Cc <- centr/Vc 69 | 70 | d/dt(depot) = -Ka*depot 71 | d/dt(centr) = Ka*depot - K20*centr 72 | Cc ~ prop(prop.sd) 73 | }) 74 | } 75 | # df_patient01: event table for Patient01, following a 30 minutes intravenous 76 | # infusion 77 | df_patient01 <- data.frame(ID=1, 78 | TIME=c(0.0,1.0,14.0), 79 | DV=c(NA,25.0,5.5), 80 | AMT=c(2000,0,0), 81 | EVID=c(1,0,0), 82 | DUR=c(0.5,NA,NA)) 83 | # estimate the Maximum A Posteriori individual parameters 84 | poso_estim_map(dat=df_patient01,prior_model=mod_run001) 85 | 86 | } 87 | -------------------------------------------------------------------------------- /docs/lightswitch.js: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * Color mode toggler for Bootstrap's docs (https://getbootstrap.com/) 4 | * Copyright 2011-2023 The Bootstrap Authors 5 | * Licensed under the Creative Commons Attribution 3.0 Unported License. 6 | * Updates for {pkgdown} by the {bslib} authors, also licensed under CC-BY-3.0. 7 | */ 8 | 9 | const getStoredTheme = () => localStorage.getItem('theme') 10 | const setStoredTheme = theme => localStorage.setItem('theme', theme) 11 | 12 | const getPreferredTheme = () => { 13 | const storedTheme = getStoredTheme() 14 | if (storedTheme) { 15 | return storedTheme 16 | } 17 | 18 | return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' 19 | } 20 | 21 | const setTheme = theme => { 22 | if (theme === 'auto') { 23 | document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')) 24 | } else { 25 | document.documentElement.setAttribute('data-bs-theme', theme) 26 | } 27 | } 28 | 29 | function bsSetupThemeToggle () { 30 | 'use strict' 31 | 32 | const showActiveTheme = (theme, focus = false) => { 33 | var activeLabel, activeIcon; 34 | 35 | document.querySelectorAll('[data-bs-theme-value]').forEach(element => { 36 | const buttonTheme = element.getAttribute('data-bs-theme-value') 37 | const isActive = buttonTheme == theme 38 | 39 | element.classList.toggle('active', isActive) 40 | element.setAttribute('aria-pressed', isActive) 41 | 42 | if (isActive) { 43 | activeLabel = element.textContent; 44 | activeIcon = element.querySelector('span').classList.value; 45 | } 46 | }) 47 | 48 | const themeSwitcher = document.querySelector('#dropdown-lightswitch') 49 | if (!themeSwitcher) { 50 | return 51 | } 52 | 53 | themeSwitcher.setAttribute('aria-label', activeLabel) 54 | themeSwitcher.querySelector('span').classList.value = activeIcon; 55 | 56 | if (focus) { 57 | themeSwitcher.focus() 58 | } 59 | } 60 | 61 | window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { 62 | const storedTheme = getStoredTheme() 63 | if (storedTheme !== 'light' && storedTheme !== 'dark') { 64 | setTheme(getPreferredTheme()) 65 | } 66 | }) 67 | 68 | window.addEventListener('DOMContentLoaded', () => { 69 | showActiveTheme(getPreferredTheme()) 70 | 71 | document 72 | .querySelectorAll('[data-bs-theme-value]') 73 | .forEach(toggle => { 74 | toggle.addEventListener('click', () => { 75 | const theme = toggle.getAttribute('data-bs-theme-value') 76 | setTheme(theme) 77 | setStoredTheme(theme) 78 | showActiveTheme(theme, true) 79 | }) 80 | }) 81 | }) 82 | } 83 | 84 | setTheme(getPreferredTheme()); 85 | bsSetupThemeToggle(); 86 | -------------------------------------------------------------------------------- /man/poso_estim_sir.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/param_estim.R 3 | \name{poso_estim_sir} 4 | \alias{poso_estim_sir} 5 | \title{Estimate the posterior distribution of individual parameters by SIR} 6 | \usage{ 7 | poso_estim_sir( 8 | dat = NULL, 9 | prior_model = NULL, 10 | n_sample = 10000, 11 | n_resample = 1000, 12 | return_model = TRUE, 13 | nocb = FALSE 14 | ) 15 | } 16 | \arguments{ 17 | \item{dat}{Dataframe. An individual subject dataset following the 18 | structure of NONMEM/rxode2 event records.} 19 | 20 | \item{prior_model}{A \code{posologyr} prior population pharmacokinetics 21 | model, a list of six objects.} 22 | 23 | \item{n_sample}{Number of samples from the S-step} 24 | 25 | \item{n_resample}{Number of samples from the R-step} 26 | 27 | \item{return_model}{A boolean. Returns a rxode2 model using the estimated 28 | ETAs if set to \code{TRUE}.} 29 | 30 | \item{nocb}{A boolean. for time-varying covariates: the next observation 31 | carried backward (nocb) interpolation style, similar to NONMEM. If 32 | \code{FALSE}, the last observation carried forward (locf) style will be used. 33 | Defaults to \code{FALSE}.} 34 | } 35 | \value{ 36 | If \code{return_model} is set to \code{FALSE}, a list of one element: a 37 | dataframe \verb{$eta} of ETAs from the posterior distribution, estimated by 38 | Sequential Importance Resampling. 39 | If \code{return_model} is set to \code{TRUE}, a list of the dataframe of the posterior 40 | distribution of ETA, and a rxode2 model using the estimated distributions of 41 | ETAs. 42 | } 43 | \description{ 44 | Estimates the posterior distribution of individual parameters by 45 | Sequential Importance Resampling (SIR) 46 | } 47 | \examples{ 48 | # model 49 | mod_run001 <- function() { 50 | ini({ 51 | THETA_Cl <- 4.0 52 | THETA_Vc <- 70.0 53 | THETA_Ka <- 1.0 54 | ETA_Cl ~ 0.2 55 | ETA_Vc ~ 0.2 56 | ETA_Ka ~ 0.2 57 | prop.sd <- sqrt(0.05) 58 | }) 59 | model({ 60 | TVCl <- THETA_Cl 61 | TVVc <- THETA_Vc 62 | TVKa <- THETA_Ka 63 | 64 | Cl <- TVCl*exp(ETA_Cl) 65 | Vc <- TVVc*exp(ETA_Vc) 66 | Ka <- TVKa*exp(ETA_Ka) 67 | 68 | K20 <- Cl/Vc 69 | Cc <- centr/Vc 70 | 71 | d/dt(depot) = -Ka*depot 72 | d/dt(centr) = Ka*depot - K20*centr 73 | Cc ~ prop(prop.sd) 74 | }) 75 | } 76 | # df_patient01: event table for Patient01, following a 30 minutes intravenous 77 | # infusion 78 | df_patient01 <- data.frame(ID=1, 79 | TIME=c(0.0,1.0,14.0), 80 | DV=c(NA,25.0,5.5), 81 | AMT=c(2000,0,0), 82 | EVID=c(1,0,0), 83 | DUR=c(0.5,NA,NA)) 84 | # estimate the posterior distribution of population parameters 85 | poso_estim_sir(dat=df_patient01,prior_model=mod_run001, 86 | n_sample=1e3,n_resample=1e2) 87 | 88 | } 89 | -------------------------------------------------------------------------------- /tests/testthat/test_issue_32.R: -------------------------------------------------------------------------------- 1 | mod_piperacillin_2cpt_Roberts2010 <- list( 2 | ppk_model = rxode2::rxode({ 3 | centr(0) = 0; 4 | # Time lag from dose infuser to patient 5 | TVLAGTIME = THETA_LAGTIME 6 | LAGTIME = TVLAGTIME*exp(ETA_LAGTIME) 7 | # ------------------------------------- 8 | TVCl = THETA_Cl*(TBW/70); 9 | TVV1 = THETA_V1; 10 | TVV2 = THETA_V2; 11 | TVQ = THETA_Q; 12 | Cl = TVCl*exp(ETA_Cl + KAPPA_Cl); 13 | Cli = TVCl*exp(ETA_Cl); 14 | V1 = TVV1*exp(ETA_V1 + KAPPA_V1); 15 | V1i = TVV1*exp(ETA_V1); 16 | V2 = TVV2*exp(ETA_V2); 17 | Q = TVQ *exp(ETA_Q); 18 | ke = Cl/V1; 19 | k12 = Q/V1; 20 | k21 = Q/V2; 21 | Cc = centr/V1; 22 | d/dt(centr) = - ke*centr - k12*centr + k21*periph; 23 | d/dt(periph) = + k12*centr - k21*periph; 24 | lag(centr) = LAGTIME; 25 | d/dt(AUC) = Cc; 26 | }), 27 | error_model = function(f,sigma){ 28 | g <- sigma[1] + sigma[2]*f 29 | return(g) 30 | }, 31 | theta = c(THETA_LAGTIME=0.07,THETA_Cl=17.1,THETA_V1=7.2,THETA_V2=17.8, 32 | THETA_Q=52.0), 33 | omega = lotri::lotri({ETA_LAGTIME + ETA_Cl + ETA_V1 + ETA_V2 + ETA_Q ~ 34 | c(0.1747673, 35 | 0.00 , 0.08507985, 36 | 0.00 , 0.00 , 0.0673745, 37 | 0.00 , 0.00 , 0.00 , 0.429067, 38 | 0.00 , 0.00 , 0.00 , 0.00 , 0.2247455)}), 39 | pi_matrix = lotri::lotri({KAPPA_Cl + KAPPA_V1 ~ 40 | c(0.1934626, 41 | 0.00 , 0.05783106)}), 42 | covariates = c("TBW"), 43 | sigma = c(additive_a = 3.2, proportional_b = 0.253)) 44 | 45 | df_patient32 <- data.frame(ID=6, 46 | TIME=c(0.0,8,16,24,32,40,47.9,48,56,64,71.9), 47 | DV=c(NA,NA,NA,NA,NA,NA,63.0,NA,NA,NA,19.7), 48 | AMT=c(4000,4000,4000,4000,4000,4000,NA,4000,4000,4000, 49 | NA), 50 | DUR=c(8,8,8,8,8,8,NA,8,8,8,NA), 51 | EVID=c(1,1,1,1,1,1,0,1,1,1,0), 52 | TBW=92,OCC=c(1,1,1,1,1,1,1,2,2,2,2)) 53 | 54 | test_that("Dosing optim functions can use models with IOV", { 55 | expect_equal(poso_time_cmin(dat=df_patient32, 56 | prior_model=mod_piperacillin_2cpt_Roberts2010, 57 | from=4, 58 | dose=1500, 59 | duration=4, 60 | target_cmin=10)$time,4.8) 61 | expect_equal(poso_dose_auc(dat=df_patient32, 62 | prior_model=mod_piperacillin_2cpt_Roberts2010, 63 | time_auc=24, 64 | duration=4, 65 | target_auc=200)$dose,3793,tolerance=1e-1) 66 | expect_equal(poso_dose_conc(dat=df_patient32, 67 | prior_model=mod_piperacillin_2cpt_Roberts2010, 68 | time_c=6, 69 | duration=4, 70 | target_conc=10)$dose,3388,tolerance=1e-1) 71 | expect_equal(poso_inter_cmin(dat=df_patient32, 72 | prior_model=mod_piperacillin_2cpt_Roberts2010, 73 | dose=5000, 74 | add_dose=10, 75 | duration=4, 76 | target_cmin=20)$interval,5.66,tolerance=1e-1) 77 | }) 78 | -------------------------------------------------------------------------------- /tests/testthat/test_map_iov.R: -------------------------------------------------------------------------------- 1 | mod_piperacillin_2cpt_Roberts2010 <- list( 2 | ppk_model = rxode2::rxode({ 3 | centr(0) = 0; 4 | # Time lag from dose infuser to patient 5 | TVLAGTIME = THETA_LAGTIME 6 | LAGTIME = TVLAGTIME*exp(ETA_LAGTIME) 7 | # ------------------------------------- 8 | TVCl = THETA_Cl*(TBW/70); 9 | TVV1 = THETA_V1; 10 | TVV2 = THETA_V2; 11 | TVQ = THETA_Q; 12 | Cl = TVCl*exp(ETA_Cl + KAPPA_Cl); 13 | Cli = TVCl*exp(ETA_Cl); 14 | V1 = TVV1*exp(ETA_V1 + KAPPA_V1); 15 | V1i = TVV1*exp(ETA_V1); 16 | V2 = TVV2*exp(ETA_V2); 17 | Q = TVQ *exp(ETA_Q); 18 | ke = Cl/V1; 19 | k12 = Q/V1; 20 | k21 = Q/V2; 21 | Cc = centr/V1; 22 | d/dt(centr) = - ke*centr - k12*centr + k21*periph; 23 | d/dt(periph) = + k12*centr - k21*periph; 24 | lag(centr) = LAGTIME; 25 | d/dt(AUC) = Cc; 26 | }), 27 | error_model = function(f,sigma){ 28 | g <- sigma[1] + sigma[2]*f 29 | return(g) 30 | }, 31 | theta = c(THETA_LAGTIME=0.07,THETA_Cl=17.1,THETA_V1=7.2,THETA_V2=17.8, 32 | THETA_Q=52.0), 33 | omega = lotri::lotri({ETA_LAGTIME + ETA_Cl + ETA_V1 + ETA_V2 + ETA_Q ~ 34 | c(0.1747673, 35 | 0.00 , 0.08507985, 36 | 0.00 , 0.00 , 0.0673745, 37 | 0.00 , 0.00 , 0.00 , 0.429067, 38 | 0.00 , 0.00 , 0.00 , 0.00 , 0.2247455)}), 39 | pi_matrix = lotri::lotri({KAPPA_Cl + KAPPA_V1 ~ 40 | c(0.1934626, 41 | 0.00 , 0.05783106)}), 42 | covariates = c("TBW"), 43 | sigma = c(additive_a = 3.2, proportional_b = 0.253)) 44 | 45 | df_patient06_pipera <- data.frame(ID=6, 46 | TIME=c(0.0,8,16,24,32,40,47.9,48, 47 | 56,64,71.9,72,80,88,95.9, 48 | 96,104,112,120), 49 | DV=c(NA,NA,NA,NA,NA,NA,63.0,NA,NA, 50 | NA,19.7,NA,NA,NA,31,NA,NA,NA,16), 51 | AMT=c(4000,4000,4000,4000,4000,4000,NA, 52 | 4000,4000,4000,NA,4000,4000,4000, 53 | NA,4000,4000,4000,NA), 54 | DUR=c(8,8,8,8,8,8,NA,8,8,8,NA,8,8,8,NA, 55 | 8,8,8,NA), 56 | EVID=c(1,1,1,1,1,1,0,1,1,1,0,1,1,1,0, 57 | 1,1,1,0), 58 | TBW=92, 59 | OCC=c(1,1,1,1,1,1,1,2,2,2,2,3,3,3,3, 60 | 4,4,4,4)) 61 | 62 | pat06_map_iov <- poso_estim_map(dat=df_patient06_pipera, 63 | prior_model=mod_piperacillin_2cpt_Roberts2010, 64 | return_model=TRUE) 65 | 66 | test_that("MAP estimates match Monolix MAP estimates", { 67 | expect_equal(pat06_map_iov$model$LAGTIME[1], 0.07, tolerance=1e-3) 68 | expect_equal(unique(pat06_map_iov$model$Cl)[1], 10.58, tolerance=1e-3) 69 | expect_equal(unique(pat06_map_iov$model$Cl)[2], 24.0, tolerance=1e-3) 70 | expect_equal(unique(pat06_map_iov$model$Cl)[3], 18.4, tolerance=1e-3) 71 | expect_equal(unique(pat06_map_iov$model$Cl)[4], 26.3, tolerance=1e-3) 72 | expect_equal(pat06_map_iov$model$V1[1], 7.2, tolerance=1e-3) 73 | expect_equal(pat06_map_iov$model$Q[1], 52, tolerance=1e-3) 74 | expect_equal(pat06_map_iov$model$V2[1], 17.8, tolerance=1e-3) 75 | }) 76 | -------------------------------------------------------------------------------- /R/iov.R: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------- 2 | # posologyr: individual dose optimization using population PK 3 | # Copyright (C) Cyril Leven 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Affero General Public License as 7 | # published by the Free Software Foundation, either version 3 of the 8 | # License, or (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU Affero General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Affero General Public License 16 | # along with this program. If not, see . 17 | #------------------------------------------------------------------------- 18 | 19 | # Get propositions for values of kappa and put them in colums to be added 20 | # to the dataset for rxode2 21 | iov_proposition_as_cols <- function(iov_col=NULL, 22 | dat=NULL, 23 | pimat=NULL, 24 | omega_dim=NULL, 25 | eta_estim=NULL){ 26 | n_iov <- ncol(iov_col)-1 #minus one because of $OCC 27 | 28 | for (i in seq_along(unique(dat$OCC))){ 29 | start_estim_iov <- omega_dim+1+n_iov*(i-1) 30 | end_estim_iov <- start_estim_iov+n_iov-1 31 | iov_vector_i <- eta_estim[start_estim_iov:end_estim_iov] 32 | 33 | occ_size <- length(iov_col[iov_col$OCC == i,1]) 34 | iov_mat_i <- matrix(iov_vector_i, 35 | nrow=occ_size, 36 | ncol=n_iov, 37 | byrow=TRUE) 38 | 39 | iov_col[iov_col$OCC == i,attr(pimat,"dimnames")[[1]]] <- iov_mat_i 40 | } 41 | return(iov_col) 42 | } 43 | 44 | # make a single matrix of omega and pi_matrix 45 | merge_covar_matrices <- function(omega_eta=NULL, 46 | omega_dim=NULL, 47 | pimat_dim=NULL, 48 | pimat_kappa=NULL, 49 | dat=NULL){ 50 | matrix_dim <- omega_dim+pimat_dim*(length(unique(dat$OCC))) 51 | all_the_mat <- matrix(0,nrow=matrix_dim,ncol=matrix_dim) 52 | all_the_mat[1:omega_dim,1:omega_dim] <- omega_eta 53 | for (i in unique(dat$OCC)){ 54 | start_pi_mat <- omega_dim+pimat_dim*(i-1)+1 55 | end_pi_mat <- omega_dim+pimat_dim*(i) 56 | all_the_mat[start_pi_mat:end_pi_mat, 57 | start_pi_mat:end_pi_mat] <- pimat_kappa 58 | } 59 | return(all_the_mat) 60 | } 61 | 62 | # create colums to store the estimations of KAPPA 63 | init_iov_col <- function(dat=NULL, 64 | pimat=NULL){ 65 | iov_col <- matrix(0,nrow=nrow(dat),ncol=nrow(pimat)) 66 | iov_col <- data.frame(iov_col,dat$OCC) 67 | names(iov_col) <- c(attr(pimat,"dimnames")[[1]],"OCC") 68 | return(iov_col) 69 | } 70 | 71 | # reshape kappa from wide to long 72 | link_kappa_to_occ <- function(input,pimat_dim,pimat_names){ 73 | current_id <- input[1] 74 | current_occ <- input[2] 75 | start_kappa <- (current_occ*pimat_dim)+1 #+2: after ID and OCC, then -1 76 | end_kappa <- start_kappa+pimat_dim-1 77 | range_kappa <- start_kappa:end_kappa 78 | kappas <- input[range_kappa] 79 | names(kappas) <- pimat_names 80 | return(c(current_id,current_occ,kappas)) 81 | } 82 | -------------------------------------------------------------------------------- /man/poso_estim_mcmc.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/param_estim.R 3 | \name{poso_estim_mcmc} 4 | \alias{poso_estim_mcmc} 5 | \title{Estimate the posterior distribution of individual parameters by MCMC} 6 | \usage{ 7 | poso_estim_mcmc( 8 | dat = NULL, 9 | prior_model = NULL, 10 | return_model = TRUE, 11 | burn_in = 50, 12 | n_iter = 1000, 13 | n_chains = 4, 14 | nocb = FALSE, 15 | control = list(n_kernel = c(2, 2, 2), stepsize_rw = 0.4, proba_mcmc = 0.3, nb_max = 3) 16 | ) 17 | } 18 | \arguments{ 19 | \item{dat}{Dataframe. An individual subject dataset following the 20 | structure of NONMEM/rxode2 event records.} 21 | 22 | \item{prior_model}{A \code{posologyr} prior population pharmacokinetics 23 | model, a list of six objects.} 24 | 25 | \item{return_model}{A boolean. Returns a rxode2 model using the estimated 26 | ETAs if set to \code{TRUE}.} 27 | 28 | \item{burn_in}{Number of burn-in iterations for the Metropolis-Hastings 29 | algorithm.} 30 | 31 | \item{n_iter}{Total number of iterations (following the burn-in iterations) 32 | for each Markov chain of the Metropolis-Hastings algorithm.} 33 | 34 | \item{n_chains}{Number of Markov chains} 35 | 36 | \item{nocb}{A boolean. for time-varying covariates: the next observation 37 | carried backward (nocb) interpolation style, similar to NONMEM. If 38 | \code{FALSE}, the last observation carried forward (locf) style will be used. 39 | Defaults to \code{FALSE}.} 40 | 41 | \item{control}{A list of parameters controlling the Metropolis-Hastings 42 | algorithm.} 43 | } 44 | \value{ 45 | If \code{return_model} is set to \code{FALSE}, a list of one element: a 46 | dataframe \verb{$eta} of ETAs from the posterior distribution, estimated by 47 | Markov Chain Monte Carlo. 48 | If \code{return_model} is set to \code{TRUE}, a list of the dataframe of the posterior 49 | distribution of ETA, and a rxode2 model using the estimated distributions of 50 | ETAs. 51 | } 52 | \description{ 53 | Estimates the posterior distribution of individual parameters by Markov 54 | Chain Monte Carlo (using a Metropolis-Hastings algorithm) 55 | } 56 | \examples{ 57 | # model 58 | mod_run001 <- function() { 59 | ini({ 60 | THETA_Cl <- 4.0 61 | THETA_Vc <- 70.0 62 | THETA_Ka <- 1.0 63 | ETA_Cl ~ 0.2 64 | ETA_Vc ~ 0.2 65 | ETA_Ka ~ 0.2 66 | prop.sd <- sqrt(0.05) 67 | }) 68 | model({ 69 | TVCl <- THETA_Cl 70 | TVVc <- THETA_Vc 71 | TVKa <- THETA_Ka 72 | 73 | Cl <- TVCl*exp(ETA_Cl) 74 | Vc <- TVVc*exp(ETA_Vc) 75 | Ka <- TVKa*exp(ETA_Ka) 76 | 77 | K20 <- Cl/Vc 78 | Cc <- centr/Vc 79 | 80 | d/dt(depot) = -Ka*depot 81 | d/dt(centr) = Ka*depot - K20*centr 82 | Cc ~ prop(prop.sd) 83 | }) 84 | } 85 | # df_patient01: event table for Patient01, following a 30 minutes intravenous 86 | # infusion 87 | df_patient01 <- data.frame(ID=1, 88 | TIME=c(0.0,1.0,14.0), 89 | DV=c(NA,25.0,5.5), 90 | AMT=c(2000,0,0), 91 | EVID=c(1,0,0), 92 | DUR=c(0.5,NA,NA)) 93 | # estimate the posterior distribution of population parameters 94 | \donttest{poso_estim_mcmc(dat=df_patient01,prior_model=mod_run001, 95 | n_iter=50,n_chains=2)} 96 | 97 | } 98 | \references{ 99 | Comets E, Lavenu A, Lavielle M. Parameter estimation in 100 | nonlinear mixed effect models using saemix, an R implementation of the SAEM 101 | algorithm. Journal of Statistical Software 80, 3 (2017), 1-41. 102 | } 103 | \author{ 104 | Emmanuelle Comets, Audrey Lavenu, Marc Lavielle, Cyril Leven 105 | } 106 | -------------------------------------------------------------------------------- /tests/testthat/test_map_mlx.R: -------------------------------------------------------------------------------- 1 | mod_tobramycin_2cpt_fictional <- list( 2 | ppk_model = rxode2::rxode({ 3 | centr(0) = 0; 4 | tTVke = log(THETA_ke)+log(CLCREAT/67.8)*0.89+log(WT/66.4)*(-1.09); 5 | tTVV = log(THETA_V)+log(WT/66.4)*0.80; 6 | tTVk12 = log(THETA_k12); 7 | tTVk21 = log(THETA_k21); 8 | ke = exp(tTVke+ETA_ke); 9 | V = exp(tTVV+ETA_V); 10 | k12 = exp(tTVk12); 11 | k21 = exp(tTVk21); 12 | Cc = centr/V; 13 | d/dt(centr) = - ke*centr - k12*centr + k21*periph; 14 | d/dt(periph) = + k12*centr - k21*periph; 15 | d/dt(AUC) = Cc; 16 | }), 17 | error_model = function(f,sigma){ 18 | g <- sigma[1] + sigma[2]*f 19 | return(g) 20 | }, 21 | theta = c(THETA_ke=0.21, THETA_V=19.8,THETA_k12=0.041, THETA_k21=0.12), 22 | omega = lotri::lotri({ETA_ke + ETA_V + ETA_k12 + ETA_k21 ~ 23 | c(0.08075, 24 | 0 , 0.01203, 25 | 0 , 0 , 0, 26 | 0 , 0 , 0, 0)}), 27 | covariates = c("CLCREAT","WT"), 28 | sigma = c(additive_a = 0, proportional_b = 0.198)) 29 | 30 | mod_vancomycin_2cpt_Goti2018 <- list( 31 | ppk_model = rxode2::rxode({ 32 | centr(0) = 0; 33 | TVCl = THETA_Cl*(CLCREAT/120)^0.8*(0.7^DIAL); 34 | TVVc = THETA_Vc*(WT/70) *(0.5^DIAL); 35 | TVVp = THETA_Vp; 36 | TVQ = THETA_Q; 37 | Cl = TVCl*exp(ETA_Cl); 38 | Vc = TVVc*exp(ETA_Vc); 39 | Vp = TVVp*exp(ETA_Vp); 40 | Q = TVQ; 41 | ke = Cl/Vc; 42 | k12 = Q/Vc; 43 | k21 = Q/Vp; 44 | Cc = centr/Vc; 45 | d/dt(centr) = - ke*centr - k12*centr + k21*periph; 46 | d/dt(periph) = + k12*centr - k21*periph; 47 | d/dt(AUC) = Cc; 48 | }), 49 | error_model = function(f,sigma){ 50 | g <- sigma[1] + sigma[2]*f 51 | return(g) 52 | }, 53 | theta = c(THETA_Cl=4.5, THETA_Vc=58.4, THETA_Vp=38.4,THETA_Q=6.5), 54 | omega = lotri::lotri({ETA_Cl + ETA_Vc + ETA_Vp + ETA_Q ~ 55 | c(0.147, 56 | 0 , 0.510, 57 | 0 , 0, 0.282, 58 | 0 , 0, 0, 0)}), 59 | covariates = c("CLCREAT","WT","DIAL"), 60 | sigma = c(additive_a = 3.4, proportional_b = 0.227)) 61 | 62 | df_patient01_tobra <- data.frame(ID=1,TIME=c(0.0,1.0,14.0), 63 | DV=c(NA,25.0,5.5), 64 | AMT=c(500,0,0), 65 | DUR=c(0.5,NA,NA), 66 | EVID=c(1,0,0), 67 | CLCREAT=80,WT=65) 68 | 69 | df_patient02_vanco <- data.frame(ID=1,TIME=c(0.0,12.0,22.2,37.5), 70 | DV=c(NA,14.8,NA,22.5), 71 | AMT=c(1900,0,1750,0), 72 | DUR=c(1,NA,1,NA), 73 | EVID=c(1,0,1,0), 74 | CLCREAT=34,WT=62,DIAL=0) 75 | 76 | patient01_tobra_map <- poso_estim_map(dat=df_patient01_tobra, 77 | prior_model=mod_tobramycin_2cpt_fictional, 78 | return_model=TRUE) 79 | 80 | patient02_vanco_map <- poso_estim_map(dat=df_patient02_vanco, 81 | prior_model=mod_vancomycin_2cpt_Goti2018, 82 | return_model=TRUE) 83 | 84 | test_that("MAP estimates match Monolix MAP estimates", { 85 | expect_equal(patient01_tobra_map$model$ke[1], 0.1258, tolerance=1e-3) 86 | expect_equal(patient01_tobra_map$model$V[1], 18.21, tolerance=1e-2) 87 | expect_equal(patient02_vanco_map$model$Cl[1], 1.72, tolerance=1e-2) 88 | expect_equal(patient02_vanco_map$model$Vc[1], 59.8, tolerance=1e-2) 89 | expect_equal(patient02_vanco_map$model$Vp[1], 41.6, tolerance=1e-2) 90 | }) 91 | -------------------------------------------------------------------------------- /R/input_validation.R: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------- 2 | # posologyr: individual dose optimization using population PK 3 | # Copyright (C) Cyril Leven 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Affero General Public License as 7 | # published by the Free Software Foundation, either version 3 of the 8 | # License, or (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU Affero General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Affero General Public License 16 | # along with this program. If not, see . 17 | #------------------------------------------------------------------------- 18 | 19 | validate_dat <- function(tdm_data){ 20 | if (is.null(tdm_data$TIME)) stop("TIME is missing from the patient record") 21 | if (is.null(tdm_data$EVID)) stop("EVID is missing from the patient record") 22 | if (is.null(tdm_data$AMT)) stop("AMT is missing from the patient record") 23 | if (is.null(tdm_data$DV)) stop("DV is missing from the patient record") 24 | } 25 | 26 | validate_priormod <- function(priormod){ 27 | if (is.null(priormod$ppk_model)){ 28 | stop("ppk_model is missing from the prior posologyr model")} 29 | if (is.null(priormod$error_model)){ 30 | stop("error_model is missing from the prior posologyr model")} 31 | if (is.null(priormod$theta)){ 32 | stop("theta is missing from the prior posologyr model")} 33 | if (is.null(priormod$omega)){ 34 | stop("omega is missing from the prior posologyr model")} 35 | if (is.null(priormod$sigma)){ 36 | stop("sigma is missing from the prior posologyr model")} 37 | 38 | # ETA == 0 are not needed in ppk_model$params, only check for ETA > 0 39 | ind_eta <- which(diag(priormod$omega)>0) 40 | omega_eta <- priormod$omega[ind_eta,ind_eta] 41 | 42 | if (FALSE %in% (attr(omega_eta,"dimnames")[[1]] %in% 43 | priormod$ppk_model$params)){ 44 | stop("The names of the omega matrix do not match the parameters of 45 | ppk_model") 46 | } 47 | if (FALSE %in% (attr(priormod$theta,"names") %in% priormod$ppk_model$params)){ 48 | stop("The names of the theta vector do not match the parameters of 49 | ppk_model") 50 | } 51 | } 52 | 53 | check_for_iov <- function(object){ 54 | if (is.null(object$tdm_data$OCC) & !is.null(object$pi_matrix)){ 55 | stop("OCC is missing from the patient record") 56 | } else if (is.null(object$tdm_data$OCC) | is.null(object$pi_matrix)){ 57 | estim_with_iov <- FALSE 58 | } else { 59 | estim_with_iov <- TRUE 60 | } 61 | return(estim_with_iov) 62 | } 63 | 64 | get_endpoints <- function(object){ 65 | if (any(class(object$sigma) == "list",class(object$error_model) == "list")) { 66 | if (is.null(object$tdm_data$DVID)){ 67 | stop("DVID is missing from the patient record") 68 | } 69 | if (any(!is.null(names(object$sigma)),!is.null(names(object$error_model)))){ 70 | if (!setequal(names(object$sigma),names(object$error_model))){ 71 | stop("The names of the sigma matrices do not match the names of the 72 | error models") 73 | } 74 | if (FALSE %in% ((unique(object$tdm_data$DVID) %in% names(object$sigma)))){ 75 | stop("The observation types in DVID do not match the names of the 76 | error models") 77 | } 78 | } else { 79 | stop("The sigma and error models lists must be named lists, with names 80 | matching the DVID column from the patient record")} 81 | endpoints <- names(object$sigma) 82 | } else { 83 | endpoints <- "Cc" 84 | } 85 | return(endpoints) 86 | } 87 | -------------------------------------------------------------------------------- /vignettes/articles/multiple_endpoints.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Multiple endpoints" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Multiple endpoints} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set( 12 | collapse = TRUE, 13 | comment = "#>" 14 | ) 15 | set.seed(1) 16 | library(rxode2) 17 | setRxThreads(2L) # limit the number of threads 18 | ``` 19 | 20 | ```{r setup} 21 | library(posologyr) 22 | ``` 23 | 24 | # Introduction 25 | A different error model can be defined for multiple endpoints models (eg. 26 | PK-PD, parent-metabolite, blood-urine...). 27 | 28 | An example can be seen below, utilizing the warfarin data and model (provided by Tomoo Funaki and Nick Holford) from the nlmixr documentation (https://nlmixr2.org/articles/multiple-endpoints.html). 29 | 30 | ## warfarin PKPD model 31 | 32 | ```{r} 33 | mod_warfarin_nlmixr <- function() { 34 | ini({ 35 | #Fixed effects: population estimates 36 | THETA_ktr=0.106 37 | THETA_ka=-0.087 38 | THETA_cl=-2.03 39 | THETA_v=2.07 40 | THETA_emax=3.4 41 | THETA_ec50=0.00724 42 | THETA_kout=-2.9 43 | THETA_e0=4.57 44 | 45 | #Random effects: inter-individual variability 46 | ETA_ktr ~ 1.024695 47 | ETA_ka ~ 0.9518403 48 | ETA_cl ~ 0.5300943 49 | ETA_v ~ 0.4785394 50 | ETA_emax ~ 0.7134424 51 | ETA_ec50 ~ 0.7204165 52 | ETA_kout ~ 0.3563706 53 | ETA_e0 ~ 0.2660827 54 | 55 | #Unexplained residual variability 56 | cp.sd <- 0.144 57 | cp.prop.sd <- 0.15 58 | pca.sd <- 3.91 59 | }) 60 | model({ 61 | #Individual model and covariates 62 | ktr <- exp(THETA_ktr + ETA_ktr) 63 | ka <- exp(THETA_ka + ETA_ka) 64 | cl <- exp(THETA_cl + ETA_cl) 65 | v <- exp(THETA_v + ETA_v) 66 | emax = expit(THETA_emax + ETA_emax) 67 | ec50 = exp(THETA_ec50 + ETA_ec50) 68 | kout = exp(THETA_kout + ETA_kout) 69 | e0 = exp(THETA_e0 + ETA_e0) 70 | 71 | #Structural model defined using ordinary differential equations (ODE) 72 | DCP = center/v 73 | PD=1-emax*DCP/(ec50+DCP) 74 | 75 | effect(0) = e0 76 | kin = e0*kout 77 | 78 | d/dt(depot) = -ktr * depot 79 | d/dt(gut) = ktr * depot -ka * gut 80 | d/dt(center) = ka * gut - cl / v * center 81 | d/dt(effect) = kin*PD -kout*effect 82 | 83 | cp = center / v 84 | pca = effect 85 | 86 | #Model for unexplained residual variability 87 | cp ~ add(cp.sd) + prop(cp.prop.sd) 88 | pca ~ add(pca.sd) 89 | }) 90 | } 91 | 92 | mod_warfarin_nlmixr <- mod_warfarin_nlmixr() 93 | ``` 94 | 95 | ## data: first subject from the warfarin dataset 96 | 97 | ```{r} 98 | warf_01 <- data.frame(ID=1, 99 | TIME=c(0.0,1.0,3.0,6.0,24.0,24.0,36.0,36.0,48.0,48.0,72.0,72.0,144.0), 100 | DV=c(0.0,1.9,6.6,10.8,5.6,44.0,4.0,27.0,2.7,28.0,0.8,31.0,71.0), 101 | DVID=c("cp","cp","cp","cp","cp","pca","cp","pca","cp","pca","cp","pca","pca"), 102 | EVID=c(1,0,0,0,0,0,0,0,0,0,0,0,0), 103 | AMT=c(100,0,0,0,0,0,0,0,0,0,0,0,0)) 104 | warf_01 105 | ``` 106 | 107 | posologyr can compute the EBE for the combined PKPD model with `poso_estim_map()` 108 | 109 | ```{r} 110 | map_warf_01 <- poso_estim_map(warf_01,mod_warfarin_nlmixr) 111 | map_warf_01 112 | ``` 113 | 114 | The observation/time curves for both endpoints can also be plotted 115 | 116 | ```{r} 117 | #| fig.alt: > 118 | #| Plot of the individual PK profile of warfarin 119 | plot(map_warf_01$model,"cp") 120 | ``` 121 | 122 | 123 | ```{r} 124 | #| fig.alt: > 125 | #| Plot of the individual PD profile of warfarin 126 | plot(map_warf_01$model,"pca") 127 | ``` 128 | -------------------------------------------------------------------------------- /docs/deps/headroom-0.11.0/headroom.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * headroom.js v0.11.0 - Give your page some headroom. Hide your header until you need it 3 | * Copyright (c) 2020 Nick Williams - http://wicky.nillia.ms/headroom.js 4 | * License: MIT 5 | */ 6 | 7 | !function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(t=t||self).Headroom=n()}(this,function(){"use strict";function t(){return"undefined"!=typeof window}function d(t){return function(t){return t&&t.document&&function(t){return 9===t.nodeType}(t.document)}(t)?function(t){var n=t.document,o=n.body,s=n.documentElement;return{scrollHeight:function(){return Math.max(o.scrollHeight,s.scrollHeight,o.offsetHeight,s.offsetHeight,o.clientHeight,s.clientHeight)},height:function(){return t.innerHeight||s.clientHeight||o.clientHeight},scrollY:function(){return void 0!==t.pageYOffset?t.pageYOffset:(s||o.parentNode||o).scrollTop}}}(t):function(t){return{scrollHeight:function(){return Math.max(t.scrollHeight,t.offsetHeight,t.clientHeight)},height:function(){return Math.max(t.offsetHeight,t.clientHeight)},scrollY:function(){return t.scrollTop}}}(t)}function n(t,s,e){var n,o=function(){var n=!1;try{var t={get passive(){n=!0}};window.addEventListener("test",t,t),window.removeEventListener("test",t,t)}catch(t){n=!1}return n}(),i=!1,r=d(t),l=r.scrollY(),a={};function c(){var t=Math.round(r.scrollY()),n=r.height(),o=r.scrollHeight();a.scrollY=t,a.lastScrollY=l,a.direction=ls.tolerance[a.direction],e(a),l=t,i=!1}function h(){i||(i=!0,n=requestAnimationFrame(c))}var u=!!o&&{passive:!0,capture:!1};return t.addEventListener("scroll",h,u),c(),{destroy:function(){cancelAnimationFrame(n),t.removeEventListener("scroll",h,u)}}}function o(t,n){n=n||{},Object.assign(this,o.options,n),this.classes=Object.assign({},o.options.classes,n.classes),this.elem=t,this.tolerance=function(t){return t===Object(t)?t:{down:t,up:t}}(this.tolerance),this.initialised=!1,this.frozen=!1}return o.prototype={constructor:o,init:function(){return o.cutsTheMustard&&!this.initialised&&(this.addClass("initial"),this.initialised=!0,setTimeout(function(t){t.scrollTracker=n(t.scroller,{offset:t.offset,tolerance:t.tolerance},t.update.bind(t))},100,this)),this},destroy:function(){this.initialised=!1,Object.keys(this.classes).forEach(this.removeClass,this),this.scrollTracker.destroy()},unpin:function(){!this.hasClass("pinned")&&this.hasClass("unpinned")||(this.addClass("unpinned"),this.removeClass("pinned"),this.onUnpin&&this.onUnpin.call(this))},pin:function(){this.hasClass("unpinned")&&(this.addClass("pinned"),this.removeClass("unpinned"),this.onPin&&this.onPin.call(this))},freeze:function(){this.frozen=!0,this.addClass("frozen")},unfreeze:function(){this.frozen=!1,this.removeClass("frozen")},top:function(){this.hasClass("top")||(this.addClass("top"),this.removeClass("notTop"),this.onTop&&this.onTop.call(this))},notTop:function(){this.hasClass("notTop")||(this.addClass("notTop"),this.removeClass("top"),this.onNotTop&&this.onNotTop.call(this))},bottom:function(){this.hasClass("bottom")||(this.addClass("bottom"),this.removeClass("notBottom"),this.onBottom&&this.onBottom.call(this))},notBottom:function(){this.hasClass("notBottom")||(this.addClass("notBottom"),this.removeClass("bottom"),this.onNotBottom&&this.onNotBottom.call(this))},shouldUnpin:function(t){return"down"===t.direction&&!t.top&&t.toleranceExceeded},shouldPin:function(t){return"up"===t.direction&&t.toleranceExceeded||t.top},addClass:function(t){this.elem.classList.add.apply(this.elem.classList,this.classes[t].split(" "))},removeClass:function(t){this.elem.classList.remove.apply(this.elem.classList,this.classes[t].split(" "))},hasClass:function(t){return this.classes[t].split(" ").every(function(t){return this.classList.contains(t)},this.elem)},update:function(t){t.isOutOfBounds||!0!==this.frozen&&(t.top?this.top():this.notTop(),t.bottom?this.bottom():this.notBottom(),this.shouldUnpin(t)?this.unpin():this.shouldPin(t)&&this.pin())}},o.options={tolerance:{up:0,down:0},offset:0,scroller:t()?window:null,classes:{frozen:"headroom--frozen",pinned:"headroom--pinned",unpinned:"headroom--unpinned",top:"headroom--top",notTop:"headroom--not-top",bottom:"headroom--bottom",notBottom:"headroom--not-bottom",initial:"headroom"}},o.cutsTheMustard=!!(t()&&function(){}.bind&&"classList"in document.documentElement&&Object.assign&&Object.keys&&requestAnimationFrame),o}); -------------------------------------------------------------------------------- /R/ofv.R: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------- 2 | # posologyr: individual dose optimization using population PK 3 | # Copyright (C) Cyril Leven 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Affero General Public License as 7 | # published by the Free Software Foundation, either version 3 of the 8 | # License, or (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU Affero General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Affero General Public License 16 | # along with this program. If not, see . 17 | #------------------------------------------------------------------------- 18 | 19 | # Update model predictions with a new set of parameters, for all obs 20 | run_model <- function(x,solved_model=NULL,estim_with_iov=NULL,endpoints=NULL){ 21 | if (!estim_with_iov){ #rxode2 already updated in errpred() if estim_with_iov 22 | solved_model$params <- x 23 | } 24 | return(solved_model[endpoints]) 25 | } 26 | 27 | # Objective function for the Empirical Bayes Estimates 28 | # doi: 10.4196/kjpp.2012.16.2.97 29 | objective_function <- function(y_obs=NULL,f=NULL,g=NULL, 30 | eta=NULL,solve_omega=NULL){ 31 | 32 | # 1) When the prediction f is zero, g can be zero (depending on the residual 33 | # error model). 34 | # 2) log(0) is NaN, the limit of log(x) when x approaches zero is -Inf, 35 | # 3) log(1) is zero, and 1^2 is 1 36 | g[which(g == 0)] <- 1 37 | 38 | U_y <- sum(((y_obs - f)/g)^2 + log(g^2)) 39 | 40 | # the transpose of a diagonal matrix is itself 41 | U_eta <- eta %*% solve_omega %*% eta 42 | 43 | if (TRUE %in% is.na(f)){ 44 | # if rxode2 fails to solve the model, the proposed ETA is not optimal, 45 | # assign a large value to OFV to divert the algorithm from this area 46 | OFV <- 10^10 47 | } else { 48 | OFV <- U_y + U_eta 49 | } 50 | 51 | return(OFV) 52 | } 53 | 54 | # Prediction error to optimize for MAP-EBE 55 | errpred <- function(eta_estim=NULL, 56 | run_model=NULL, 57 | y_obs=NULL, 58 | endpoints=NULL, 59 | theta=NULL, 60 | ind_eta=NULL, 61 | sigma=NULL, 62 | solve_omega=NULL, 63 | omega=NULL, 64 | omega_dim=NULL, 65 | iov_col=NULL, 66 | pimat=NULL, 67 | dat=NULL, 68 | solved_model=NULL, 69 | error_model=NULL, 70 | estim_with_iov=NULL, 71 | interpolation=NULL){ 72 | 73 | eta <- diag(omega)*0 74 | 75 | if (estim_with_iov){ 76 | eta[ind_eta] <- eta_estim[1:omega_dim] 77 | iov_col <- iov_proposition_as_cols(iov_col=iov_col,dat=dat,pimat=pimat, 78 | omega_dim=omega_dim, 79 | eta_estim=eta_estim) 80 | dat <- data.frame(dat,iov_col) 81 | solved_model <- rxode2::rxSolve(solved_model,c(theta,eta),dat, 82 | covsInterpolation=interpolation) 83 | } else { 84 | eta[ind_eta] <- eta_estim 85 | } 86 | #simulated concentrations with the proposed eta estimates 87 | f_all_endpoints <- do.call(run_model,list(c(theta,eta), 88 | solved_model=solved_model, 89 | estim_with_iov=estim_with_iov, 90 | endpoints=endpoints)) 91 | 92 | obs_res <- residual_error_all_endpoints(f_all_endpoints=f_all_endpoints, 93 | y_obs=y_obs, 94 | error_model=error_model, 95 | sigma=sigma, 96 | endpoints=endpoints) 97 | 98 | optimize_me <- objective_function(y_obs=y_obs[,"DV"], 99 | f=obs_res$f_all_endpoints$f, 100 | g=obs_res$g_all_endpoints$g, 101 | eta=eta_estim, 102 | solve_omega=solve_omega) 103 | return(optimize_me) 104 | } 105 | -------------------------------------------------------------------------------- /vignettes/articles/patient_data.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Patient data" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Patient data} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set( 12 | collapse = TRUE, 13 | comment = "#>" 14 | ) 15 | ``` 16 | 17 | # Introduction 18 | This describes the structure of patient records compatible with `posologyr`. 19 | 20 | # Structure 21 | Data for input into `posologyr` is the same type of data input for rxode2. As stated in the [rxode2 documentation (rxode2 datasets)](https://nlmixr2.github.io/rxode2/articles/rxode2-datasets.html), it is also similar to [data for NONMEM](https://doi.org/10.1002/psp4.12404). 22 | 23 | The patient dataset is a table of sequential event records, in which each line is an event. A description of the different event types is available in the [rxode2 documentation (rxode2 Event Types)](https://nlmixr2.github.io/rxode2/articles/rxode2-event-types.html). 24 | 25 | Below is a minimal working example: 26 | 27 | ```{r minimal_patient_df} 28 | data.frame(ID=1, 29 | TIME=c(0.0,3), 30 | DV=c(NA,60.0), 31 | AMT=c(1000,0), 32 | EVID=c(101,0)) 33 | ``` 34 | 35 | ## Required fields and data 36 | 37 | TIME 38 | : Dosing times, and sampling times of therapeutic drug monitoring (TDM). The units depend on the specification of the population pharmacokinetics (ppk) model. 39 | 40 | AMT 41 | : Amount of drug administered. The units depend on the specification of the ppk model. 42 | 43 | EVID 44 | : Event type. Must be 0 for all observations (concentrations from TDM). 45 | 46 | DV 47 | : For concentrations. Must be NA when EVID is not 0. 48 | 49 | Covariates 50 | : Every covariate defined in the prior `posologyr` model. The column names must match the **covariate** vector from the ppk model. 51 | 52 | OCC 53 | : Occasions. Required for models with inter-occasion variability. 54 | 55 | DVID 56 | : Observation type. Required for models with multiple endpoints. 57 | 58 | CMT 59 | : Name (or number) of the compartment where the dose is administered, see `vignette("route_of_administration")`. 60 | 61 | # Common use cases 62 | ## A priori dose adjustment 63 | Before dosing: the simplest patient record is a single line dataframe, with individual patient covariates, and all other columns (TIME, DV, AMT, EVID) set to zero. 64 | 65 | ```{r before_dosing_df} 66 | data.frame(ID=1, 67 | TIME=0, 68 | DV=0, 69 | AMT=0, 70 | EVID=0, 71 | COVAR1=c("X"), 72 | COVAR2=c("Y")) 73 | ``` 74 | 75 | ## Oral administration or IV bolus 76 | `EVID = 1` for an instantaneous administration in the first compartment defined in the ppk model: either the central compartment for an IV bolus, or a depot compartment for an oral administration. 77 | 78 | ```{r oral_IV_bolus_df} 79 | data.frame(ID=1, 80 | TIME=c(0.0,3), 81 | DV=c(NA,60.0), 82 | AMT=c(1000,0), 83 | EVID=c(1,0), 84 | COVAR1=c("X"), 85 | COVAR2=c("Y")) 86 | ``` 87 | 88 | ## Intermittent infusion 89 | `EVID = 1` for a bolus infusion, administered in the first compartment defined in the ppk model. 90 | 91 | `DUR` defines its duration. 92 | 93 | `AMT` is the amount administered over the duration `DUR`. 94 | 95 | ```{r intermittent_infusion_df} 96 | data.frame(ID=1, 97 | TIME=c(0.0,1.0,14.0), 98 | DV=c(NA,25.0,5.5), 99 | AMT=c(1000,0,0), 100 | DUR=c(0.5,NA,NA), 101 | EVID=c(1,0,0), 102 | COVAR1=c("X"), 103 | COVAR2=c("Y")) 104 | ``` 105 | 106 | ## Inter-occasion variability 107 | For a given occasion, the value of `OCC` must be repeated for each row. `OCC` must be specified for all the rows in the table. 108 | 109 | ```{r iov_df} 110 | data.frame(ID=1, 111 | TIME=c(0.0,1.0,14.0,24.0,25.0,36.0), 112 | DV=c(NA,25.0,5.5,NA,30.0,6.0), 113 | AMT=c(1000,0,0,1000,0,0), 114 | DUR=c(0.5,NA,NA,0.5,NA,NA), 115 | EVID=c(1,0,0,1,0,0), 116 | OCC=c(1,1,1,2,2,2), 117 | COVAR1=c("X"), 118 | COVAR2=c("Y")) 119 | ``` 120 | 121 | ## Multiple endpoints 122 | `DVID` is used to specify the type of each observation. The values of `DVID` in the dataset must match the names of the residual error models, see `vignette("multiple_endpoints")`. 123 | 124 | ```{r endpoints} 125 | data.frame(ID=1, 126 | TIME=c(0.0,1.0,14.0,24.0,25.0,36.0), 127 | DV=c(NA,20.0,80,35.5,60.0,40.0), 128 | AMT=c(1000,0,0,0,0,0), 129 | EVID=c(1,0,0,0,0,0), 130 | DVID=c("parent","parent","metabolite","parent","metabolite","metabolite"), 131 | COVAR1=c("X"), 132 | COVAR2=c("Y")) 133 | ``` 134 | 135 | -------------------------------------------------------------------------------- /man/poso_inter_cmin.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/dosing_optim.R 3 | \name{poso_inter_cmin} 4 | \alias{poso_inter_cmin} 5 | \title{Estimate the optimal dosing interval to consistently achieve a target trough 6 | concentration (Cmin)} 7 | \usage{ 8 | poso_inter_cmin( 9 | dat = NULL, 10 | prior_model = NULL, 11 | dose, 12 | target_cmin, 13 | cmt_dose = 1, 14 | endpoint = "Cc", 15 | estim_method = "map", 16 | nocb = FALSE, 17 | p = NULL, 18 | greater_than = TRUE, 19 | starting_interval = 12, 20 | add_dose = 10, 21 | duration = 0, 22 | indiv_param = NULL 23 | ) 24 | } 25 | \arguments{ 26 | \item{dat}{Dataframe. An individual subject dataset following the 27 | structure of NONMEM/rxode2 event records.} 28 | 29 | \item{prior_model}{A \code{posologyr} prior population pharmacokinetics 30 | model, a list of six objects.} 31 | 32 | \item{dose}{Numeric. The dose given.} 33 | 34 | \item{target_cmin}{Numeric. Target trough concentration (Cmin).} 35 | 36 | \item{cmt_dose}{Character or numeric. The compartment in which the dose is 37 | to be administered. Must match one of the compartments in the prior model. 38 | Defaults to 1.} 39 | 40 | \item{endpoint}{Character. The endpoint of the prior model to be optimised 41 | for. The default is "Cc", which is the central concentration.} 42 | 43 | \item{estim_method}{A character string. An estimation method to be used for 44 | the individual parameters. The default method "map" is the Maximum A 45 | Posteriori estimation, the method "prior" simulates from the prior 46 | population model, and "sir" uses the Sequential Importance Resampling 47 | algorithm to estimate the a posteriori distribution of the individual 48 | parameters. This argument is ignored if \code{indiv_param} is provided.} 49 | 50 | \item{nocb}{A boolean. for time-varying covariates: the next observation 51 | carried backward (nocb) interpolation style, similar to NONMEM. If 52 | \code{FALSE}, the last observation carried forward (locf) style will be used. 53 | Defaults to \code{FALSE}.} 54 | 55 | \item{p}{Numeric. The proportion of the distribution of concentrations to 56 | consider for the optimization. Mandatory for \code{estim_method=sir}.} 57 | 58 | \item{greater_than}{A boolean. If \code{TRUE}: targets a dose leading to a 59 | proportion \code{p} of the concentrations to be greater than \code{target_conc}. 60 | Respectively, lower if \code{FALSE}.} 61 | 62 | \item{starting_interval}{Numeric. Starting inter-dose interval for 63 | the optimization algorithm.} 64 | 65 | \item{add_dose}{Numeric. Additional doses administered at 66 | inter-dose interval after the first dose.} 67 | 68 | \item{duration}{Numeric. Duration of infusion, for zero-order 69 | administrations.} 70 | 71 | \item{indiv_param}{Optional. A set of individual parameters : THETA, 72 | estimates of ETA, and covariates.} 73 | } 74 | \value{ 75 | A list containing the following components: 76 | \describe{ 77 | \item{interval}{Numeric. An inter-dose interval to reach the target trough 78 | concentration before each dosing of a multiple dose regimen.} 79 | \item{type_of_estimate}{Character string. The type of estimate of the 80 | individual parameters. Either a point estimate, or a distribution.} 81 | \item{conc_estimate}{A vector of numeric estimates of the conc. Either a 82 | single value (for a point estimate of ETA), or a distribution.} 83 | \item{indiv_param}{A \code{data.frame}. The set of individual parameters used 84 | for the determination of the optimal dose : THETA, estimates of ETA, and 85 | covariates} 86 | } 87 | } 88 | \description{ 89 | Estimates the optimal dosing interval to consistently achieve a target Cmin, 90 | given a dose, a population pharmacokinetic model, a set of individual 91 | parameters, and a target concentration. 92 | } 93 | \examples{ 94 | rxode2::setRxThreads(2L) # limit the number of threads 95 | 96 | # model 97 | mod_run001 <- function() { 98 | ini({ 99 | THETA_Cl <- 4.0 100 | THETA_Vc <- 70.0 101 | THETA_Ka <- 1.0 102 | ETA_Cl ~ 0.2 103 | ETA_Vc ~ 0.2 104 | ETA_Ka ~ 0.2 105 | prop.sd <- sqrt(0.05) 106 | }) 107 | model({ 108 | TVCl <- THETA_Cl 109 | TVVc <- THETA_Vc 110 | TVKa <- THETA_Ka 111 | 112 | Cl <- TVCl*exp(ETA_Cl) 113 | Vc <- TVVc*exp(ETA_Vc) 114 | Ka <- TVKa*exp(ETA_Ka) 115 | 116 | K20 <- Cl/Vc 117 | Cc <- centr/Vc 118 | 119 | d/dt(depot) = -Ka*depot 120 | d/dt(centr) = Ka*depot - K20*centr 121 | Cc ~ prop(prop.sd) 122 | }) 123 | } 124 | # df_patient01: event table for Patient01, following a 30 minutes intravenous 125 | # infusion 126 | df_patient01 <- data.frame(ID=1, 127 | TIME=c(0.0,1.0,14.0), 128 | DV=c(NA,25.0,5.5), 129 | AMT=c(2000,0,0), 130 | EVID=c(1,0,0), 131 | DUR=c(0.5,NA,NA)) 132 | # estimate the optimal interval to reach a cmin of of 2.5 mg/l 133 | # before each administration 134 | poso_inter_cmin(dat=df_patient01,prior_model=mod_run001, 135 | dose=1500,duration=0.5,target_cmin=2.5) 136 | 137 | } 138 | -------------------------------------------------------------------------------- /vignettes/articles/route_of_administration.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Route of administration" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Route of administration} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set( 12 | collapse = TRUE, 13 | comment = "#>" 14 | ) 15 | set.seed(1) 16 | library(rxode2) 17 | setRxThreads(2L) # limit the number of threads 18 | ``` 19 | 20 | ```{r setup} 21 | library(posologyr) 22 | ``` 23 | 24 | # Introduction 25 | The Caldès 2009 ganciclovir model (https://doi.org/10.1128/aac.00085-09) is capable of describing the pharmacokinetics of either injectable ganciclovir or oral valganciclovir. 26 | 27 | ```{r model} 28 | mod_ganciclovir_Caldes_2009 <- function() { 29 | ini({ 30 | THETA_cl <- 7.49 31 | THETA_v1 <- 31.90 32 | THETA_cld <- 10.20 33 | THETA_v2 <- 32.0 34 | THETA_ka <- 0.895 35 | THETA_baf <- 0.825 36 | ETA_cl ~ 0.107 37 | ETA_v1 ~ 0.227 38 | ETA_ka ~ 0.464 39 | ETA_baf ~ 0.049 40 | add.sd <- 0.465 41 | prop.sd <- 0.143 42 | }) 43 | model({ 44 | TVcl = THETA_cl*(ClCr/57); 45 | TVv1 = THETA_v1; 46 | TVcld = THETA_cld; 47 | TVv2 = THETA_v2; 48 | TVka = THETA_ka; 49 | TVbaf = THETA_baf; 50 | 51 | cl = TVcl*exp(ETA_cl); 52 | v1 = TVv1*exp(ETA_v1); 53 | cld = TVcld; 54 | v2 = TVv2; 55 | ka = TVka*exp(ETA_ka); 56 | baf = TVbaf*exp(ETA_baf); 57 | 58 | k10 = cl/v1; 59 | k12 = cld / v1; 60 | k21 = cld / v2; 61 | Cc = centr/v1; 62 | 63 | d/dt(depot) = -ka*depot 64 | d/dt(centr) = ka*depot - k10*centr - k12*centr + k21*periph; 65 | d/dt(periph) = k12*centr - k21*periph; 66 | d/dt(AUC) = Cc; 67 | 68 | f(depot)=baf; 69 | alag(depot)=0.382; 70 | 71 | Cc ~ add(add.sd) + prop(prop.sd) + combined1() 72 | }) 73 | } 74 | 75 | mod_ganciclovir_Caldes_2009 <- mod_ganciclovir_Caldes_2009() 76 | ``` 77 | 78 | # Intravenous ganciclovir 79 | 80 | ## Patient record with TDM data 81 | 82 | To describe intravenous administration, a CMT column has been added to the TDM data table to indicate administrations directly into the central compartment. 83 | 84 | Note: to compute the AUC between the last dose and the time of the last dose + 24 hours, a dummy dose of 0 mg is added to the time of the last observation of interest (i.e. H144). 85 | 86 | ```{r tdm_patientA} 87 | patient <- data.frame(ID=1,TIME=c(0,121,122,126,144), 88 | DV=c(NA,10.8,5.8,3.3,NA), 89 | ADDL=c(5,0,0,0,0), 90 | II=c(24,0,0,0,0), 91 | EVID=c(1,0,0,0,1), 92 | CMT=c("centr",NA,NA,NA,"centr"), 93 | AMT=c(250,0,0,0,0), 94 | DUR=c(0.5,NA,NA,NA,NA), 95 | ClCr=25) 96 | patient 97 | ``` 98 | 99 | ## Individual PK profile and AUC 0-24 100 | 101 | The individual PK profile can be estimated, and plotted. 102 | 103 | ```{r estim_map} 104 | map_patient <- poso_estim_map(patient,mod_ganciclovir_Caldes_2009) 105 | ``` 106 | 107 | ```{r plot_map} 108 | #| fig.alt: > 109 | #| Plot of the individual PK profile 110 | plot(map_patient$model,Cc) 111 | ``` 112 | 113 | The difference between the cumulative AUC at H144 and that at H120 gives the AUC 0-24 after the last dose. Using data.table is optional, but the syntax is more convenient. 114 | 115 | ```{r auc_24_ganci} 116 | library(data.table) 117 | data.table(map_patient$model)[time==144,AUC] - 118 | data.table(map_patient$model)[time==120,AUC] 119 | ``` 120 | 121 | ## Optimal dose for an intravenous ganciclovir injection 122 | 123 | The optimal dose to achieve an AUC of 50 mg.h/L can be determined for a new injection of IV ganciclovir by setting `cmt_dose = "centr"`. 124 | 125 | ```{r optimal_intravenous_ganci} 126 | poso_dose_auc(patient,mod_ganciclovir_Caldes_2009,tdm=TRUE, 127 | time_dose = 145, 128 | duration = 1, 129 | time_auc = 24, 130 | target_auc = 50, 131 | cmt_dose = "centr") 132 | ``` 133 | 134 | ## Optimal dose for an oral valganciclovir administration 135 | 136 | The optimal dose to achieve an AUC of 50 mg.h/L can be determined for an administration of oral valganciclovir by setting `cmt_dose = "depot"`. 137 | 138 | ```{r optimal_oral_valganci} 139 | poso_dose_auc(patient,mod_ganciclovir_Caldes_2009,tdm=TRUE, 140 | time_dose = 145, 141 | time_auc = 24, 142 | target_auc = 50, 143 | cmt_dose = "depot") 144 | ``` 145 | Keeping the default value of cmt_dose, which is the first compartment declared in the PK model, would also work here. 146 | 147 | > **Note** in this case the estimated dose should be corrected by a factor of 1/0.72 as the Caldès 2009 paper states: 148 | > 149 | > 150 | >*"As NONMEM estimated the pharmacokinetic parameters of ganciclovir, valganciclovir doses were converted to their equivalent ganciclovir content by multiplying the valganciclovir dose by 0.720 (corresponding to the ratio between the molecular weights of ganciclovir and valganciclovir)."* 151 | -------------------------------------------------------------------------------- /vignettes/articles/a_posteriori_dosing.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "A posteriori dose selection" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{A posteriori dose selection} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set( 12 | collapse = TRUE, 13 | comment = "#>" 14 | ) 15 | set.seed(1) 16 | library(rxode2) 17 | setRxThreads(2L) # limit the number of threads 18 | ``` 19 | 20 | ```{r setup} 21 | library(posologyr) 22 | ``` 23 | 24 | # Introduction 25 | Dosage individualization for a critical care patient treated with amikacin for suspected ventilator-associated pneumonia, using the population pharmacokinetic (ppk) model of Burdet et al. 2015, using the data from therapeutic drug monitoring (TDM). 26 | 27 | ```{r model} 28 | mod_amikacin_Burdet2015 <- function() { 29 | ini({ 30 | THETA_Cl=4.3 31 | THETA_Vc=15.9 32 | THETA_Vp=21.4 33 | THETA_Q=12.1 34 | ETA_Cl + ETA_Vc + ETA_Vp + ETA_Q ~ 35 | c(0.1, 36 | 0.01 , 0.05 , 37 | 0.01 , 0.02 , 0.2 , 38 | -0.06 , 0.004, 0.003, 0.08) 39 | add_sd <- 0.2 40 | prop_sd <- 0.1 41 | }) 42 | model({ 43 | TVCl = THETA_Cl*(CLCREAT4H/82)^0.7 44 | TVVc = THETA_Vc*(TBW/78)^0.9*(PoverF/169)^0.4 45 | TVVp = THETA_Vp 46 | TVQ = THETA_Q 47 | Cl = TVCl*exp(ETA_Cl) 48 | Vc = TVVc*exp(ETA_Vc) 49 | Vp = TVVp*exp(ETA_Vp) 50 | Q = TVQ *exp(ETA_Q) 51 | ke = Cl/Vc 52 | k12 = Q/Vc 53 | k21 = Q/Vp 54 | Cp = centr/Vc 55 | d/dt(centr) = - ke*centr - k12*centr + k21*periph 56 | d/dt(periph) = + k12*centr - k21*periph 57 | 58 | Cp ~ add(add_sd) + prop(prop_sd) + combined1() 59 | }) 60 | } 61 | 62 | mod_amikacin_Burdet2015 <- mod_amikacin_Burdet2015() 63 | ``` 64 | 65 | # A posteriori dose selection 66 | 67 | ## Patient record with TDM data 68 | 69 | After the first administration, the dosage selection can be refined using the results of TDM. See `vignette("patient_data_input")` for more details regarding the patient record. 70 | 71 | ```{r tdm_patientA} 72 | df_patientA <- data.frame(ID=1,TIME=c(0,1,6), 73 | DV=c(NA,58,14), 74 | EVID=c(1,0,0), 75 | AMT=c(2000,0,0), 76 | DUR=c(0.5,NA,NA), 77 | CLCREAT4H=50,TBW=62,PoverF=169) 78 | df_patientA 79 | ``` 80 | The concentration measured 30 min after a 30 min infusion do not meet the target for a peak concentration; it is < 60 mg/L. 81 | 82 | ## Estimate the MAP individual parameters 83 | 84 | The maximum a posteriori (MAP) individual parameters are estimated. 85 | 86 | ```{r estim_map} 87 | patA_map <- poso_estim_map(dat=df_patientA, 88 | prior_model=mod_amikacin_Burdet2015) 89 | ``` 90 | 91 | ## Plot the individual pharmacokinetic profile 92 | 93 | The individual pharmacokinetic profile can be plotted using the `rxode2` model provided by the `poso_estim_map()` function. 94 | 95 | ```{r map_plot_tdm} 96 | #| fig.alt: > 97 | #| Plot of the individual PK profile 98 | plot(patA_map$model,Cc) 99 | ``` 100 | 101 | ## Time required to reach the target Cmin following the first administration 102 | 103 | With the MAP estimates of the individual parameters, the prediction of the time needed before reaching the target Cmin can be updated. 104 | 105 | ```{r map_Cmin_priordose_patientA} 106 | poso_time_cmin(dat=df_patientA, 107 | prior_model=mod_amikacin_Burdet2015, 108 | tdm = TRUE, 109 | target_cmin = 2.5) 110 | ``` 111 | The next dose (if needed) can be administered 33.9 hours following the first infusion. 112 | 113 | ## Optimal dose selection a posteriori 114 | 115 | The optimal dose to achieve a peak concentration of 80 mg/l can be determined using the MAP estimates. 116 | 117 | ```{r map_Cmax_optim_patientA} 118 | map_dose <- poso_dose_conc(dat=df_patientA, 119 | prior_model=mod_amikacin_Burdet2015, 120 | tdm=TRUE, 121 | time_c = 35, #target concentration at t = 35 h 122 | time_dose = 34, #dosing at t = 34 h 123 | duration = 0.5, 124 | target_conc = 80) 125 | map_dose 126 | ``` 127 | The next dose should be 2450 mg. 128 | 129 | ## Interdose interval selection a posteriori 130 | 131 | The optimal inter-dose interval to reach a Cmin of 2.5 mg/L before each dosing can be determined using the MAP estimates. 132 | 133 | ```{r map_Cmin_optim_patientA} 134 | map_interval <- poso_inter_cmin(dat=df_patientA, 135 | prior_model=mod_amikacin_Burdet2015, 136 | dose = map_dose$dose, 137 | duration = 0.5, 138 | target_cmin = 2.5) 139 | map_interval 140 | ``` 141 | The interval between doses should not be less than 38.6 hours to allow adequate elimination of amikacin between each infusion. 142 | -------------------------------------------------------------------------------- /tests/testthat/test_multi_outputs.R: -------------------------------------------------------------------------------- 1 | # Difference from the usual warfarin PKPD model: some IIV are set to zero to 2 | # reduce the dimension of omega and reduce the execution time of the test 3 | 4 | if(Sys.getenv("POSOLOGYR_DEV_MACHINE")=="TRUE"){ 5 | mod_warfarin_nlmixr <- list( 6 | ppk_model = rxode2::rxode({ 7 | ktr <- exp(THETA_ktr + ETA_ktr) 8 | ka <- exp(THETA_ka + ETA_ka) 9 | cl <- exp(THETA_cl + ETA_cl) 10 | v <- exp(THETA_v + ETA_v) 11 | emax = expit(THETA_emax + ETA_emax) 12 | ec50 = exp(THETA_ec50 + ETA_ec50) 13 | kout = exp(THETA_kout + ETA_kout) 14 | e0 = exp(THETA_e0 + ETA_e0) 15 | ## 16 | DCP = center/v 17 | PD=1-emax*DCP/(ec50+DCP) 18 | ## 19 | effect(0) = e0 20 | kin = e0*kout 21 | ## 22 | d/dt(depot) = -ktr * depot 23 | d/dt(gut) = ktr * depot -ka * gut 24 | d/dt(center) = ka * gut - cl / v * center 25 | d/dt(effect) = kin*PD -kout*effect 26 | ## 27 | cp = center / v 28 | pca = effect 29 | }), 30 | error_model = list( 31 | cp = function(f,sigma){ 32 | g <- sigma[1]^2 + (sigma[2]^2)*(f^2) 33 | return(sqrt(g)) 34 | }, 35 | pca = function(f,sigma){ 36 | g <- sigma[1]^2 + (sigma[2]^2)*(f^2) 37 | return(sqrt(g)) 38 | } 39 | ), 40 | theta = c(THETA_ktr=0.106, 41 | THETA_ka=-0.087, 42 | THETA_cl=-2.03, 43 | THETA_v=2.07, 44 | THETA_emax=3.4, 45 | THETA_ec50=0.00724, 46 | THETA_kout=-2.9, 47 | THETA_e0=4.57), 48 | omega = lotri::lotri({ETA_ktr + ETA_ka + ETA_cl + ETA_v + ETA_emax + ETA_ec50 + 49 | ETA_kout + ETA_e0 ~ 50 | c(1.024695, 51 | 0.00 , 0.9518403 , 52 | 0.00 , 0.00 , 0.5300943 , 53 | 0.00 , 0.00, 0.00, 0,#0.4785394, 54 | 0.00 , 0.00, 0.00, 0.00, 0.7134424, 55 | 0.00 , 0.00, 0.00, 0.00, 0.00, 0.7204165, 56 | 0.00 , 0.00, 0.00, 0.00, 0.00, 0.00, 0,#0.3563706, 57 | 0.00 , 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0)}),#0.2660827)}), 58 | sigma = list( 59 | cp=c(additive_a = 0.144, proportional_b = 0.15), 60 | pca=c(additive_a = 3.91, proportional_b = 0.0) 61 | ) 62 | ) 63 | 64 | warf_01 <- data.frame(ID=1, 65 | TIME=c(0.0,0.5,1.0,2.0,3.0,6.0,9.0,12.0,24.0,24.0,36.0, 66 | 36.0,48.0,48.0,72.0,72.0,96.0,120.0,144.0), 67 | DV=c(0.0,0.0,1.9,3.3,6.6,9.1,10.8,8.6,5.6,44.0,4.0,27.0, 68 | 2.7,28.0,0.8,31.0,60.0,65.0,71.0), 69 | DVID=c("cp","cp","cp","cp","cp","cp","cp","cp","cp","pca", 70 | "cp","pca","cp","pca","cp","pca","pca","pca","pca"), 71 | EVID=c(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), 72 | AMT=c(100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)) 73 | set.seed(1) 74 | map_warf_01 <- poso_estim_map(dat=warf_01, 75 | prior_model=mod_warfarin_nlmixr, 76 | return_model=TRUE) 77 | 78 | test_that("MAP estimates match nlmixr posthoc estimates for multi endpoints models", { 79 | expect_equal(map_warf_01$model$ktr[1], 0.6392321, tolerance=1e-3) 80 | expect_equal(map_warf_01$model$ka[1], 0.5294417, tolerance=1e-3) 81 | expect_equal(map_warf_01$model$cl[1], 0.2852736, tolerance=1e-3) 82 | expect_equal(map_warf_01$model$v[1], 7.924823, tolerance=1e-3) 83 | expect_equal(map_warf_01$model$emax[1], 0.9304377, tolerance=1e-3) 84 | expect_equal(map_warf_01$model$ec50[1], 0.7909184, tolerance=1e-3) 85 | expect_equal(map_warf_01$model$kout[1], 0.05502322, tolerance=1e-3) 86 | expect_equal(map_warf_01$model$e0[1], 96.54411, tolerance=1e-3) 87 | }) 88 | } 89 | ## estimates from nlmixr 90 | #pk.turnover.emax3 <- function() { 91 | # ini({ 92 | # tktr <- 0.106 93 | # tka <- -0.087 94 | # tcl <- -2.03 95 | # tv <- 2.07 96 | # ## 97 | # eta.ktr ~ sqrt(1.05) 98 | # eta.ka ~ sqrt(0.906) 99 | # eta.cl ~ 0#sqrt(0.281) 100 | # eta.v ~ 0#sqrt(0.229) 101 | # prop.err <- 0.15 102 | # pkadd.err <- 0.144 103 | # ## 104 | # temax <- 3.4 105 | # tec50 <- 0.00724 106 | # tkout <- -2.9 107 | # te0 <- 4.57 108 | # ## 109 | # eta.emax ~ sqrt(.509) 110 | # eta.ec50 ~ sqrt(.519) 111 | # eta.kout ~ 0#sqrt(.127) 112 | # eta.e0 ~ 0#sqrt(.0708) 113 | # ## 114 | # pdadd.err <- 3.91 115 | # }) 116 | # model({ 117 | # ktr <- exp(tktr + eta.ktr) 118 | # ka <- exp(tka + eta.ka) 119 | # cl <- exp(tcl + eta.cl) 120 | # v <- exp(tv + eta.v) 121 | # emax = expit(temax+eta.emax) 122 | # ec50 = exp(tec50 + eta.ec50) 123 | # kout = exp(tkout + eta.kout) 124 | # e0 = exp(te0 + eta.e0) 125 | # ## 126 | # DCP = center/v 127 | # PD=1-emax*DCP/(ec50+DCP) 128 | # ## 129 | # effect(0) = e0 130 | # kin = e0*kout 131 | # ## 132 | # d/dt(depot) = -ktr * depot 133 | # d/dt(gut) = ktr * depot -ka * gut 134 | # d/dt(center) = ka * gut - cl / v * center 135 | # d/dt(effect) = kin*PD -kout*effect 136 | # ## 137 | # cp = center / v 138 | # cp ~ prop(prop.err) + add(pkadd.err) 139 | # effect ~ add(pdadd.err) | pca 140 | # }) 141 | #} 142 | # nlmixr(pk.turnover.emax3,warfarin,"focei", 143 | # control=foceiControl(maxOuterIterations=0)) 144 | -------------------------------------------------------------------------------- /tests/testthat/test_doseoptim_cmt.R: -------------------------------------------------------------------------------- 1 | mod_ganciclovir_Caldes_AAC2009 <- function() { 2 | ini({ 3 | THETA_cl <- 7.49 4 | THETA_v1 <- 31.90 5 | THETA_cld <- 10.20 6 | THETA_v2 <- 32.0 7 | THETA_ka <- 0.895 8 | THETA_baf <- 0.825 9 | ETA_cl ~ 0.107 10 | ETA_v1 ~ 0.227 11 | ETA_ka ~ 0.464 12 | ETA_baf ~ 0.049 13 | add.sd <- 0.465 14 | prop.sd <- 0.143 15 | }) 16 | model({ 17 | TVcl = THETA_cl*(ClCr/57); 18 | TVv1 = THETA_v1; 19 | TVcld = THETA_cld; 20 | TVv2 = THETA_v2; 21 | TVka = THETA_ka; 22 | TVbaf = THETA_baf; 23 | 24 | cl = TVcl*exp(ETA_cl); 25 | v1 = TVv1*exp(ETA_v1); 26 | cld = TVcld; 27 | v2 = TVv2; 28 | ka = TVka*exp(ETA_ka); 29 | baf = TVbaf*exp(ETA_baf); 30 | 31 | k10 = cl/v1; 32 | k12 = cld / v1; 33 | k21 = cld / v2; 34 | Cc = centr/v1; 35 | 36 | d/dt(depot) = -ka*depot 37 | d/dt(centr) = ka*depot - k10*centr - k12*centr + k21*periph; 38 | d/dt(periph) = k12*centr - k21*periph; 39 | d/dt(AUC) = Cc; 40 | 41 | f(depot)=baf; 42 | alag(depot)=0.382; 43 | 44 | Cc ~ add(add.sd) + prop(prop.sd) + combined1() 45 | }) 46 | } 47 | 48 | df_patient <- data.frame(ID=1,TIME=c(0,1,2,6), 49 | DV=c(NA,3.4,2.7,1.4), 50 | AMT=c(450,0,0,0), 51 | EVID=c(1,0,0,0), 52 | ClCr=80) 53 | 54 | test_that("Optimal dose can be estimated for dosing in any compartment", { 55 | # poso_dose_conc-------------------------------------------------------------- 56 | # cmt_dose = "depot" 57 | expect_equal(poso_dose_conc(df_patient,mod_ganciclovir_Caldes_AAC2009, 58 | tdm=TRUE,time_c = 25,time_dose = 24.1, 59 | target_conc = 6,cmt_dose = "depot")$dose, 60 | 1014.197,tolerance=1e-3) 61 | expect_equal(poso_dose_conc(dat=df_patient, 62 | prior_model=mod_ganciclovir_Caldes_AAC2009, 63 | time_c=1,target_conc=6,cmt_dose = "depot")$dose, 64 | 928.35,tolerance=1e-3) 65 | # cmt_dose="centr" 66 | expect_equal(poso_dose_conc(df_patient,mod_ganciclovir_Caldes_AAC2009, 67 | tdm=TRUE,time_c = 25,time_dose = 24.1, 68 | target_conc = 6,cmt_dose = "centr")$dose, 69 | 367.7199,tolerance=1e-3) 70 | expect_equal(poso_dose_conc(dat=df_patient, 71 | prior_model=mod_ganciclovir_Caldes_AAC2009, 72 | time_c=1, 73 | target_conc=6,cmt_dose = "centr")$dose, 74 | 393.84,tolerance=1e-3) 75 | # poso_time_cmin ------------------------------------------------------------- 76 | # cmt_dose = 1 77 | expect_equal(poso_time_cmin(df_patient,mod_ganciclovir_Caldes_AAC2009, 78 | tdm=TRUE,target_cmin = 0.5,from=1)$time, 79 | 13,tolerance=1e-3) 80 | expect_equal(poso_time_cmin(df_patient,mod_ganciclovir_Caldes_AAC2009, 81 | target_cmin = 0.5,from=1,dose=500)$time, 82 | 13.7,tolerance=1e-3) 83 | # cmt_dose="centr" 84 | expect_equal(poso_time_cmin(df_patient,mod_ganciclovir_Caldes_AAC2009, 85 | tdm=TRUE,from=1,target_cmin = 0.5, 86 | cmt_dose = "centr")$time, 87 | 13,tolerance=1e-3) 88 | expect_equal(poso_time_cmin(df_patient,mod_ganciclovir_Caldes_AAC2009, 89 | target_cmin = 0.5,from=1,dose=500, 90 | cmt_dose = "centr")$time, 91 | 14.6,tolerance=1e-3) 92 | # poso_dose_auc ------------------------------------------------------------- 93 | # cmt_dose = 1 94 | expect_equal(poso_dose_auc(df_patient,mod_ganciclovir_Caldes_AAC2009, 95 | tdm=TRUE,time_auc = 24,time_dose = 24.1, 96 | target_auc = 50)$dose, 97 | 924.458,tolerance=1e-3) 98 | expect_equal(poso_dose_auc(df_patient,mod_ganciclovir_Caldes_AAC2009, 99 | time_auc = 24,target_auc = 50)$dose, 100 | 938.59,tolerance=1e-3) 101 | # cmt_dose="centr" 102 | expect_equal(poso_dose_auc(df_patient,mod_ganciclovir_Caldes_AAC2009, 103 | tdm=TRUE,time_auc = 24,time_dose = 24.1, 104 | target_auc = 50,cmt_dose = "centr")$dose, 105 | 645.857,tolerance=1e-3) 106 | expect_equal(poso_dose_auc(df_patient,mod_ganciclovir_Caldes_AAC2009, 107 | time_auc = 24,target_auc = 50, 108 | cmt_dose = "centr")$dose, 109 | 655.729,tolerance=1e-3) 110 | # poso_dose_auc ------------------------------------------------------------- 111 | # cmt_dose = 1 112 | expect_equal(poso_inter_cmin(df_patient,mod_ganciclovir_Caldes_AAC2009, 113 | dose=500,target_cmin = 1)$interval, 114 | 10.69046,tolerance=1e-3) 115 | # cmt_dose="centr" 116 | expect_equal(poso_inter_cmin(df_patient,mod_ganciclovir_Caldes_AAC2009, 117 | dose=500,target_cmin = 1, 118 | cmt_dose = "centr")$interval, 119 | 11.34967,tolerance=1e-3) 120 | }) 121 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | /* http://gregfranko.com/blog/jquery-best-practices/ */ 2 | (function($) { 3 | $(function() { 4 | 5 | $('nav.navbar').headroom(); 6 | 7 | Toc.init({ 8 | $nav: $("#toc"), 9 | $scope: $("main h2, main h3, main h4, main h5, main h6") 10 | }); 11 | 12 | if ($('#toc').length) { 13 | $('body').scrollspy({ 14 | target: '#toc', 15 | offset: $("nav.navbar").outerHeight() + 1 16 | }); 17 | } 18 | 19 | // Activate popovers 20 | $('[data-bs-toggle="popover"]').popover({ 21 | container: 'body', 22 | html: true, 23 | trigger: 'focus', 24 | placement: "top", 25 | sanitize: false, 26 | }); 27 | 28 | $('[data-bs-toggle="tooltip"]').tooltip(); 29 | 30 | /* Clipboard --------------------------*/ 31 | 32 | function changeTooltipMessage(element, msg) { 33 | var tooltipOriginalTitle=element.getAttribute('data-bs-original-title'); 34 | element.setAttribute('data-bs-original-title', msg); 35 | $(element).tooltip('show'); 36 | element.setAttribute('data-bs-original-title', tooltipOriginalTitle); 37 | } 38 | 39 | if(ClipboardJS.isSupported()) { 40 | $(document).ready(function() { 41 | var copyButton = ""; 42 | 43 | $("div.sourceCode").addClass("hasCopyButton"); 44 | 45 | // Insert copy buttons: 46 | $(copyButton).prependTo(".hasCopyButton"); 47 | 48 | // Initialize tooltips: 49 | $('.btn-copy-ex').tooltip({container: 'body'}); 50 | 51 | // Initialize clipboard: 52 | var clipboard = new ClipboardJS('[data-clipboard-copy]', { 53 | text: function(trigger) { 54 | return trigger.parentNode.textContent.replace(/\n#>[^\n]*/g, ""); 55 | } 56 | }); 57 | 58 | clipboard.on('success', function(e) { 59 | changeTooltipMessage(e.trigger, 'Copied!'); 60 | e.clearSelection(); 61 | }); 62 | 63 | clipboard.on('error', function(e) { 64 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 65 | }); 66 | 67 | }); 68 | } 69 | 70 | /* Search marking --------------------------*/ 71 | var url = new URL(window.location.href); 72 | var toMark = url.searchParams.get("q"); 73 | var mark = new Mark("main#main"); 74 | if (toMark) { 75 | mark.mark(toMark, { 76 | accuracy: { 77 | value: "complementary", 78 | limiters: [",", ".", ":", "/"], 79 | } 80 | }); 81 | } 82 | 83 | /* Search --------------------------*/ 84 | /* Adapted from https://github.com/rstudio/bookdown/blob/2d692ba4b61f1e466c92e78fd712b0ab08c11d31/inst/resources/bs4_book/bs4_book.js#L25 */ 85 | // Initialise search index on focus 86 | var fuse; 87 | $("#search-input").focus(async function(e) { 88 | if (fuse) { 89 | return; 90 | } 91 | 92 | $(e.target).addClass("loading"); 93 | var response = await fetch($("#search-input").data("search-index")); 94 | var data = await response.json(); 95 | 96 | var options = { 97 | keys: ["what", "text", "code"], 98 | ignoreLocation: true, 99 | threshold: 0.1, 100 | includeMatches: true, 101 | includeScore: true, 102 | }; 103 | fuse = new Fuse(data, options); 104 | 105 | $(e.target).removeClass("loading"); 106 | }); 107 | 108 | // Use algolia autocomplete 109 | var options = { 110 | autoselect: true, 111 | debug: true, 112 | hint: false, 113 | minLength: 2, 114 | }; 115 | var q; 116 | async function searchFuse(query, callback) { 117 | await fuse; 118 | 119 | var items; 120 | if (!fuse) { 121 | items = []; 122 | } else { 123 | q = query; 124 | var results = fuse.search(query, { limit: 20 }); 125 | items = results 126 | .filter((x) => x.score <= 0.75) 127 | .map((x) => x.item); 128 | if (items.length === 0) { 129 | items = [{dir:"Sorry 😿",previous_headings:"",title:"No results found.",what:"No results found.",path:window.location.href}]; 130 | } 131 | } 132 | callback(items); 133 | } 134 | $("#search-input").autocomplete(options, [ 135 | { 136 | name: "content", 137 | source: searchFuse, 138 | templates: { 139 | suggestion: (s) => { 140 | if (s.title == s.what) { 141 | return `${s.dir} >
    ${s.title}
    `; 142 | } else if (s.previous_headings == "") { 143 | return `${s.dir} >
    ${s.title}
    > ${s.what}`; 144 | } else { 145 | return `${s.dir} >
    ${s.title}
    > ${s.previous_headings} > ${s.what}`; 146 | } 147 | }, 148 | }, 149 | }, 150 | ]).on('autocomplete:selected', function(event, s) { 151 | window.location.href = s.path + "?q=" + q + "#" + s.id; 152 | }); 153 | }); 154 | })(window.jQuery || window.$) 155 | 156 | document.addEventListener('keydown', function(event) { 157 | // Check if the pressed key is '/' 158 | if (event.key === '/') { 159 | event.preventDefault(); // Prevent any default action associated with the '/' key 160 | document.getElementById('search-input').focus(); // Set focus to the search input 161 | } 162 | }); 163 | -------------------------------------------------------------------------------- /R/posologyr.R: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------- 2 | # posologyr: individual dose optimization using population PK 3 | # Copyright (C) Cyril Leven 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Affero General Public License as 7 | # published by the Free Software Foundation, either version 3 of the 8 | # License, or (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU Affero General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Affero General Public License 16 | # along with this program. If not, see . 17 | #------------------------------------------------------------------------- 18 | 19 | #' Get prior model making sure to account for rxode2 ui 20 | #' 21 | #' @param prior_model prior model list or ui 22 | #' @return prior model lis 23 | #' @noRd 24 | #' @author Matthew L. Fidler 25 | get_prior_model <- function(prior_model) { 26 | if (!is.list(prior_model)) { 27 | rxui <- try(rxode2::as.rxUi(prior_model), silent=FALSE) 28 | if (inherits(rxui, "rxUi")) { 29 | prior_model <- rxui$posologyr 30 | } 31 | } 32 | prior_model 33 | } 34 | 35 | #' Creates a posologyr list from a prior model and an individual event 36 | #' record 37 | #' 38 | #' Creates a list for a \code{posologyr} prior model, an individual event 39 | #' record, and an \code{\link[rxode2]{rxSolve}} solve object, 40 | #' created from the prior ppk model and the individual event record. 41 | #' 42 | #' @param prior_model A \code{posologyr} prior population pharmacokinetics 43 | #' model, a list of six objects. 44 | #' @param dat Dataframe. An individual subject dataset following the 45 | #' structure of NONMEM/rxode2 event records. 46 | #' @param nocb A boolean. for time-varying covariates: the next observation 47 | #' carried backward (nocb) interpolation style, similar to NONMEM. If 48 | #' `FALSE`, the last observation carried forward (locf) style will be used. 49 | #' Defaults to `FALSE`. 50 | #' 51 | #' \code{posologyr} will check the validity of the compiled rxode2 52 | #' model. If \code{prior_model$ppk_model$isValid()} returns \code{FALSE}, 53 | #' \code{posologyr} will call \code{\link[rxode2]{rxode2}} 54 | #' to recompile the model before solving it using \code{prior_model} 55 | #' and \code{dat}. 56 | #' 57 | #' @return A list of eight objects: the posologyr prior population 58 | #' pharmacokinetics model given as `prior_model` parameter (6 objects), 59 | #' the individual event record (\code{tdm_data}) given as `dat` parameter, 60 | #' and the solved model (\code{solved_ppk_model}). 61 | #' \describe{ 62 | #' \item{ppk_model}{A rxode2 model implementing the structural 63 | #' population pharmacokinetics model with the individual model 64 | #' (i.e. the model of inter-individual variability) and the 65 | #' covariates} 66 | #' \item{error_model}{A function of the residual error model} 67 | #' \item{theta}{A named vector of the population estimates of the 68 | #' fixed effects parameters (called THETAs, following NONMEM 69 | #' terminology)} 70 | #' \item{omega}{A named square variance-covariance matrix of the 71 | #' population parameters inter-individual variability} 72 | #' \item{covariates}{A character vector of the covariates of 73 | #' the model} 74 | #' \item{sigma}{The estimates of the parameters of the residual error model} 75 | #' \item{tdm_data}{A dataframe. The individual subject dataset 76 | #' given as `dat` parameter} 77 | #' \item{solved_ppk_model}{An \code{\link[rxode2]{rxSolve}} solve object, 78 | #' created with `prior_ppk_model` and using `dat` as the event record.} 79 | #' } 80 | #' 81 | #' @keywords internal 82 | #' @noRd 83 | posologyr <- function(prior_model=NULL,dat=NULL,nocb=FALSE){ 84 | prior_model <- get_prior_model(prior_model) 85 | validate_priormod(prior_model) 86 | validate_dat(dat) 87 | 88 | # check the validity of the compiled model and call rxode2::rxode 89 | # on invalid models 90 | if (!prior_model$ppk_model$isValid()){ 91 | warning("Invalid rxode2 model, trying to recompile...") 92 | prior_model$ppk_model <- try(rxode2::rxode(prior_model$ppk_model), 93 | silent=TRUE) 94 | if (prior_model$ppk_model$isValid()){ 95 | message("Success","\n") 96 | } else { 97 | stop("Failed. The rxode2 model is still invalid. Aborting", 98 | call. = FALSE) 99 | } 100 | } 101 | 102 | # interpolation method for time-varying covariates, nocb or locf 103 | interpolation <- ifelse(nocb,"nocb","locf") 104 | 105 | solved_ppk_model <- rxode2::rxSolve(prior_model$ppk_model, 106 | c(prior_model$theta, 107 | diag(prior_model$omega)*0, 108 | diag(prior_model$pi_matrix)*0), 109 | dat,covsInterpolation=interpolation) 110 | 111 | # assign the objects to a single list 112 | prior_model$tdm_data <- as.data.frame(dat) 113 | prior_model$solved_ppk_model <- solved_ppk_model 114 | prior_model$interpolation <- interpolation 115 | 116 | return(prior_model) 117 | } 118 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | (function() { 6 | 'use strict'; 7 | 8 | window.Toc = { 9 | helpers: { 10 | // return all matching elements in the set, or their descendants 11 | findOrFilter: function($el, selector) { 12 | // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ 13 | // http://stackoverflow.com/a/12731439/358804 14 | var $descendants = $el.find(selector); 15 | return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); 16 | }, 17 | 18 | generateUniqueIdBase: function(el) { 19 | var text = $(el).text(); 20 | var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); 21 | return anchor || el.tagName.toLowerCase(); 22 | }, 23 | 24 | generateUniqueId: function(el) { 25 | var anchorBase = this.generateUniqueIdBase(el); 26 | for (var i = 0; ; i++) { 27 | var anchor = anchorBase; 28 | if (i > 0) { 29 | // add suffix 30 | anchor += '-' + i; 31 | } 32 | // check if ID already exists 33 | if (!document.getElementById(anchor)) { 34 | return anchor; 35 | } 36 | } 37 | }, 38 | 39 | generateAnchor: function(el) { 40 | if (el.id) { 41 | return el.id; 42 | } else { 43 | var anchor = this.generateUniqueId(el); 44 | el.id = anchor; 45 | return anchor; 46 | } 47 | }, 48 | 49 | createNavList: function() { 50 | return $(''); 51 | }, 52 | 53 | createChildNavList: function($parent) { 54 | var $childList = this.createNavList(); 55 | $parent.append($childList); 56 | return $childList; 57 | }, 58 | 59 | generateNavEl: function(anchor, text) { 60 | var $a = $(''); 61 | $a.attr('href', '#' + anchor); 62 | $a.text(text); 63 | var $li = $('
  • '); 64 | $li.append($a); 65 | return $li; 66 | }, 67 | 68 | generateNavItem: function(headingEl) { 69 | var anchor = this.generateAnchor(headingEl); 70 | var $heading = $(headingEl); 71 | var text = $heading.data('toc-text') || $heading.text(); 72 | return this.generateNavEl(anchor, text); 73 | }, 74 | 75 | // Find the first heading level (`

    `, then `

    `, etc.) that has more than one element. Defaults to 1 (for `

    `). 76 | getTopLevel: function($scope) { 77 | for (var i = 1; i <= 6; i++) { 78 | var $headings = this.findOrFilter($scope, 'h' + i); 79 | if ($headings.length > 1) { 80 | return i; 81 | } 82 | } 83 | 84 | return 1; 85 | }, 86 | 87 | // returns the elements for the top level, and the next below it 88 | getHeadings: function($scope, topLevel) { 89 | var topSelector = 'h' + topLevel; 90 | 91 | var secondaryLevel = topLevel + 1; 92 | var secondarySelector = 'h' + secondaryLevel; 93 | 94 | return this.findOrFilter($scope, topSelector + ',' + secondarySelector); 95 | }, 96 | 97 | getNavLevel: function(el) { 98 | return parseInt(el.tagName.charAt(1), 10); 99 | }, 100 | 101 | populateNav: function($topContext, topLevel, $headings) { 102 | var $context = $topContext; 103 | var $prevNav; 104 | 105 | var helpers = this; 106 | $headings.each(function(i, el) { 107 | var $newNav = helpers.generateNavItem(el); 108 | var navLevel = helpers.getNavLevel(el); 109 | 110 | // determine the proper $context 111 | if (navLevel === topLevel) { 112 | // use top level 113 | $context = $topContext; 114 | } else if ($prevNav && $context === $topContext) { 115 | // create a new level of the tree and switch to it 116 | $context = helpers.createChildNavList($prevNav); 117 | } // else use the current $context 118 | 119 | $context.append($newNav); 120 | 121 | $prevNav = $newNav; 122 | }); 123 | }, 124 | 125 | parseOps: function(arg) { 126 | var opts; 127 | if (arg.jquery) { 128 | opts = { 129 | $nav: arg 130 | }; 131 | } else { 132 | opts = arg; 133 | } 134 | opts.$scope = opts.$scope || $(document.body); 135 | return opts; 136 | } 137 | }, 138 | 139 | // accepts a jQuery object, or an options object 140 | init: function(opts) { 141 | opts = this.helpers.parseOps(opts); 142 | 143 | // ensure that the data attribute is in place for styling 144 | opts.$nav.attr('data-toggle', 'toc'); 145 | 146 | var $topContext = this.helpers.createChildNavList(opts.$nav); 147 | var topLevel = this.helpers.getTopLevel(opts.$scope); 148 | var $headings = this.helpers.getHeadings(opts.$scope, topLevel); 149 | this.helpers.populateNav($topContext, topLevel, $headings); 150 | } 151 | }; 152 | 153 | $(function() { 154 | $('nav[data-toggle="toc"]').each(function(i, el) { 155 | var $nav = $(el); 156 | Toc.init($nav); 157 | }); 158 | }); 159 | })(); 160 | -------------------------------------------------------------------------------- /R/et.R: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------- 2 | # posologyr: individual dose optimization using population PK 3 | # Copyright (C) Cyril Leven 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Affero General Public License as 7 | # published by the Free Software Foundation, either version 3 of the 8 | # License, or (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU Affero General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Affero General Public License 16 | # along with this program. If not, see . 17 | #------------------------------------------------------------------------- 18 | 19 | 20 | #' Update a model with events from a new rxode2 event table 21 | #' 22 | #' Update a model with events from a new rxode2 event table, while accounting 23 | #' for and interpolating any covariates or inter-occasion variability. 24 | #' 25 | #' @param target_model Solved rxode2 object. A model generated by one of 26 | #' posologyr's estimation functions. 27 | #' @param prior_model A \code{posologyr} prior population model. 28 | #' @param event_table An rxode2 event table. 29 | #' @param interpolation Character string. Specifies the interpolation method to 30 | #' be used for covariates. Choices are "locf" for last observation carried 31 | #' forward, "nocb" for next observation carried backward, "midpoint", or 32 | #' "linear". 33 | #' 34 | #' @return A solved rxode2 object, updated with the event table provided. 35 | #' 36 | #' @examples 37 | #' # model 38 | #' mod_run001 <- function() { 39 | #' ini({ 40 | #' THETA_Cl <- 4.0 41 | #' THETA_Vc <- 70.0 42 | #' THETA_Ka <- 1.0 43 | #' ETA_Cl ~ 0.2 44 | #' ETA_Vc ~ 0.2 45 | #' ETA_Ka ~ 0.2 46 | #' prop.sd <- sqrt(0.05) 47 | #' }) 48 | #' model({ 49 | #' TVCl <- THETA_Cl 50 | #' TVVc <- THETA_Vc 51 | #' TVKa <- THETA_Ka 52 | #' 53 | #' Cl <- TVCl*exp(ETA_Cl) 54 | #' Vc <- TVVc*exp(ETA_Vc) 55 | #' Ka <- TVKa*exp(ETA_Ka) 56 | #' 57 | #' K20 <- Cl/Vc 58 | #' Cc <- centr/Vc 59 | #' 60 | #' d/dt(depot) = -Ka*depot 61 | #' d/dt(centr) = Ka*depot - K20*centr 62 | #' Cc ~ prop(prop.sd) 63 | #' }) 64 | #' } 65 | #' # df_patient01: event table for Patient01, following a 30 minutes intravenous 66 | #' # infusion 67 | #' df_patient01 <- data.frame(ID=1, 68 | #' TIME=c(0.0,1.0,14.0), 69 | #' DV=c(NA,25.0,5.5), 70 | #' AMT=c(2000,0,0), 71 | #' EVID=c(1,0,0), 72 | #' DUR=c(0.5,NA,NA)) 73 | #' # estimate the prior distribution of population parameters 74 | #' pop_model <- poso_simu_pop(dat=df_patient01,prior_model=mod_run001,n_simul=100) 75 | #' # create a new rxode2 event table from the initial dataset 76 | #' new_et <- rxode2::as.et(df_patient01) 77 | #' new_et$add_sampling(seq(14,15,by=0.1)) 78 | #' # update the model with the new event table 79 | #' poso_replace_et(pop_model$model,mod_run001,event_table=new_et) 80 | #' 81 | #' @export 82 | poso_replace_et <- function(target_model=NULL,prior_model=NULL, 83 | event_table=NULL,interpolation="locf"){ 84 | # input validation 85 | if (is.null(target_model)) stop("argument 'target_model' is missing, with no default") 86 | if (is.null(prior_model)) stop("argument 'prior_model' is missing, with no default") 87 | if (is.null(event_table)) stop("argument 'event_table' is missing, with no default") 88 | prior_model <- get_prior_model(prior_model) 89 | validate_priormod(prior_model) 90 | 91 | yes_covariates <- !is.null(prior_model$covariates) 92 | estim_with_iov <- ifelse(is.null(prior_model$pi_matrix),FALSE,TRUE) 93 | 94 | # translate the interpolation method for approxfun 95 | if(interpolation == "nocb" | interpolation == "locf" | interpolation == "midpoint"){ 96 | interpolation <- "constant" 97 | } else if (interpolation != "linear") { 98 | stop(paste(interpolation,"is not a valid value for 'interpolation'. Choices 99 | are 'locf', 'nocb', 'midpoint' or 'linear'.")) 100 | } 101 | # for approxfun, compromise between left- and right-continuous step functions 102 | if(interpolation == "nocb"){ 103 | left_right_step <- 1 104 | } else if (interpolation == "midpoint"){ 105 | left_right_step <- 0.5 106 | } else { 107 | left_right_step <- 0 108 | } 109 | 110 | if(estim_with_iov){ 111 | pimat <- prior_model$pi_matrix 112 | iov_kappa <- attr(pimat,"dimnames")[[1]] 113 | iov_kappa_mat <- sapply(iov_kappa,FUN=extrapol_iov,dat=target_model, 114 | iov_kappa=iov_kappa, 115 | event_table=event_table) 116 | 117 | event_table <- cbind(event_table,iov_kappa_mat) 118 | } 119 | if(yes_covariates){ 120 | covar_mat <- sapply(prior_model$covariates,FUN=extrapol_cov,dat=target_model, 121 | covar=prior_model$covariates, 122 | interpol_approx=interpolation, 123 | f=left_right_step, 124 | event_table=event_table) 125 | 126 | event_table <- cbind(event_table,covar_mat) 127 | } 128 | updated_model <- rxode2::rxSolve(target_model,event_table,target_model$params) 129 | return(updated_model) 130 | } 131 | -------------------------------------------------------------------------------- /vignettes/articles/a_priori_dosing.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "A priori dose selection" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{A priori dose selection} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set( 12 | collapse = TRUE, 13 | comment = "#>" 14 | ) 15 | set.seed(1) 16 | library(rxode2) 17 | setRxThreads(2L) # limit the number of threads 18 | ``` 19 | 20 | ```{r setup} 21 | library(posologyr) 22 | ``` 23 | 24 | # Introduction 25 | First dose selection for a critical care patient treated with amikacin for suspected ventilator-associated pneumonia. Population pharmacokinetic (ppk) model form Burdet et al. 2015. 26 | 27 | ```{r model} 28 | mod_amikacin_Burdet2015 <- function() { 29 | ini({ 30 | THETA_Cl=4.3 31 | THETA_Vc=15.9 32 | THETA_Vp=21.4 33 | THETA_Q=12.1 34 | ETA_Cl + ETA_Vc + ETA_Vp + ETA_Q ~ 35 | c(0.1, 36 | 0.01 , 0.05 , 37 | 0.01 , 0.02 , 0.2 , 38 | -0.06 , 0.004, 0.003, 0.08) 39 | add_sd <- 0.2 40 | prop_sd <- 0.1 41 | }) 42 | model({ 43 | TVCl = THETA_Cl*(CLCREAT4H/82)^0.7 44 | TVVc = THETA_Vc*(TBW/78)^0.9*(PoverF/169)^0.4 45 | TVVp = THETA_Vp 46 | TVQ = THETA_Q 47 | Cl = TVCl*exp(ETA_Cl) 48 | Vc = TVVc*exp(ETA_Vc) 49 | Vp = TVVp*exp(ETA_Vp) 50 | Q = TVQ *exp(ETA_Q) 51 | ke = Cl/Vc 52 | k12 = Q/Vc 53 | k21 = Q/Vp 54 | Cp = centr/Vc 55 | d/dt(centr) = - ke*centr - k12*centr + k21*periph 56 | d/dt(periph) = + k12*centr - k21*periph 57 | 58 | Cp ~ add(add_sd) + prop(prop_sd) + combined1() 59 | }) 60 | } 61 | 62 | mod_amikacin_Burdet2015 <- mod_amikacin_Burdet2015() 63 | ``` 64 | 65 | # A priori dose selection 66 | 67 | ## Patient record 68 | 69 | Before the first administration, no concentration information is available. The patient record contains only the information required to fill in the covariates of the model: 70 | 71 | * CLCREAT4H: 4-h creatinine clearance in ml/min 72 | * TBW: Total body weight in kg 73 | * PoverF: PaO2/FIO2 ratio in mmHg 74 | 75 | ```{r prior_patientA} 76 | df_patientA <- data.frame(ID=1,TIME=0, 77 | DV=0, 78 | EVID=0, 79 | AMT=0, 80 | CLCREAT4H=50,TBW=62,PoverF=169) 81 | df_patientA 82 | ``` 83 | 84 | ## Optimal dose selection 85 | 86 | In the absence of measured concentrations, the optimal dose in mg to achieve a concentration of 80 mg/l one hour after the start of the 30-minute infusion is 87 | determined from the typical profile of the ppk model. 88 | 89 | ```{r prior_Cmax_optim_patientA} 90 | prior_dose <- poso_dose_conc(dat=df_patientA, 91 | prior_model=mod_amikacin_Burdet2015, 92 | time_c = 1, #30 min after a 93 | duration = 0.5, #30 min infusion 94 | target_conc = 80) 95 | prior_dose 96 | ``` 97 | 98 | ## Time required to reach the target Cmin 99 | 100 | Following this dose, the time in hours required to reach a target Cmin concentration of 2.5 mg/l can be estimated. 101 | 102 | ```{r prior_Cmin_optim_patientA} 103 | poso_time_cmin(dat=df_patientA, 104 | prior_model=mod_amikacin_Burdet2015, 105 | dose = prior_dose$dose, 106 | duration = 0.5, #30 min infusion 107 | target_cmin = 2.5) 108 | ``` 109 | 110 | ## Plotting the selected dosage 111 | 112 | The selected dose can be simulated and plotted. By setting `n_simul = 0`, the `poso_simu_pop()` function produces a compiled `rxode2` model without inter-individual variability, using typical population parameter values and individual covariates from the patient record. 113 | 114 | ```{r prior_plot_model} 115 | # generate a model using the individual covariates 116 | simu_patA <- poso_simu_pop(dat=df_patientA, 117 | prior_model=mod_amikacin_Burdet2015, 118 | n_simul = 0) 119 | ``` 120 | 121 | Observations and a 30-minutes infusion of the optimal dose are added to the `rxode2` model by updating the [rxode2 event table](https://nlmixr2.github.io/rxode2/articles/rxode2-event-table.html). 122 | 123 | ```{r} 124 | simu_patA$model$time <- seq(0,20,b=0.1) 125 | simu_patA$model$add.dosing(dose=prior_dose$dose,rate=prior_dose$dose/0.5) 126 | ``` 127 | 128 | Plotting the simulated scenario. 129 | 130 | ```{r} 131 | #| fig.alt: > 132 | #| Plot of the concentration over time following the selected dosing 133 | plot(simu_patA$model,Cc) 134 | ``` 135 | 136 | The resulting plot can be further augmented with `ggplot2`. For example, by adding an horizontal ribbon showing the 60-80 mg/l target interval of 1 h peak concentration, and a vertical dashed line marking 1 hour. 137 | 138 | ```{r prior_plot} 139 | #| fig.alt: > 140 | #| Plot of the concentration over time following the selected dosing 141 | #| with an horizontal ribbon showing the 60-80 mg/l target interval of 142 | #| 1 h peak concentration, and a vertical dashed line marking 1 hour. 143 | plot(simu_patA$model,Cc) + 144 | ggplot2::ylab("Central concentration") + 145 | ggplot2::geom_vline(xintercept=1, linetype="dashed") + 146 | ggplot2::geom_ribbon(ggplot2::aes(ymin=60, ymax=80), 147 | fill="seagreen",show.legend = FALSE, alpha=0.15) 148 | ``` 149 | 150 | For a typical patient (i.e. with a PK profile typical of the model population), the selected dose meets the peak concentration target. 151 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>", 11 | fig.path = "man/figures/README-", 12 | out.width = "100%" 13 | ) 14 | set.seed(1) 15 | ``` 16 | 17 | # posologyr [](https://github.com/levenc/posologyr/) 18 | 19 | 20 | [![R-CMD-check](https://github.com/levenc/posologyr/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/levenc/posologyr/actions/workflows/R-CMD-check.yaml) 21 | [![CRAN status](https://www.r-pkg.org/badges/version/posologyr)](https://CRAN.R-project.org/package=posologyr) 22 | 23 | 24 | ## Overview 25 | 26 | Personalize drug regimens using individual pharmacokinetic (PK) and pharmacokinetic-pharmacodynamic (PK-PD) profiles. By combining therapeutic drug monitoring (TDM) data with a population model, `posologyr` offers accurate posterior estimates and helps compute optimal individualized dosing regimens. 27 | 28 | Key dosage optimization functions in `posologyr` include: 29 | 30 | + `poso_dose_conc()` estimates the optimal dose to achieve a target concentration at any given time 31 | + `poso_dose_auc()` estimates the dose needed to reach a target area under the concentration-time curve (AUC) 32 | + `poso_time_cmin()` estimates the time required to reach a target trough concentration (Cmin) 33 | + `poso_inter_cmin()` estimates the optimal dosing interval to consistently achieve a target Cmin 34 | 35 | Individual PK profiles can be estimated with or without TDM data: 36 | 37 | + `poso_estim_map()` computes Maximum A Posteriori Bayesian Estimates (MAP-BE) of individual PK parameters using TDM results 38 | + `poso_simu_pop()` samples from the the prior distributions of PK parameters 39 | 40 | `posologyr` leverages the simulation capabilities of the 41 | [rxode2](https://github.com/nlmixr2/rxode2) package. 42 | 43 | ## Installation 44 | 45 | You can install the released version of `posologyr` from 46 | [CRAN](https://CRAN.R-project.org) with: 47 | 48 | ``` {r eval = FALSE} 49 | install.packages("posologyr") 50 | ``` 51 | 52 | You can install the development version of `posologyr` from 53 | [GitHub](https://github.com/) with: 54 | 55 | ```{r eval = FALSE} 56 | # install.packages("remotes") 57 | remotes::install_github("levenc/posologyr") 58 | ``` 59 | 60 | ## Bayesian dosing example 61 | 62 | To determine the optimal dose of gentamicin for a patient with `posologyr`, you will need: 63 | 64 | 1. A prior PK model, written in `rxode2` mini-language 65 | 66 | In this example, a gentamicin PK from the literature 67 | 68 | ```{r} 69 | mod_gentamicin_Xuan2003 <- function() { 70 | ini({ 71 | THETA_Cl = 0.047 72 | THETA_V = 0.28 73 | THETA_k12 = 0.092 74 | THETA_k21 = 0.071 75 | ETA_Cl ~ 0.084 76 | ETA_V ~ 0.003 77 | ETA_k12 ~ 0.398 78 | ETA_k21 ~ 0.342 79 | add_sd <- 0.230 80 | prop_sd <- 0.237 81 | }) 82 | model({ 83 | TVl = THETA_Cl*ClCr 84 | TVV = THETA_V*WT 85 | TVk12 = THETA_k12 86 | TVk21 = THETA_k21 87 | 88 | Cl = TVl*exp(ETA_Cl) 89 | V = TVV*exp(ETA_V) 90 | k12 = TVk12*exp(ETA_k12) 91 | k21 = TVk21 *exp(ETA_k21) 92 | 93 | ke = Cl/V 94 | Cp = centr/V 95 | 96 | d/dt(centr) = - ke*centr - k12*centr + k21*periph 97 | d/dt(periph) = + k12*centr - k21*periph 98 | 99 | Cp ~ add(add_sd) + prop(prop_sd) + combined1() 100 | }) 101 | } 102 | ``` 103 | 104 | 2. A table of the patient's TDM data, in a format similar to the data for NONMEM 105 | 106 | ```{r} 107 | patient_data <- data.frame(ID=1, 108 | TIME=c(0.0,1.0,11.0), 109 | DV=c(NA,9,2), 110 | AMT=c(180,0,0), 111 | DUR=c(0.5,NA,NA), 112 | EVID=c(1,0,0), 113 | ClCr=38, 114 | WT=63) 115 | patient_data 116 | ``` 117 | 118 | 119 | ### Individual PK profile 120 | 121 | With these two elements, you can estimate and plot and the individual concentrations over time. 122 | 123 | ```{r} 124 | library("posologyr") 125 | ``` 126 | 127 | ```{r map_plot} 128 | #| fig.alt: > 129 | #| Plot of the individual profile 130 | patient_map <- poso_estim_map(patient_data,mod_gentamicin_Xuan2003) 131 | plot(patient_map$model,Cc) 132 | ``` 133 | 134 | ### Dose optimization 135 | 136 | We will optimize the gentamicin dosage for this patient to meet two criteria: 137 | 138 | + A peak concentration of 12 mg/L, 30 minutes after a 30-minute infusion. 139 | + A trough concentration of less than 0.5 mg/L. 140 | 141 | The time required to reach a residual concentration of 0.5 mg/L can be estimated as follows: 142 | 143 | ```{r} 144 | poso_time_cmin(patient_data,mod_gentamicin_Xuan2003,tdm=TRUE, 145 | target_cmin = 0.5) 146 | ``` 147 | 148 | The dose required to achieve our target concentration can then be determined for an infusion at H48. 149 | 150 | ```{r} 151 | poso_dose_conc(patient_data,mod_gentamicin_Xuan2003,tdm=TRUE, 152 | target_conc = 12,duration=0.5,time_dose = 48,time_c = 49) 153 | ``` 154 | 155 | In conclusion a dose of 240 mg 48 h after the first injection would be appropriate to meet our 2 criteria. 156 | 157 | More examples can be found at: https://levenc.github.io/posologyr/ 158 | 159 | ## Performance of the MAP-BE algorithm in posologyr 160 | `posologyr` showed comparable performance to NONMEM MAP estimation with option `MAXEVAL=0`: 161 | 162 | * Pharmaceutics **2022**, 14(2), 442; [doi:10.3390/pharmaceutics14020442](https://doi.org/10.3390/pharmaceutics14020442) 163 | * Supporting data: [https://github.com/levenc/posologyr-pharmaceutics](https://github.com/levenc/posologyr-pharmaceutics) 164 | -------------------------------------------------------------------------------- /vignettes/articles/auc_based_dosing.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "AUC-based dose selection" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{AUC-based dose selection} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include=FALSE} 11 | knitr::opts_chunk$set( 12 | collapse=TRUE, 13 | comment="#>" 14 | ) 15 | set.seed(1) 16 | library(rxode2) 17 | setRxThreads(2L) # limit the number of threads 18 | ``` 19 | 20 | ```{r setup} 21 | library(posologyr) 22 | ``` 23 | 24 | # Introduction 25 | AUC-based dosage adjustment for a patient treated with vancomycin for methicillin-resistant Staphylococcus aureus blood stream infection, using the population pharmacokinetic (ppk) model of Goti et al. 2018, using the data from therapeutic drug monitoring (TDM). 26 | 27 | ```{r model} 28 | mod_vancomycin_Goti2018 <- function() { 29 | ini({ 30 | THETA_Cl <- 4.5 31 | THETA_Vc <- 58.4 32 | THETA_Vp <- 38.4 33 | THETA_Q <- 6.5 34 | ETA_Cl ~ 0.147 35 | ETA_Vc ~ 0.510 36 | ETA_Vp ~ 0.282 37 | add.sd <- 3.4 38 | prop.sd <- 0.227 39 | }) 40 | model({ 41 | TVCl = THETA_Cl*(CLCREAT/120)^0.8*(0.7^DIAL); 42 | TVVc = THETA_Vc*(WT/70) *(0.5^DIAL); 43 | TVVp = THETA_Vp; 44 | TVQ = THETA_Q; 45 | Cl = TVCl*exp(ETA_Cl); 46 | Vc = TVVc*exp(ETA_Vc); 47 | Vp = TVVp*exp(ETA_Vp); 48 | Q = TVQ; 49 | ke = Cl/Vc; 50 | k12 = Q/Vc; 51 | k21 = Q/Vp; 52 | Cc = centr/Vc; 53 | d/dt(centr) = - ke*centr - k12*centr + k21*periph; 54 | d/dt(periph) = + k12*centr - k21*periph; 55 | d/dt(AUC) <- Cc 56 | Cc ~ add(add.sd) + prop(prop.sd) + combined1() 57 | }) 58 | } 59 | 60 | mod_vancomycin_Goti2018 <- mod_vancomycin_Goti2018() 61 | ``` 62 | 63 | # Discontinuous intravenous infusion 64 | 65 | ## Patient record with TDM data 66 | 67 | The dosage selection can be informed using the results of TDM. See `vignette("patient_data_input")` for more details regarding the patient records. 68 | 69 | ```{r tdm_patientB} 70 | df_patientB <- data.frame(ID=1,TIME=c(0.0,13.0,24.2,48), 71 | DV=c(NA,12,NA,9.5), 72 | AMT=c(2000,0,1000,0), 73 | DUR=c(2,NA,2,NA), 74 | EVID=c(1,0,1,0), 75 | CLCREAT=65,WT=70,DIAL=0) 76 | df_patientB 77 | ``` 78 | 79 | ## Estimate the MAP individual parameters 80 | 81 | ```{r estim_map} 82 | patB_map <- poso_estim_map(dat=df_patientB, 83 | prior_model=mod_vancomycin_Goti2018) 84 | ``` 85 | 86 | ## Plot the individual pharmacokinetic profile 87 | 88 | The individual pharmacokinetic profile can be plotted using the `rxode2` model provided by the `poso_estim_map()` function. 89 | 90 | ```{r} 91 | #| fig.alt: > 92 | #| Plot of the invidual PK profile 93 | plot(patB_map$model,Cc) 94 | ``` 95 | 96 | Using `ggplot2` the observed data points can be added to the plot 97 | 98 | ```{r map_plot_tdm} 99 | #| fig.alt: > 100 | #| Plot of the individual PK profile, including the observed data points 101 | #Get the observations from the patient record 102 | indiv_obs <- df_patientB[,c("DV","TIME")] 103 | names(indiv_obs) <- c("value","time") 104 | 105 | #Overlay the MAP profile and the observations 106 | plot(patB_map$model,Cc) + 107 | ggplot2::ylab("Central concentration") + 108 | ggplot2::geom_point(data=indiv_obs, size= 3, na.rm=TRUE) 109 | 110 | ``` 111 | 112 | The MAP profile matches the observations. 113 | 114 | ## Get the AUC24 from the MAP model 115 | 116 | Considering a MIC of 1 mg/L, the target AUC over 24 hours (AUC24) is 400 mg.h/L. The AUC can be retrieved from the `rxode2` model using the usual R `data.frame` syntax. 117 | 118 | ```{r AUC_map_dose} 119 | #AUC 0_24 120 | AUC_map_first_dose <- patB_map$model$AUC[which(patB_map$model$time == 24)] 121 | AUC_map_first_dose 122 | 123 | #AUC 24_48 124 | AUC_map_second_dose <- patB_map$model$AUC[which(patB_map$model$time == 48)] - AUC_map_first_dose 125 | AUC_map_second_dose 126 | ``` 127 | 128 | The current dosage does not meet the target AUC. 129 | 130 | ## Optimal dose selection a posteriori 131 | 132 | The next dose needed to achieve an AUC24 of 400 mg.h/L can be estimated using TDM data. 133 | 134 | ```{r optim_next_dose} 135 | poso_dose_auc(dat=df_patientB, 136 | prior_model=mod_vancomycin_Goti2018, 137 | tdm=TRUE, 138 | time_auc=24, #AUC24 139 | time_dose = 48, #48 h: immediately following the last observation 140 | duration=2, #infused over 2 h 141 | target_auc=400) 142 | ``` 143 | The optimal dose estimated for the next infusion is 1411 mg. 144 | 145 | ## Optimal maintenance dose selection a posteriori 146 | 147 | The maintenance dose needed to reliably achieve an AUC24 of 400 mg.h/L can be estimated by simulating a multiple dose regimen over enough administrations (e.g. 11 consecutive administrations, with `add_dose=10`) to approximate the steady-state. 148 | 149 | ```{r optim_maintenance_dose} 150 | poso_dose_auc(dat=df_patientB, 151 | prior_model=mod_vancomycin_Goti2018, 152 | time_auc=24, 153 | starting_time=24*9, 154 | interdose_interval=24, 155 | add_dose=10, 156 | duration=2, 157 | target_auc=400) 158 | ``` 159 | The optimal maintenance dose is 1200 mg. 160 | 161 | # Continuous intravenous infusion 162 | 163 | The maintenance dose for a continuous intravenous infusion can be easily determined by setting the `duration` of the infusion equal to the `interdose_interval`. 164 | 165 | ```{r continuous_infusion} 166 | poso_dose_auc(dat=df_patientB, 167 | prior_model=mod_vancomycin_Goti2018, 168 | time_auc=24, 169 | starting_time=24*9, 170 | interdose_interval=24, 171 | add_dose=10, 172 | duration=24, 173 | target_auc=400) 174 | ``` 175 | 176 | The optimal maintenance dose is also 1200 mg / 24 h for a continuous intravenous infusion. 177 | -------------------------------------------------------------------------------- /man/poso_dose_conc.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/dosing_optim.R 3 | \name{poso_dose_conc} 4 | \alias{poso_dose_conc} 5 | \title{Estimate the optimal dose to achieve a target concentration at any given time} 6 | \usage{ 7 | poso_dose_conc( 8 | dat = NULL, 9 | prior_model = NULL, 10 | tdm = FALSE, 11 | time_c, 12 | time_dose = NULL, 13 | target_conc, 14 | cmt_dose = 1, 15 | endpoint = "Cc", 16 | estim_method = "map", 17 | nocb = FALSE, 18 | p = NULL, 19 | greater_than = TRUE, 20 | starting_dose = 100, 21 | interdose_interval = NULL, 22 | add_dose = NULL, 23 | duration = 0, 24 | indiv_param = NULL 25 | ) 26 | } 27 | \arguments{ 28 | \item{dat}{Dataframe. An individual subject dataset following the 29 | structure of NONMEM/rxode2 event records.} 30 | 31 | \item{prior_model}{A \code{posologyr} prior population pharmacokinetics 32 | model, a list of six objects.} 33 | 34 | \item{tdm}{A boolean. If \code{TRUE}: estimates the optimal dose for a selected 35 | target concentration at a selected point in time following the events from 36 | \code{dat}, and using Maximum A Posteriori estimation. Setting \code{tdm} to \code{TRUE} causes the 37 | following to occur: 38 | \itemize{ 39 | \item the arguments \code{estim_method}, \code{p}, \code{greater_than}, \code{interdose_interval}, 40 | \code{add_dose}, \code{indiv_param} and \code{starting_time} are ignored. 41 | }} 42 | 43 | \item{time_c}{Numeric. Point in time for which the dose is to be 44 | optimized.} 45 | 46 | \item{time_dose}{Numeric. Time when the dose is to be given.} 47 | 48 | \item{target_conc}{Numeric. Target concentration.} 49 | 50 | \item{cmt_dose}{Character or numeric. The compartment in which the dose is 51 | to be administered. Must match one of the compartments in the prior model. 52 | Defaults to 1.} 53 | 54 | \item{endpoint}{Character. The endpoint of the prior model to be optimised 55 | for. The default is "Cc", which is the central concentration.} 56 | 57 | \item{estim_method}{A character string. An estimation method to be used for 58 | the individual parameters. The default method "map" is the Maximum A 59 | Posteriori estimation, the method "prior" simulates from the prior 60 | population model, and "sir" uses the Sequential Importance Resampling 61 | algorithm to estimate the a posteriori distribution of the individual 62 | parameters. This argument is ignored if \code{indiv_param} is provided or if 63 | \code{tdm} is set to \code{TRUE}.} 64 | 65 | \item{nocb}{A boolean. for time-varying covariates: the next observation 66 | carried backward (nocb) interpolation style, similar to NONMEM. If 67 | \code{FALSE}, the last observation carried forward (locf) style will be used. 68 | Defaults to \code{FALSE}.} 69 | 70 | \item{p}{Numeric. The proportion of the distribution of concentrations to 71 | consider for the optimization. Mandatory for \code{estim_method=sir}. This 72 | argument is ignored if \code{tdm} is set to \code{TRUE}.} 73 | 74 | \item{greater_than}{A boolean. If \code{TRUE}: targets a dose leading to a 75 | proportion \code{p} of the concentrations to be greater than \code{target_conc}. 76 | Respectively, lower if \code{FALSE}. This argument is ignored if \code{tdm} is 77 | set to \code{TRUE}.} 78 | 79 | \item{starting_dose}{Numeric. Starting dose for the optimization 80 | algorithm.} 81 | 82 | \item{interdose_interval}{Numeric. Time for the interdose interval 83 | for multiple dose regimen. Must be provided when add_dose is used. This 84 | argument is ignored if \code{tdm} is set to \code{TRUE}.} 85 | 86 | \item{add_dose}{Numeric. Additional doses administered at inter-dose interval 87 | after the first dose. Optional. This argument is ignored if \code{tdm} is set 88 | to \code{TRUE}.} 89 | 90 | \item{duration}{Numeric. Duration of infusion, for zero-order 91 | administrations.} 92 | 93 | \item{indiv_param}{Optional. A set of individual parameters : THETA, 94 | estimates of ETA, and covariates. This argument is ignored if \code{tdm} is 95 | set to \code{TRUE}.} 96 | } 97 | \value{ 98 | A list containing the following components: 99 | \describe{ 100 | \item{dose}{Numeric. An optimal dose for the selected target 101 | concentration.} 102 | \item{type_of_estimate}{Character string. The type of estimate of the 103 | individual parameters. Either a point estimate, or a distribution.} 104 | \item{conc_estimate}{A vector of numeric estimates of the conc. Either a 105 | single value (for a point estimate of ETA), or a distribution.} 106 | \item{indiv_param}{A \code{data.frame}. The set of individual parameters used 107 | for the determination of the optimal dose : THETA, estimates of ETA, and 108 | covariates} 109 | } 110 | } 111 | \description{ 112 | Estimates the optimal dose to achieve a target concentration at any given 113 | time given a population pharmacokinetic model, a set of individual 114 | parameters, a selected point in time, and a target concentration. 115 | } 116 | \examples{ 117 | rxode2::setRxThreads(2L) # limit the number of threads 118 | 119 | # model 120 | mod_run001 <- function() { 121 | ini({ 122 | THETA_Cl <- 4.0 123 | THETA_Vc <- 70.0 124 | THETA_Ka <- 1.0 125 | ETA_Cl ~ 0.2 126 | ETA_Vc ~ 0.2 127 | ETA_Ka ~ 0.2 128 | prop.sd <- sqrt(0.05) 129 | }) 130 | model({ 131 | TVCl <- THETA_Cl 132 | TVVc <- THETA_Vc 133 | TVKa <- THETA_Ka 134 | 135 | Cl <- TVCl*exp(ETA_Cl) 136 | Vc <- TVVc*exp(ETA_Vc) 137 | Ka <- TVKa*exp(ETA_Ka) 138 | 139 | K20 <- Cl/Vc 140 | Cc <- centr/Vc 141 | 142 | d/dt(depot) = -Ka*depot 143 | d/dt(centr) = Ka*depot - K20*centr 144 | Cc ~ prop(prop.sd) 145 | }) 146 | } 147 | # df_patient01: event table for Patient01, following a 30 minutes intravenous 148 | # infusion 149 | df_patient01 <- data.frame(ID=1, 150 | TIME=c(0.0,1.0,14.0), 151 | DV=c(NA,25.0,5.5), 152 | AMT=c(2000,0,0), 153 | EVID=c(1,0,0), 154 | DUR=c(0.5,NA,NA)) 155 | # estimate the optimal dose to reach a concentration of 80 mg/l 156 | # one hour after starting the 30-minutes infusion 157 | poso_dose_conc(dat=df_patient01,prior_model=mod_run001, 158 | time_c=1,duration=0.5,target_conc=80) 159 | 160 | } 161 | -------------------------------------------------------------------------------- /man/poso_dose_auc.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/dosing_optim.R 3 | \name{poso_dose_auc} 4 | \alias{poso_dose_auc} 5 | \title{Estimate the dose needed to reach a target area under the concentration-time 6 | curve (AUC)} 7 | \usage{ 8 | poso_dose_auc( 9 | dat = NULL, 10 | prior_model = NULL, 11 | tdm = FALSE, 12 | time_auc, 13 | time_dose = NULL, 14 | cmt_dose = 1, 15 | target_auc, 16 | estim_method = "map", 17 | nocb = FALSE, 18 | p = NULL, 19 | greater_than = TRUE, 20 | starting_time = 0, 21 | interdose_interval = NULL, 22 | add_dose = NULL, 23 | duration = 0, 24 | starting_dose = 100, 25 | indiv_param = NULL 26 | ) 27 | } 28 | \arguments{ 29 | \item{dat}{Dataframe. An individual subject dataset following the 30 | structure of NONMEM/rxode2 event records.} 31 | 32 | \item{prior_model}{A \code{posologyr} prior population pharmacokinetics 33 | model, a list of six objects.} 34 | 35 | \item{tdm}{A boolean. If \code{TRUE}: estimates the optimal dose for a selected 36 | target auc over a selected duration following the events from \code{dat}, and 37 | using Maximum A Posteriori estimation. Setting \code{tdm} to \code{TRUE} causes the 38 | following to occur: 39 | \itemize{ 40 | \item the \code{time_dose} argument is required and is used as the starting point 41 | for the AUC calculation instead of \code{starting_time}; 42 | \item the arguments \code{estim_method}, \code{p}, \code{greater_than}, \code{interdose_interval}, 43 | \code{add_dose}, \code{indiv_param} and \code{starting_time} are ignored. 44 | }} 45 | 46 | \item{time_auc}{Numeric. A duration. The target AUC is computed from 47 | \code{starting_time} to \code{starting_time} + \code{time_auc}. 48 | When \code{tdm} is set to \code{TRUE} the target AUC is computed from \code{time_dose} to 49 | \code{time_dose} + \code{time_auc} instead.} 50 | 51 | \item{time_dose}{Numeric. Time when the dose is to be given. Only used and 52 | mandatory, when \code{tdm} is set to \code{TRUE}.} 53 | 54 | \item{cmt_dose}{Character or numeric. The compartment in which the dose is 55 | to be administered. Must match one of the compartments in the prior model. 56 | Defaults to 1.} 57 | 58 | \item{target_auc}{Numeric. The target AUC.} 59 | 60 | \item{estim_method}{A character string. An estimation method to be used for 61 | the individual parameters. The default method "map" is the Maximum A 62 | Posteriori estimation, the method "prior" simulates from the prior 63 | population model, and "sir" uses the Sequential Importance Resampling 64 | algorithm to estimate the a posteriori distribution of the individual 65 | parameters. This argument is ignored if \code{indiv_param} is provided, or if 66 | \code{tdm} is set to \code{TRUE}.} 67 | 68 | \item{nocb}{A boolean. for time-varying covariates: the next observation 69 | carried backward (nocb) interpolation style, similar to NONMEM. If 70 | \code{FALSE}, the last observation carried forward (locf) style will be used. 71 | Defaults to \code{FALSE}.} 72 | 73 | \item{p}{Numeric. The proportion of the distribution of AUC to consider for 74 | the optimization. Mandatory for \code{estim_method=sir}. This argument is 75 | ignored if \code{tdm} is set to \code{TRUE}.} 76 | 77 | \item{greater_than}{A boolean. If \code{TRUE}: targets a dose leading to a 78 | proportion \code{p} of the AUCs to be greater than \code{target_auc}. Respectively, 79 | lower if \code{FALSE}. This argument is ignored if \code{tdm} is set to \code{TRUE}.} 80 | 81 | \item{starting_time}{Numeric. First point in time of the AUC, for multiple 82 | dose regimen. The default is zero. This argument is ignored if \code{tdm} is 83 | set to \code{TRUE}, and \code{time_dose} is used as a starting point instead.} 84 | 85 | \item{interdose_interval}{Numeric. Time for the interdose interval for 86 | multiple dose regimen. Must be provided when add_dose is used. This 87 | argument is ignored if \code{tdm} is set to \code{TRUE}.} 88 | 89 | \item{add_dose}{Numeric. Additional doses administered at inter-dose interval 90 | after the first dose. Optional. This argument is ignored if \code{tdm} is set 91 | to \code{TRUE}.} 92 | 93 | \item{duration}{Numeric. Duration of infusion, for zero-order 94 | administrations.} 95 | 96 | \item{starting_dose}{Numeric. Starting dose for the optimization 97 | algorithm.} 98 | 99 | \item{indiv_param}{Optional. A set of individual parameters : THETA, 100 | estimates of ETA, and covariates. This argument is ignored if \code{tdm} is 101 | set to \code{TRUE}.} 102 | } 103 | \value{ 104 | A list containing the following components: 105 | \describe{ 106 | \item{dose}{Numeric. An optimal dose for the selected target AUC.} 107 | \item{type_of_estimate}{Character string. The type of estimate of the 108 | individual parameters. Either a point estimate, or a distribution.} 109 | \item{auc_estimate}{A vector of numeric estimates of the AUC. Either a 110 | single value (for a point estimate of ETA), or a distribution.} 111 | \item{indiv_param}{A \code{data.frame}. The set of individual parameters used 112 | for the determination of the optimal dose : THETA, estimates of ETA, and 113 | covariates} 114 | } 115 | } 116 | \description{ 117 | estimates the dose needed to reach a target area under the concentration-time 118 | curve (AUC) given a population pharmacokinetic model, a set of individual 119 | parameters, and a target AUC. 120 | } 121 | \examples{ 122 | rxode2::setRxThreads(2L) # limit the number of threads 123 | 124 | # model 125 | mod_run001 <- function() { 126 | ini({ 127 | THETA_Cl <- 4.0 128 | THETA_Vc <- 70.0 129 | THETA_Ka <- 1.0 130 | ETA_Cl ~ 0.2 131 | ETA_Vc ~ 0.2 132 | ETA_Ka ~ 0.2 133 | prop.sd <- sqrt(0.05) 134 | }) 135 | model({ 136 | TVCl <- THETA_Cl 137 | TVVc <- THETA_Vc 138 | TVKa <- THETA_Ka 139 | 140 | Cl <- TVCl*exp(ETA_Cl) 141 | Vc <- TVVc*exp(ETA_Vc) 142 | Ka <- TVKa*exp(ETA_Ka) 143 | 144 | K20 <- Cl/Vc 145 | Cc <- centr/Vc 146 | 147 | d/dt(depot) = -Ka*depot 148 | d/dt(centr) = Ka*depot - K20*centr 149 | Cc ~ prop(prop.sd) 150 | }) 151 | } 152 | # df_patient01: event table for Patient01, following a 30 minutes intravenous 153 | # infusion 154 | df_patient01 <- data.frame(ID=1, 155 | TIME=c(0.0,1.0,14.0), 156 | DV=c(NA,25.0,5.5), 157 | AMT=c(2000,0,0), 158 | EVID=c(1,0,0), 159 | DUR=c(0.5,NA,NA)) 160 | # estimate the optimal dose to reach an AUC(0-12h) of 45 h.mg/l 161 | poso_dose_auc(dat=df_patient01,prior_model=mod_run001, 162 | time_auc=12,target_auc=45) 163 | 164 | } 165 | -------------------------------------------------------------------------------- /docs/articles/index.html: -------------------------------------------------------------------------------- 1 | 2 | Articles • posologyr 3 | Skip to contents 4 | 5 | 6 |
    45 |
    46 |
    49 | 50 |
    51 |

    All vignettes

    52 |
    53 | 54 |
    A posteriori dose selection
    55 |
    56 |
    A priori dose selection
    57 |
    58 |
    AUC-based dose selection
    59 |
    60 |
    Classic posologyr models
    61 |
    62 |
    Multiple endpoints
    63 |
    64 |
    Patient data
    65 |
    66 |
    Population models
    67 |
    68 |
    Route of administration
    69 |
    70 |
    71 |
    72 | 73 | 74 |
    77 | 78 | 81 | 82 |
    83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # posologyr [](https://github.com/levenc/posologyr/) 5 | 6 | 7 | 8 | [![R-CMD-check](https://github.com/levenc/posologyr/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/levenc/posologyr/actions/workflows/R-CMD-check.yaml) 9 | [![CRAN 10 | status](https://www.r-pkg.org/badges/version/posologyr)](https://CRAN.R-project.org/package=posologyr) 11 | 12 | 13 | ## Overview 14 | 15 | Personalize drug regimens using individual pharmacokinetic (PK) and 16 | pharmacokinetic-pharmacodynamic (PK-PD) profiles. By combining 17 | therapeutic drug monitoring (TDM) data with a population model, 18 | `posologyr` offers accurate posterior estimates and helps compute 19 | optimal individualized dosing regimens. 20 | 21 | Key dosage optimization functions in `posologyr` include: 22 | 23 | - `poso_dose_conc()` estimates the optimal dose to achieve a target 24 | concentration at any given time 25 | - `poso_dose_auc()` estimates the dose needed to reach a target area 26 | under the concentration-time curve (AUC) 27 | - `poso_time_cmin()` estimates the time required to reach a target 28 | trough concentration (Cmin) 29 | - `poso_inter_cmin()` estimates the optimal dosing interval to 30 | consistently achieve a target Cmin 31 | 32 | Individual PK profiles can be estimated with or without TDM data: 33 | 34 | - `poso_estim_map()` computes Maximum A Posteriori Bayesian Estimates 35 | (MAP-BE) of individual PK parameters using TDM results 36 | - `poso_simu_pop()` samples from the the prior distributions of PK 37 | parameters 38 | 39 | `posologyr` leverages the simulation capabilities of the 40 | [rxode2](https://github.com/nlmixr2/rxode2) package. 41 | 42 | ## Installation 43 | 44 | You can install the released version of `posologyr` from 45 | [CRAN](https://CRAN.R-project.org) with: 46 | 47 | ``` r 48 | install.packages("posologyr") 49 | ``` 50 | 51 | You can install the development version of `posologyr` from 52 | [GitHub](https://github.com/) with: 53 | 54 | ``` r 55 | # install.packages("remotes") 56 | remotes::install_github("levenc/posologyr") 57 | ``` 58 | 59 | ## Bayesian dosing example 60 | 61 | To determine the optimal dose of gentamicin for a patient with 62 | `posologyr`, you will need: 63 | 64 | 1. A prior PK model, written in `rxode2` mini-language 65 | 66 | In this example, a gentamicin PK from the literature 67 | 68 | 69 | ``` r 70 | mod_gentamicin_Xuan2003 <- function() { 71 | ini({ 72 | THETA_Cl = 0.047 73 | THETA_V = 0.28 74 | THETA_k12 = 0.092 75 | THETA_k21 = 0.071 76 | ETA_Cl ~ 0.084 77 | ETA_V ~ 0.003 78 | ETA_k12 ~ 0.398 79 | ETA_k21 ~ 0.342 80 | add_sd <- 0.230 81 | prop_sd <- 0.237 82 | }) 83 | model({ 84 | TVl = THETA_Cl*ClCr 85 | TVV = THETA_V*WT 86 | TVk12 = THETA_k12 87 | TVk21 = THETA_k21 88 | 89 | Cl = TVl*exp(ETA_Cl) 90 | V = TVV*exp(ETA_V) 91 | k12 = TVk12*exp(ETA_k12) 92 | k21 = TVk21 *exp(ETA_k21) 93 | 94 | ke = Cl/V 95 | Cp = centr/V 96 | 97 | d/dt(centr) = - ke*centr - k12*centr + k21*periph 98 | d/dt(periph) = + k12*centr - k21*periph 99 | 100 | Cp ~ add(add_sd) + prop(prop_sd) + combined1() 101 | }) 102 | } 103 | ``` 104 | 105 | 2. A table of the patient’s TDM data, in a format similar to the data 106 | for NONMEM 107 | 108 | ``` r 109 | patient_data <- data.frame(ID=1, 110 | TIME=c(0.0,1.0,11.0), 111 | DV=c(NA,9,2), 112 | AMT=c(180,0,0), 113 | DUR=c(0.5,NA,NA), 114 | EVID=c(1,0,0), 115 | ClCr=38, 116 | WT=63) 117 | patient_data 118 | #> ID TIME DV AMT DUR EVID ClCr WT 119 | #> 1 1 0 NA 180 0.5 1 38 63 120 | #> 2 1 1 9 0 NA 0 38 63 121 | #> 3 1 11 2 0 NA 0 38 63 122 | ``` 123 | 124 | ### Individual PK profile 125 | 126 | With these two elements, you can estimate and plot and the individual 127 | concentrations over time. 128 | 129 | ``` r 130 | library("posologyr") 131 | ``` 132 | 133 | ``` r 134 | patient_map <- poso_estim_map(patient_data,mod_gentamicin_Xuan2003) 135 | plot(patient_map$model,Cc) 136 | ``` 137 | 138 | Plot of the individual profile 139 | 140 | ### Dose optimization 141 | 142 | We will optimize the gentamicin dosage for this patient to meet two 143 | criteria: 144 | 145 | - A peak concentration of 12 mg/L, 30 minutes after a 30-minute 146 | infusion. 147 | - A trough concentration of less than 0.5 mg/L. 148 | 149 | The time required to reach a residual concentration of 0.5 mg/L can be 150 | estimated as follows: 151 | 152 | ``` r 153 | poso_time_cmin(patient_data,mod_gentamicin_Xuan2003,tdm=TRUE, 154 | target_cmin = 0.5) 155 | #> $time 156 | #> [1] 44.9 157 | #> 158 | #> $type_of_estimate 159 | #> [1] "point estimate" 160 | #> 161 | #> $cmin_estimate 162 | #> [1] 0.4991313 163 | #> 164 | #> $indiv_param 165 | #> THETA_Cl THETA_V THETA_k12 THETA_k21 add_sd prop_sd ETA_Cl ETA_V 166 | #> 3 0.047 0.28 0.092 0.071 0.23 0.237 0.03701064 0.001447308 167 | #> ETA_k12 ETA_k21 ClCr WT 168 | #> 3 0.08904703 -0.04838898 38 63 169 | ``` 170 | 171 | The dose required to achieve our target concentration can then be 172 | determined for an infusion at H48. 173 | 174 | ``` r 175 | poso_dose_conc(patient_data,mod_gentamicin_Xuan2003,tdm=TRUE, 176 | target_conc = 12,duration=0.5,time_dose = 48,time_c = 49) 177 | #> $dose 178 | #> [1] 237.5902 179 | #> 180 | #> $type_of_estimate 181 | #> [1] "point estimate" 182 | #> 183 | #> $conc_estimate 184 | #> [1] 12 185 | #> 186 | #> $indiv_param 187 | #> THETA_Cl THETA_V THETA_k12 THETA_k21 add_sd prop_sd ETA_Cl ETA_V 188 | #> 3 0.047 0.28 0.092 0.071 0.23 0.237 0.03701052 0.001447305 189 | #> ETA_k12 ETA_k21 ClCr WT 190 | #> 3 0.08904752 -0.04838936 38 63 191 | ``` 192 | 193 | In conclusion a dose of 240 mg 48 h after the first injection would be 194 | appropriate to meet our 2 criteria. 195 | 196 | More examples can be found at: 197 | 198 | ## Performance of the MAP-BE algorithm in posologyr 199 | 200 | `posologyr` showed comparable performance to NONMEM MAP estimation with 201 | option `MAXEVAL=0`: 202 | 203 | - Pharmaceutics **2022**, 14(2), 442; 204 | [doi:10.3390/pharmaceutics14020442](https://doi.org/10.3390/pharmaceutics14020442) 205 | - Supporting data: 206 | -------------------------------------------------------------------------------- /man/poso_time_cmin.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/dosing_optim.R 3 | \name{poso_time_cmin} 4 | \alias{poso_time_cmin} 5 | \title{Estimate the time required to reach a target trough concentration (Cmin)} 6 | \usage{ 7 | poso_time_cmin( 8 | dat = NULL, 9 | prior_model = NULL, 10 | tdm = FALSE, 11 | target_cmin, 12 | dose = NULL, 13 | cmt_dose = 1, 14 | endpoint = "Cc", 15 | estim_method = "map", 16 | nocb = FALSE, 17 | p = NULL, 18 | greater_than = TRUE, 19 | from = 0.2, 20 | last_time = 72, 21 | add_dose = NULL, 22 | interdose_interval = NULL, 23 | duration = 0, 24 | indiv_param = NULL 25 | ) 26 | } 27 | \arguments{ 28 | \item{dat}{Dataframe. An individual subject dataset following the 29 | structure of NONMEM/rxode2 event records.} 30 | 31 | \item{prior_model}{A \code{posologyr} prior population pharmacokinetics 32 | model, a list of six objects.} 33 | 34 | \item{tdm}{A boolean. If \code{TRUE}: computes the predicted time to reach the 35 | target trough concentration (Cmin) following the last event from \code{dat}, 36 | and using Maximum A Posteriori estimation. Setting \code{tdm} to \code{TRUE} causes 37 | the following to occur: 38 | \itemize{ 39 | \item the simulation starts at the time of the last recorded dose (from the 40 | TDM data) plus \code{from}; 41 | \item the simulation stops at the time of the last recorded dose (from the TDM 42 | data) plus \code{last_time}; 43 | \item the arguments \code{dose}, \code{duration}, \code{estim_method}, \code{p}, \code{greater_than}, 44 | \code{interdose_interval}, \code{add_dose}, \code{indiv_param} and \code{starting_time} are 45 | ignored. 46 | }} 47 | 48 | \item{target_cmin}{Numeric. Target trough concentration (Cmin).} 49 | 50 | \item{dose}{Numeric. Dose administered. This argument is ignored if \code{tdm} is 51 | set to \code{TRUE}.} 52 | 53 | \item{cmt_dose}{Character or numeric. The compartment in which the dose is 54 | to be administered. Must match one of the compartments in the prior model. 55 | Defaults to 1.} 56 | 57 | \item{endpoint}{Character. The endpoint of the prior model to be optimised 58 | for. The default is "Cc", which is the central concentration.} 59 | 60 | \item{estim_method}{A character string. An estimation method to be used for 61 | the individual parameters. The default method "map" is the Maximum A 62 | Posteriori estimation, the method "prior" simulates from the prior 63 | population model, and "sir" uses the Sequential Importance Resampling 64 | algorithm to estimate the a posteriori distribution of the individual 65 | parameters. This argument is ignored if \code{indiv_param} is provided, or if 66 | \code{tdm} is set to \code{TRUE}.} 67 | 68 | \item{nocb}{A boolean. For time-varying covariates: the next observation 69 | carried backward (nocb) interpolation style, similar to NONMEM. If 70 | \code{FALSE}, the last observation carried forward (locf) style will be used. 71 | Defaults to \code{FALSE}.} 72 | 73 | \item{p}{Numeric. The proportion of the distribution of Cmin to consider for 74 | the estimation. Mandatory for \code{estim_method=sir}. This argument is ignored 75 | if \code{tdm} is set to \code{TRUE}.} 76 | 77 | \item{greater_than}{A boolean. If \code{TRUE}: targets a time leading to a 78 | proportion \code{p} of the cmins to be greater than \code{target_cmin}. 79 | Respectively, lower if \code{FALSE}. This argument is ignored if \code{tdm} is set 80 | to \code{TRUE}.} 81 | 82 | \item{from}{Numeric. Starting time for the simulation of the individual 83 | time-concentration profile. The default value is 0.2. When \code{tdm} is set 84 | to \code{TRUE} the simulation starts at the time of the last recorded dose plus 85 | \code{from}.} 86 | 87 | \item{last_time}{Numeric. Ending time for the simulation of the individual 88 | time-concentration profile. The default value is 72. When \code{tdm} is set to 89 | \code{TRUE} the simulation stops at the time of the last recorded dose plus 90 | \code{last_time}.} 91 | 92 | \item{add_dose}{Numeric. Additional doses administered at inter-dose interval 93 | after the first dose. Optional. This argument is ignored if \code{tdm} is 94 | set to \code{TRUE}.} 95 | 96 | \item{interdose_interval}{Numeric. Time for the inter-dose interval for 97 | multiple dose regimen. Must be provided when add_dose is used. This 98 | argument is ignored if \code{tdm} is set to \code{TRUE}.} 99 | 100 | \item{duration}{Numeric. Duration of infusion, for zero-order 101 | administrations. This argument is ignored if \code{tdm} is set to \code{TRUE}.} 102 | 103 | \item{indiv_param}{Optional. A set of individual parameters : THETA, 104 | estimates of ETA, and covariates.} 105 | } 106 | \value{ 107 | A list containing the following components: 108 | \describe{ 109 | \item{time}{Numeric. Time needed to reach the selected Cmin.} 110 | \item{type_of_estimate}{Character string. The type of estimate of the 111 | individual parameters. Either a point estimate, or a distribution.} 112 | \item{cmin_estimate}{A vector of numeric estimates of the Cmin. Either a 113 | single value (for a point estimate of ETA), or a distribution.} 114 | \item{indiv_param}{A \code{data.frame}. The set of individual parameters used 115 | for the determination of the time needed to reach a selected Cmin: THETA, 116 | estimates of ETA, and covariates} 117 | } 118 | } 119 | \description{ 120 | Estimates the time required to reach a target trough concentration (Cmin) 121 | given a population pharmacokinetic model, a set of individual 122 | parameters, a dose, and a target Cmin. 123 | } 124 | \examples{ 125 | rxode2::setRxThreads(2L) # limit the number of threads 126 | 127 | # model 128 | mod_run001 <- function() { 129 | ini({ 130 | THETA_Cl <- 4.0 131 | THETA_Vc <- 70.0 132 | THETA_Ka <- 1.0 133 | ETA_Cl ~ 0.2 134 | ETA_Vc ~ 0.2 135 | ETA_Ka ~ 0.2 136 | prop.sd <- sqrt(0.05) 137 | }) 138 | model({ 139 | TVCl <- THETA_Cl 140 | TVVc <- THETA_Vc 141 | TVKa <- THETA_Ka 142 | 143 | Cl <- TVCl*exp(ETA_Cl) 144 | Vc <- TVVc*exp(ETA_Vc) 145 | Ka <- TVKa*exp(ETA_Ka) 146 | 147 | K20 <- Cl/Vc 148 | Cc <- centr/Vc 149 | 150 | d/dt(depot) = -Ka*depot 151 | d/dt(centr) = Ka*depot - K20*centr 152 | Cc ~ prop(prop.sd) 153 | }) 154 | } 155 | # df_patient01: event table for Patient01, following a 30 minutes intravenous 156 | # infusion 157 | df_patient01 <- data.frame(ID=1, 158 | TIME=c(0.0,1.0,14.0), 159 | DV=c(NA,25.0,5.5), 160 | AMT=c(2000,0,0), 161 | EVID=c(1,0,0), 162 | DUR=c(0.5,NA,NA)) 163 | # predict the time needed to reach a concentration of 2.5 mg/l 164 | # after the administration of a 2500 mg dose over a 30 minutes 165 | # infusion 166 | poso_time_cmin(dat=df_patient01,prior_model=mod_run001, 167 | dose=2500,duration=0.5,from=0.5,target_cmin=2.5) 168 | 169 | } 170 | -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Page not found (404) • posologyr 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Skip to contents 24 | 25 | 26 |
    74 |
    75 |
    79 | 80 | Content not found. Please use links in the navbar. 81 | 82 |
    83 |
    84 | 85 | 86 | 95 |
    96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | --------------------------------------------------------------------------------