library(shiny) library(bslib) library(mrgsolve) library(dplyr) library(ggplot2) # ── BAY 81-8973 (Kovaltry®) Population PK Model ────────────────────────────── # Two-compartment IV model from Garmann et al. (2017) Haemophilia 23:528-537 # LEOPOLD Trials (n=183, ages 1-61y, severe haemophilia A) # M3 method (BLQ samples included) — final model with LBW covariate # ────────────────────────────────────────────────────────────────────────────── model_code <- ' $PARAM @annotated CL : 1.88 : Clearance (dL/h) CLp : 1.90 : Intercompartmental clearance (dL/h) Vc : 30.0 : Central volume of distribution (dL) Vp : 6.37 : Peripheral volume of distribution (dL) LBW : 51.1 : Lean body weight (kg) $CMT @annotated CENT : Central compartment (IU) PERI : Peripheral compartment (IU) $MAIN double CLi = CL * pow(LBW / 51.1, 0.610); double CLpi = CLp; double Vci = Vc * pow(LBW / 51.1, 0.950); double Vpi = Vp; $ODE dxdt_CENT = -(CLi / Vci) * CENT - (CLpi / Vci) * CENT + (CLpi / Vpi) * PERI; dxdt_PERI = (CLpi / Vci) * CENT - (CLpi / Vpi) * PERI; $TABLE double FVIII = CENT / Vci; $CAPTURE FVIII ' mod <- mcode("kovaltry", model_code) app_theme <- bs_theme( version = 5, bootswatch = "flatly", primary = "#8b5cf6" ) |> bs_add_rules(" .metric-card { background: #f8f9fa; border-radius: 8px; padding: 15px; margin: 5px; text-align: center; border: 1px solid #dee2e6; } .metric-value { font-size: 24px; font-weight: bold; color: #2c3e50; } .metric-label { font-size: 12px; color: #7f8c8d; } .metric-success .metric-value { color: #10b981; } .metric-warning .metric-value { color: #f59e0b; } .metric-primary .metric-value { color: #8b5cf6; } .metric-info .metric-value { color: #0dcaf0; } .ref-box { background: #f0f4ff; border-left: 4px solid #8b5cf6; padding: 12px 16px; border-radius: 4px; margin-top: 10px; font-size: 13px; } .ref-box a { color: #8b5cf6; } ") ui <- page_sidebar( title = "Kovaltry\u00ae (BAY 81-8973) \u2014 Recombinant Factor VIII PK Simulator", theme = app_theme, sidebar = sidebar( title = "Simulation Settings", width = 340, h6("\U0001F489 Dosing"), sliderInput("dose", "Dose (IU/kg)", min = 10, max = 60, value = 50, step = 5), sliderInput("interval", "Dosing Interval (h)", min = 48, max = 96, value = 84, step = 12), helpText("48h = every other day, 56h \u2248 3x/wk, 84h \u2248 2x/wk"), numericInput("n_weeks", "Duration (weeks)", value = 2, min = 1, max = 4), hr(), h6("\U0001F9D1 Patient Characteristics"), sliderInput("wt", "Body Weight (kg)", min = 10, max = 120, value = 60, step = 5), sliderInput("lbw", "Lean Body Weight (kg)", min = 9, max = 80, value = 51, step = 1), helpText("Median in LEOPOLD trials: 51.1 kg (range: 9.3\u201379.2 kg)"), hr(), h6("\U0001F3AF Targets"), selectInput("threshold", "FVIII Trough Target (IU/dL)", choices = c("1 IU/dL (Standard)" = 1, "3 IU/dL (Moderate)" = 3, "5 IU/dL (Higher)" = 5), selected = 1 ), checkboxInput("log_scale", "Log Scale (Y-axis)", value = TRUE) ), navset_card_tab( title = "Factor VIII Activity Profile", full_screen = TRUE, nav_panel("Simulation", layout_column_wrap( width = 1/4, fill = FALSE, div(class = "metric-card metric-success", div(class = "metric-value", textOutput("cmax")), div(class = "metric-label", "Cmax (IU/dL)") ), div(class = "metric-card metric-warning", div(class = "metric-value", textOutput("ctrough")), div(class = "metric-label", "Ctrough (IU/dL)") ), div(class = "metric-card metric-primary", div(class = "metric-value", textOutput("auc")), div(class = "metric-label", "AUC\u2080\u208B\u03C4 (IU\u00B7h/dL)") ), div(class = "metric-card metric-info", div(class = "metric-value", textOutput("thalf")), div(class = "metric-label", "t\u00BD\u03B2 (h)") ) ), plotOutput("pkPlot", height = "500px") ), nav_panel("Model Information", markdown(" ## BAY 81-8973 (Kovaltry\u00ae) \u2014 Two-Compartment Population PK Model **Drug:** BAY 81-8973 (Kovaltry\u00ae), full-length unmodified recombinant human Factor VIII **Indication:** Prevention and treatment of bleeding in patients with Hemophilia A **Route:** Intravenous infusion (~10 min) ### Population PK Parameters (M3 Method \u2014 Final Model) | Parameter | Estimate | BSV (%CV) | |-----------|----------|-----------| | CL (Clearance) | 1.88 dL/h | 37.0% | | CLp (Intercompartmental CL) | 1.90 dL/h | \u2014 | | Vc (Central volume) | 30.0 dL | 11.2% | | Vp (Peripheral volume) | 6.37 dL | \u2014 | | LBW on CL | Exponent = 0.610 | \u2014 | | LBW on Vc | Exponent = 0.950 | \u2014 | **Reference LBW:** 51.1 kg (population median) **Distributive half-life (t\u00BD\u03B1):** 1.85 h **Terminal half-life (t\u00BD\u03B2):** 13.9 h **Residual error:** Combined proportional (26.7% CV) + additive (1.10 IU/dL) ### Covariate Effects - **Lean Body Weight (LBW):** Primary covariate on CL and Vc - CL = 1.88 \u00D7 (LBW/51.1)\u2070\u00B7\u2076\u00B9\u2070 dL/h - Vc = 30.0 \u00D7 (LBW/51.1)\u2070\u00B7\u2079\u2075\u2070 dL - **Age:** Highly correlated with LBW; not independently significant - **Race:** Asian effect on Vc identified but not retained in final model ### Age-Stratified PK (Geometric Mean, 50 IU/kg dose) | Age Group | AUC (IU\u00B7h/dL) | CL (dL/h/kg) | Vss (dL/kg) | |-----------|----------|-----------|-----------| | \u226518 years | 1858 | 0.03 | 0.56 | | 12\u2013<18 years | 1523 | 0.03 | 0.61 | | 6\u2013<12 years | 1242 | 0.04 | 0.77 | | 0\u2013<6 years | 970 | 0.05 | 0.92 | ### Key Findings from Garmann et al. 2017 - ~16.5% of samples were below limit of quantitation (BLQ) - Excluding BLQ samples overestimates terminal half-life (18.9 h vs 13.9 h) - M3 method essential for unbiased FVIII PK parameter estimation - LBW-based dosing may be preferable to total body weight in obese patients - Overall Vss (Vc + Vp \u2248 36.4 dL) is close to plasma volume ")), nav_panel("References", div(class = "ref-box", tags$h5("\U0001F4DA Key References"), tags$ol( tags$li("Garmann D, McLeay S, Shah A, Vis P, Maas Enriquez M, Ploeger BA. Population pharmacokinetic characterization of BAY 81-8973, a full-length recombinant factor VIII: lessons learned \u2014 importance of including samples with factor VIII levels below the quantitation limit. ", tags$em("Haemophilia"), " 2017; 23:528\u2013537. ", tags$a(href = "https://doi.org/10.1111/hae.13192", target = "_blank", "DOI: 10.1111/hae.13192")), tags$li("Shah A, Delesen H, Garger S, Lalezari S. Pharmacokinetic properties of BAY 81-8973, a full-length recombinant factor VIII. ", tags$em("Haemophilia"), " 2015; 21:766\u201371."), tags$li("Saxena K, Lalezari S, Oldenberg J et al. Efficacy and safety of BAY 81-8973: results from the LEOPOLD I trial. ", tags$em("Haemophilia"), " 2016; 22:706\u201312."), tags$li("Kavakli K, Yang R, Rusen L et al. Prophylaxis vs on-demand treatment with BAY 81-8973: LEOPOLD II. ", tags$em("J Thromb Haemost"), " 2015; 13:360\u20139."), tags$li("Ljung R, Kenet G, Mancuso ME et al. BAY 81-8973 safety and efficacy in children: LEOPOLD Kids Trial. ", tags$em("Haemophilia"), " 2016; 22:354\u201360."), tags$li("Bjorkman S, Oh M, Spotts G et al. Population pharmacokinetics of recombinant factor VIII: the relationships of pharmacokinetics to age and body weight. ", tags$em("Blood"), " 2012; 119:612\u20138.") ), tags$h5("\U0001F48A Therapeutic Context"), tags$ul( tags$li(tags$strong("Drug Class:"), " Full-length recombinant Factor VIII (Antihemophilic Factor)"), tags$li(tags$strong("Brand:"), " Kovaltry\u00ae (Bayer)"), tags$li(tags$strong("Indication:"), " Hemophilia A \u2014 prophylaxis and on-demand treatment of bleeding"), tags$li(tags$strong("Dosing:"), " 20\u201350 IU/kg IV, 2\u20133 times weekly for prophylaxis"), tags$li(tags$strong("Population:"), " 183 male patients aged 1\u201361 years from LEOPOLD I, II, and Kids trials"), tags$li(tags$strong("Assay:"), " Chromogenic FVIII activity assay (LLOQ: 1.5 IU/dL)"), tags$li(tags$strong("Estimation:"), " NONMEM 7.2, FOCE-I with M3 method for BLQ handling") ) )) ), div(style = "text-align: center; padding: 20px; margin-top: 30px; border-top: 1px solid #e9ecef; color: #6c757d; font-size: 12px;", "Powered by ", tags$a(href = "https://www.pkpdbuilder.com", target = "_blank", style = "color: #8b5cf6; font-weight: 500;", "PKPDBuilder.com"), " \u2022 Built by Sunny \u2600\uFE0F (Husain Attarwala's AI Assistant)", br(), tags$span(style = "font-size: 10px;", "For research and educational purposes only. Not for clinical decision-making.")) ) server <- function(input, output, session) { sim_data <- reactive({ total_dose <- input$dose * input$wt infusion_rate <- total_dose / 0.167 # 10-min IV infusion n_doses <- max(1, floor(input$n_weeks * 7 * 24 / input$interval)) ev1 <- ev(amt = total_dose, cmt = 1, rate = infusion_rate, ii = input$interval, addl = n_doses - 1) mod %>% param(LBW = input$lbw) %>% ev(ev1) %>% mrgsim(end = input$n_weeks * 7 * 24, delta = 0.25) %>% as.data.frame() %>% mutate(time_h = time, time_d = time / 24) }) # ── Steady-state dosing interval (last complete interval) ── ss_data <- reactive({ d <- sim_data() last_dose_time <- (floor(max(d$time_h) / input$interval) - 1) * input$interval d %>% filter(time_h >= last_dose_time, time_h <= last_dose_time + input$interval) }) output$cmax <- renderText({ sprintf("%.1f", max(ss_data()$FVIII, na.rm = TRUE)) }) output$ctrough <- renderText({ sprintf("%.2f", min(ss_data()$FVIII, na.rm = TRUE)) }) output$auc <- renderText({ d <- ss_data() if (nrow(d) > 1) { auc <- sum(diff(d$time_h) * (head(d$FVIII, -1) + tail(d$FVIII, -1)) / 2) sprintf("%.0f", auc) } else { "\u2014" } }) output$thalf <- renderText({ CLi <- 1.88 * (input$lbw / 51.1)^0.610 Vci <- 30.0 * (input$lbw / 51.1)^0.950 CLpi <- 1.90 Vpi <- 6.37 k10 <- CLi / Vci k12 <- CLpi / Vci k21 <- CLpi / Vpi s <- k10 + k12 + k21 beta_val <- 0.5 * (s - sqrt(s^2 - 4 * k10 * k21)) sprintf("%.1f", log(2) / beta_val) }) output$pkPlot <- renderPlot({ d <- sim_data() thresh <- as.numeric(input$threshold) p <- ggplot(d, aes(x = time_d, y = FVIII)) + # Danger zone shading below target annotate("rect", xmin = -Inf, xmax = Inf, ymin = 0, ymax = thresh, fill = "#ef4444", alpha = 0.07) + # Threshold lines geom_hline(yintercept = 1, linetype = "dotted", color = "#ef4444", alpha = 0.5) + geom_hline(yintercept = 3, linetype = "dotted", color = "#f59e0b", alpha = 0.5) + geom_hline(yintercept = 5, linetype = "dotted", color = "#3b82f6", alpha = 0.5) + # Selected threshold (bold) geom_hline(yintercept = thresh, linetype = "dashed", color = "#ef4444", linewidth = 0.7) + # Annotations annotate("text", x = max(d$time_d) * 0.98, y = 1.3, label = "1 IU/dL", hjust = 1, size = 3, color = "#ef4444", fontface = "italic") + annotate("text", x = max(d$time_d) * 0.98, y = 3.6, label = "3 IU/dL", hjust = 1, size = 3, color = "#f59e0b", fontface = "italic") + annotate("text", x = max(d$time_d) * 0.98, y = 6.0, label = "5 IU/dL", hjust = 1, size = 3, color = "#3b82f6", fontface = "italic") + # PK curve geom_line(color = "#8b5cf6", linewidth = 0.9) + labs( x = "Time (days)", y = "FVIII Activity (IU/dL)", title = paste0("Kovaltry\u00ae ", input$dose, " IU/kg Q", input$interval, "H \u2014 ", input$wt, " kg patient (LBW: ", input$lbw, " kg)") ) + theme_minimal(base_size = 14) + theme(plot.title = element_text(face = "bold", size = 13)) if (input$log_scale) { p <- p + scale_y_log10( limits = c(0.1, NA), breaks = c(0.1, 0.5, 1, 3, 5, 10, 25, 50, 100), labels = c("0.1", "0.5", "1", "3", "5", "10", "25", "50", "100") ) } p }) } shinyApp(ui = ui, server = server)