library(shiny) library(bslib) library(mrgsolve) library(dplyr) library(ggplot2) model_code <- ' $PARAM @annotated CL : 0.0680 : Clearance CL/F (L/h) V2 : 14.5 : Central volume V2/F (L) V3 : 3.01 : Peripheral volume V3/F (L) Q : 0.05 : Intercompartmental clearance Q/F (L/h) KA : 0.0255 : Absorption rate constant (1/h) F1 : 1.0 : Bioavailability (relative, already apparent) WT : 70 : Body weight (kg) EGFR : 90 : Baseline eGFR (mL/min/1.73m2) $CMT @annotated DEPOT : SC depot (mg) CENT : Central (mg) PERIPH : Peripheral (mg) $MAIN double CLi = CL * pow(WT / 70.0, 0.75) * pow(EGFR / 90.0, 0.1); double V2i = V2 * pow(WT / 70.0, 1.0); double V3i = V3 * pow(WT / 70.0, 1.0); double Qi = Q * pow(WT / 70.0, 0.75); F_DEPOT = F1; $ODE dxdt_DEPOT = -KA * DEPOT; dxdt_CENT = KA * DEPOT - (CLi / V2i) * CENT - (Qi / V2i) * CENT + (Qi / V3i) * PERIPH; dxdt_PERIPH = (Qi / V2i) * CENT - (Qi / V3i) * PERIPH; $TABLE double CP = CENT / V2i; $CAPTURE CP ' mod <- mcode("efsubaglutide", 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 = "Efsubaglutide Alfa PK Simulator", theme = app_theme, sidebar = sidebar( title = "Simulation Settings", width = 340, h6("Dosing"), sliderInput("dose", "Dose (mg)", min = 0.375, max = 9.0, value = 3.0, step = 0.375), selectInput("interval", "Dosing Frequency", choices = c("Once Weekly (168 h)" = 168, "Once Every 2 Weeks (336 h)" = 336), selected = 168), numericInput("n_weeks", "Duration (weeks)", value = 8, min = 1, max = 24), hr(), h6("Patient Characteristics"), sliderInput("wt", "Weight (kg)", min = 50, max = 150, value = 70, step = 5), sliderInput("egfr", "Baseline eGFR (mL/min/1.73m\u00B2)", min = 30, max = 120, value = 90, step = 5), hr(), checkboxInput("log_scale", "Log Scale (Y-axis)", value = FALSE), checkboxInput("show_ss", "Highlight Last Dosing Interval", value = TRUE) ), navset_card_tab( title = "Efsubaglutide Alfa PK Simulator", 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 (ng/mL)")), div(class = "metric-card metric-warning", div(class = "metric-value", textOutput("ctrough")), div(class = "metric-label", "Ctrough (ng/mL)")), div(class = "metric-card metric-primary", div(class = "metric-value", textOutput("auc")), div(class = "metric-label", "AUC\u2080\u2080-\u03C4 (ng\u00B7h/mL)")), div(class = "metric-card metric-info", div(class = "metric-value", textOutput("thalf")), div(class = "metric-label", "t\u00BD (h)")) ), plotOutput("pkPlot", height = "500px") ), nav_panel("Model Information", markdown(" ## Efsubaglutide Alfa \u2014 Two-Compartment Population PK Model **Drug:** Efsubaglutide alfa (novel long-acting GLP-1 receptor agonist) **Class:** GLP-1 Receptor Agonist **Indication:** Type 2 Diabetes Mellitus **Route:** Subcutaneous injection, once weekly or once every 2 weeks ### Model Structure - **Type:** Two-compartment with first-order absorption and first-order elimination - **Software:** NONMEM (original); reproduced with mrgsolve ### Population PK Parameters (Typical Values) | Parameter | Value | Description | |-----------|-------|-------------| | Ka | 0.0255 h\u207B\u00B9 | Absorption rate constant | | CL/F | 0.0680 L/h | Apparent clearance | | V2/F | 14.5 L | Apparent central volume | | V3/F | 3.01 L | Apparent peripheral volume | | Q/F | ~0.05 L/h | Intercompartmental clearance (estimated) | | t\u00BD | 182\u2013215 h | Terminal half-life (T2D, 1\u20133 mg) | ### Covariates - **CL/F:** Body weight (allometric), baseline eGFR, neutralizing antibody status, study, dose - **V2/F:** Body weight, study - **Clinical relevance:** Dose-proportional exposure. No dose adjustment needed for weight or renal function. ### Dosing Information - **Dose range studied:** 0.375\u20139.0 mg subcutaneous - **Recommended:** Once weekly (supports once every 2 weeks) - **Population:** 911 participants (36 healthy, 875 T2D) across 4 clinical trials ")), nav_panel("References", div(class = "ref-box", tags$h5("\U0001F4DA Key References"), tags$ol( tags$li("Lou YR, Xu YL, Xiong Y, Deng C, Wang Q. Population Pharmacokinetics of Efsubaglutide Alfa in Healthy Subjects and Subjects with Type 2 Diabetes. Clin Pharmacokinet. 2025;64(4):533-552. PMID: 39961992. DOI: 10.1007/s40262-025-01475-7"), tags$li(tags$a(href = "https://go.drugbank.com/drugs/DB21757", target = "_blank", "DrugBank: Efsubaglutide Alfa (DB21757)")), tags$li(tags$a(href = "https://clinicaltrials.gov/study/NCT06921486", target = "_blank", "ClinicalTrials.gov: Efficacy and Safety Study")) ), tags$h5("\U0001F48A Therapeutic Context"), tags$ul( tags$li(tags$strong("Class:"), " GLP-1 Receptor Agonist (long-acting)"), tags$li(tags$strong("Mechanism:"), " Activates GLP-1 receptors to enhance glucose-dependent insulin secretion, suppress glucagon, slow gastric emptying, and reduce appetite"), tags$li(tags$strong("Doses studied:"), " 0.375\u20139.0 mg SC once weekly"), tags$li(tags$strong("Treatment duration:"), " 1\u201324 weeks across trials"), tags$li(tags$strong("Key PK feature:"), " Long half-life (182\u2013215 h) supports once-weekly or biweekly dosing") ), tags$h5("\U0001F52C Model Validation"), tags$ul( tags$li("Based on 4,173 plasma concentration measurements from 911 participants"), tags$li("Validated via visual predictive checks, nonparametric bootstrap, and simulations"), tags$li("Dose-proportional exposure confirmed across dose range") ) )) ), 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({ tau <- as.numeric(input$interval) total_hours <- input$n_weeks * 7 * 24 n_doses <- floor(total_hours / tau) ev1 <- ev(amt = input$dose, cmt = 1, ii = tau, addl = max(n_doses - 1, 0)) mod %>% param(WT = input$wt, EGFR = input$egfr) %>% ev(ev1) %>% mrgsim(end = total_hours, delta = 1) %>% as.data.frame() %>% mutate( time_h = time, time_days = time / 24, CP_ng = CP * 1000 # mg/L to ng/mL (ug/mL -> ng/mL since dose in mg, vol in L) ) }) last_interval_data <- reactive({ d <- sim_data() tau <- as.numeric(input$interval) total_hours <- input$n_weeks * 7 * 24 last_dose_time <- total_hours - tau d %>% filter(time_h >= last_dose_time, time_h <= total_hours) }) output$cmax <- renderText({ li <- last_interval_data() sprintf("%.1f", max(li$CP_ng, na.rm = TRUE)) }) output$ctrough <- renderText({ li <- last_interval_data() sprintf("%.1f", min(li$CP_ng, na.rm = TRUE)) }) output$auc <- renderText({ li <- last_interval_data() if (nrow(li) < 2) return("--") auc_val <- sum(diff(li$time_h) * (head(li$CP_ng, -1) + tail(li$CP_ng, -1)) / 2) if (auc_val > 1000) { sprintf("%.0f", auc_val) } else { sprintf("%.1f", auc_val) } }) output$thalf <- renderText({ CLi <- 0.0680 * (input$wt / 70)^0.75 * (input$egfr / 90)^0.1 V2i <- 14.5 * (input$wt / 70) V3i <- 3.01 * (input$wt / 70) Qi <- 0.05 * (input$wt / 70)^0.75 k10 <- CLi / V2i k12 <- Qi / V2i k21 <- Qi / V3i s <- k10 + k12 + k21 p <- k10 * k21 beta_val <- 0.5 * (s - sqrt(s^2 - 4 * p)) sprintf("%.0f", log(2) / beta_val) }) output$pkPlot <- renderPlot({ d <- sim_data() tau <- as.numeric(input$interval) total_hours <- input$n_weeks * 7 * 24 last_dose_time <- total_hours - tau p <- ggplot(d, aes(x = time_days, y = CP_ng)) + geom_line(color = "#8b5cf6", linewidth = 0.8) if (input$show_ss && total_hours > tau) { p <- p + annotate("rect", xmin = last_dose_time / 24, xmax = total_hours / 24, ymin = -Inf, ymax = Inf, fill = "#8b5cf6", alpha = 0.08) } p <- p + labs( x = "Time (days)", y = "Concentration (ng/mL)", title = paste0("Efsubaglutide Alfa ", input$dose, " mg ", ifelse(tau == 168, "QW", "Q2W"), " \u2014 ", input$n_weeks, " Weeks") ) + theme_minimal(base_size = 14) + theme(plot.title = element_text(face = "bold")) if (input$log_scale) p <- p + scale_y_log10() p }) } shinyApp(ui = ui, server = server)