library(shiny) library(bslib) library(mrgsolve) library(dplyr) library(ggplot2) # ============================================================================= # Oxcarbazepine (OXZ) / Monohydroxy Derivative (MHD) Population PK Simulator # Reference: Samant BS et al. (2025) Clin Pharmacokinet # "Population Pharmacokinetic Modeling of Oxcarbazepine and its Active # Metabolite MHD to Inform Dosing in Children with Obesity" # DOI: 10.1007/s40262-025-01579-0 # # Model: 1-CMT joint parent-metabolite, PKWT-scaled allometric # Population: Pediatric patients (2–21 years), including children with obesity # ============================================================================= model_code <- ' $PARAM @annotated CL_MHD : 3.05 : Typical CL of MHD at PKWT_REF (L/h) CL_OXZ : 220 : Typical CL of OXZ at PKWT_REF (L/h) V_MHD : 50 : Typical V of MHD at PKWT_REF (L) [reference fixed] V_OXZ : 33.1 : Typical V of OXZ at PKWT_REF (L) KA : 0.269 : First-order absorption rate constant (h-1) KBT : 0.0433 : Backward transformation MHD to OXZ (h-1) PKWT : 30 : Pharmacokinetic weight - FFM-based (kg) PKWT_REF : 50 : Reference PKWT (kg) EXP_CL_MHD : 0.671 : Allometric exponent for CL_MHD EXP_CL_OXZ : 1.0 : Allometric exponent for CL_OXZ (fixed) EXP_V : 0.752 : Shared allometric exponent for V_MHD and V_OXZ SF_FT : 1.008 : Salt factor OXZ-to-MHD (MW_MHD/MW_OXZ = 254.28/252.27) SF_BT : 0.9921 : Salt factor MHD-to-OXZ (MW_OXZ/MW_MHD = 252.27/254.28) F1 : 1.0 : Oral bioavailability of OXZ (~100%) $CMT @annotated GUT : Oral GI tract (mg) OXZ : Central OXZ compartment (mg) MHD : Central MHD compartment (mg) $MAIN double pkwt_ratio = PKWT / PKWT_REF; // Allometric scaling: typical values scaled to individual PKWT double TVCLi_MHD = CL_MHD * pow(pkwt_ratio, EXP_CL_MHD); double TVCLi_OXZ = CL_OXZ * pow(pkwt_ratio, EXP_CL_OXZ); double TVVi_MHD = V_MHD * pow(pkwt_ratio, EXP_V); double TVVi_OXZ = V_OXZ * pow(pkwt_ratio, EXP_V); F_GUT = F1; $ODE double Vi_OXZ = V_OXZ * pow(PKWT / PKWT_REF, EXP_V); double Vi_MHD = V_MHD * pow(PKWT / PKWT_REF, EXP_V); double CLi_OXZ = CL_OXZ * pow(PKWT / PKWT_REF, EXP_CL_OXZ); double CLi_MHD = CL_MHD * pow(PKWT / PKWT_REF, EXP_CL_MHD); double ke_OXZ = CLi_OXZ / Vi_OXZ; double ke_MHD = CLi_MHD / Vi_MHD; // ODEs (Eqs 1-3, Samant et al. 2025) dxdt_GUT = -KA * GUT; dxdt_OXZ = KA * GUT - ke_OXZ * OXZ + KBT * MHD * SF_BT; dxdt_MHD = ke_OXZ * OXZ * SF_FT - ke_MHD * MHD - KBT * MHD; $TABLE double CONC_OXZ = OXZ / (V_OXZ * pow(PKWT / PKWT_REF, EXP_V)); double CONC_MHD = MHD / (V_MHD * pow(PKWT / PKWT_REF, EXP_V)); $CAPTURE CONC_OXZ CONC_MHD ' mod <- mcode("oxcarbazepine_mhd", model_code, quiet = TRUE) # --------------------------------------------------------------------------- # # Theme # # --------------------------------------------------------------------------- # 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; } .metric-danger .metric-value { color: #ef4444; } .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; } .dose-rec-box { background: #fef9c3; border-left: 4px solid #f59e0b; padding: 10px 14px; border-radius: 4px; font-size: 12px; } ") # --------------------------------------------------------------------------- # # UI # # --------------------------------------------------------------------------- # ui <- page_sidebar( title = "Oxcarbazepine (OXZ / MHD) PK Simulator — Pediatrics", theme = app_theme, sidebar = sidebar( title = "Simulation Settings", width = 360, h6("Dosing"), sliderInput("dose", "Single Dose (mg)", min = 50, max = 1200, value = 450, step = 50), numericInput("interval", "Dosing Interval (h)", value = 12, min = 8, max = 24, step = 4), numericInput("n_days", "Duration (days)", value = 7, min = 1, max = 14), hr(), h6("Patient Characteristics"), sliderInput("pkwt", "Pharmacokinetic Weight — PKWT (kg)", min = 3, max = 70, value = 30, step = 1), div(class = "dose-rec-box", tags$strong("PKWT notes:"), tags$ul(style = "padding-left: 16px; margin-bottom: 0;", tags$li("Age < 3 years: PKWT ≈ Total body weight"), tags$li("Age ≥ 3 years: PKWT = fat-free mass (FFM)"), tags$li("Typical values: 10 kg (toddler), 20 kg (child), 30–40 kg (adolescent)") ) ), hr(), h6("Display"), checkboxInput("show_oxz", "Show OXZ concentrations on plot", value = FALSE), checkboxInput("log_scale", "Log Scale (Y-axis)", value = FALSE) ), # ---- Metric cards + plot ------------------------------------------------ # layout_column_wrap( width = 1 / 4, fill = FALSE, div(class = "metric-card metric-primary", div(class = "metric-value", textOutput("cmax_mhd")), div(class = "metric-label", "MHD Cmax (mg/L)")), div(class = "metric-card metric-success", div(class = "metric-value", textOutput("ctrough_mhd")), div(class = "metric-label", "MHD Ctrough,ss (mg/L)")), div(class = "metric-card metric-info", div(class = "metric-value", textOutput("auc_mhd")), div(class = "metric-label", "MHD AUCτ (mg·h/L)")), div(class = "metric-card metric-warning", div(class = "metric-value", textOutput("thalf_mhd")), div(class = "metric-label", "MHD t½ (h)")) ), navset_card_underline( title = NULL, full_screen = TRUE, # ---- Simulation tab ---------------------------------------------------- # nav_panel("Simulation", card( full_screen = TRUE, card_body( plotOutput("pkPlot", height = "500px") ) ) ), # ---- Model Information tab --------------------------------------------- # nav_panel("Model Information", markdown(" ## Oxcarbazepine (OXZ) / Monohydroxy Derivative (MHD) — Joint Parent-Metabolite PopPK Model **Reference population:** Pediatric patients aged 2–21 years (including children with obesity) **N = 100 participants** from two multicenter studies (POP01, AED01); 425 plasma observations --- ### Model Structure **Type:** One-compartment joint parent-metabolite model with first-order absorption **Transformation:** Bi-directional — OXZ ⇌ MHD (forward: kₒₓ→ₘₕD = CL_OXZ/V_OXZ; backward: Kbt) **Elimination:** Linear (first-order) for both OXZ and MHD **Estimation method:** NONMEM 7.4, FOCEI --- ### Final Model Parameters (Table 4, Samant et al. 2025) | Parameter | Value | %RSE | BSV (CV%) | |-----------|-------|------|-----------| | CL_MHD (L/h) at PKWT=50 kg | 3.05 | 7% | 36% | | CL_OXZ (L/h) at PKWT=50 kg | 220 | 13% | 51% | | V_MHD (L) at PKWT=50 kg | 50 (fixed) | — | 80% | | V_OXZ (L) at PKWT=50 kg | 33.1 | 34% | — | | Ka (h⁻¹) | 0.269 | 28% | — | | Kbt (h⁻¹) | 0.0433 | 22% | — | | θ_CL,MHD (exponent) | 0.671 | 10% | — | | θ_CL,OXZ (exponent) | 1.0 (fixed) | — | — | | θ_V (shared exponent) | 0.752 | 10% | — | | σ_prop,MHD (CV%) | 24% | — | — | | σ_prop,OXZ (CV%) | 52% | — | — | --- ### Allometric Scaling Equations (Final Model) **Typical values scaled by pharmacokinetic weight (PKWT):** - TVCL_MHD = 3.05 × (PKWT/50)^0.671 (L/h) - TVCL_OXZ = 220 × (PKWT/50)^1.0 (L/h) - TVV_MHD = 50 × (PKWT/50)^0.752 (L) - TVV_OXZ = 33.1 × (PKWT/50)^0.752 (L) **PKWT:** Fat-free mass (FFM) for age ≥ 3 years; total body weight for age < 3 years. The less-than-proportional scaling of V (exponent 0.752 vs conventional 1.0) is consistent with the low lipophilicity of OXZ (LogP 1.31) and MHD (LogP 0.94). CL_OXZ scales proportionally (exponent = 1.0), reflecting widespread extra-hepatic metabolism by AKR family enzymes. --- ### Covariates - **Body size only** — PKWT is the sole significant covariate (no age maturation effect detected) - **Obesity:** Accounted for by using PKWT (FFM) instead of total body weight --- ### Therapeutic Drug Monitoring - **MHD reference range (ILAE):** 3–35 mg/L - Target trough (Ctrough,ss): typically 13–28 mg/L at recommended doses - MHD is ~45× more abundant than OXZ at steady state ")), # ---- References tab ---------------------------------------------------- # nav_panel("References", div(class = "ref-box", tags$h5("📚 Primary Reference"), tags$p(tags$strong("Samant BS, Capparelli EV, Benjamin DK Jr, Zimmerman K, Sun J, et al."), " Population Pharmacokinetic Modeling of Oxcarbazepine and its Active Metabolite", " 10-Monohydroxy Derivative to Inform Dosing in Children with Obesity.", tags$em(" Clinical Pharmacokinetics."), " 2025.", tags$a(href="https://doi.org/10.1007/s40262-025-01579-0", target="_blank", " DOI:10.1007/s40262-025-01579-0")), tags$hr(), tags$h5("💊 Drug Information"), tags$ul( tags$li(tags$strong("Generic name:"), " Oxcarbazepine (OXZ); active metabolite: licarbazepine / MHD"), tags$li(tags$strong("Brand names:"), " Trileptal® (IR tablet/suspension), Oxtellar XR® (ER tablet)"), tags$li(tags$strong("Drug class:"), " Antiepileptic drug (AED), dibenz[b,f]azepine derivative"), tags$li(tags$strong("Indication:"), " Partial-onset seizures (adults and children ≥ 2 years)"), tags$li(tags$strong("Route:"), " Oral (tablet or suspension)"), tags$li(tags$strong("Metabolism:"), " OXZ → MHD by cytosolic AKR enzymes (ubiquitous, extra-hepatic)"), tags$li(tags$strong("MHD elimination:"), " Glucuronide conjugation (~50%) + renal excretion (~25%)") ), tags$hr(), tags$h5("📖 Supporting References"), tags$ol( tags$li("Rodrigues M et al. (2017) Br J Clin Pharmacol — OXZ/MHD PopPK in children 2–12 years"), tags$li("Landmark CJ et al. (2019) medRxiv — Systematic review of OXZ PopPK"), tags$li("Trileptal® [prescribing information]. Novartis Pharmaceuticals Corp"), tags$li("Patsalos PN et al. (2008) Epilepsia — TDM in epilepsy (ILAE reference ranges)") ) )) ), # ---- Footer ------------------------------------------------------------ # div( style = paste0("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"), " • Built by Sunny ☀️ (Husain Attarwala's AI Assistant)", tags$br(), tags$span(style = "font-size:10px;", "For research and educational purposes only. Not for clinical decision-making.") ) ) # --------------------------------------------------------------------------- # # Server # # --------------------------------------------------------------------------- # server <- function(input, output, session) { sim_data <- reactive({ shiny::req(input$dose, input$interval, input$n_days, input$pkwt) n_doses <- max(1, floor(input$n_days * 24 / input$interval)) ev1 <- ev(amt = input$dose, cmt = 1, ii = input$interval, addl = n_doses - 1) mod |> param(PKWT = input$pkwt) |> ev(ev1) |> mrgsim(end = input$n_days * 24, delta = 0.1) |> as.data.frame() |> mutate(time_h = time) }) # Steady-state window: last dosing interval ss_window <- reactive({ shiny::req(sim_data()) d <- sim_data() t_end <- max(d$time_h) t_ss <- t_end - input$interval dplyr::filter(d, time_h >= t_ss) }) output$cmax_mhd <- renderText({ d <- ss_window() sprintf("%.2f", max(d$CONC_MHD, na.rm = TRUE)) }) output$ctrough_mhd <- renderText({ d <- ss_window() cmin <- min(d$CONC_MHD, na.rm = TRUE) sprintf("%.2f", cmin) }) output$auc_mhd <- renderText({ d <- ss_window() if (nrow(d) < 2) return("—") auc <- sum(diff(d$time_h) * (utils::head(d$CONC_MHD, -1) + utils::tail(d$CONC_MHD, -1)) / 2) sprintf("%.1f", auc) }) output$thalf_mhd <- renderText({ shiny::req(input$pkwt) pkwt_ratio <- input$pkwt / 50 cl_mhd_i <- 3.05 * pkwt_ratio^0.671 v_mhd_i <- 50 * pkwt_ratio^0.752 thalf <- log(2) * v_mhd_i / cl_mhd_i sprintf("%.1f", thalf) }) output$pkPlot <- renderPlot({ shiny::req(sim_data()) d <- sim_data() # Therapeutic reference band (ILAE: 3–35 mg/L for MHD) tmin <- 3 tmax <- 35 p <- ggplot(d, aes(x = time_h)) + annotate("rect", xmin = -Inf, xmax = Inf, ymin = tmin, ymax = tmax, fill = "#10b981", alpha = 0.10) + geom_hline(yintercept = c(tmin, tmax), linetype = "dashed", color = "#10b981", alpha = 0.7, linewidth = 0.5) + annotate("text", x = max(d$time_h) * 0.02, y = tmax + 0.5, label = paste0("ILAE reference: ", tmin, "–", tmax, " mg/L"), hjust = 0, size = 3.5, color = "#10b981") + geom_line(aes(y = CONC_MHD, color = "MHD (active metabolite)"), linewidth = 1.0) + scale_color_manual( name = "Compound", values = c("MHD (active metabolite)" = "#8b5cf6", "OXZ (parent)" = "#f59e0b") ) + labs( x = "Time (hours)", y = "Plasma Concentration (mg/L)", title = paste0("Oxcarbazepine → MHD | Dose: ", input$dose, " mg Q", input$interval, "H | PKWT: ", input$pkwt, " kg") ) + theme_minimal(base_size = 14) + theme(legend.position = "bottom") if (input$show_oxz) { p <- p + geom_line(aes(y = CONC_OXZ, color = "OXZ (parent)"), linewidth = 0.7, linetype = "dashed") } if (input$log_scale) { p <- p + scale_y_log10() } p }) } shinyApp(ui = ui, server = server)