library(shiny) library(bslib) library(mrgsolve) library(dplyr) library(ggplot2) model_code <- ' $PARAM @annotated CL : 0.0739 : Apparent clearance after separating F (L/day) V : 7.44 : Apparent volume after separating F (L) KA : 0.542 : First-order absorption rate constant (1/day) F1 : 0.70 : Subcutaneous bioavailability (fraction) $CMT @annotated DEPOT : Subcutaneous depot (mg) CENT : Central compartment (mg) $MAIN F_DEPOT = F1; $ODE dxdt_DEPOT = -KA * DEPOT; dxdt_CENT = KA * DEPOT - (CL / V) * CENT; $TABLE double CP = CENT / V; double KEL = CL / V; double THALF = log(2.0) / KEL; $CAPTURE @annotated CP : Plasma concentration (mg/L; numerically equal to ug/mL) KEL : Elimination rate constant (1/day) THALF : Terminal half-life (day) ' mod <- mcode("orka002_hs_318", model_code, quiet = TRUE) 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; } .small-note { color: #6c757d; font-size: 12px; margin-top: 8px; } .info-grid td { padding: 6px 10px; vertical-align: top; border-bottom: 1px solid #eef2f7; } .info-grid td:first-child { font-weight: 600; width: 230px; } ") regimen_choices <- c( "Single 320 mg SC dose (PK reference)" = "single_320", "HS modeled regimen" = "hs_regimen", "Custom fixed-interval SC regimen" = "custom" ) build_regimen_schedule <- function(regimen, duration_weeks, custom_dose = 320, custom_interval = 12) { duration_days <- duration_weeks * 7 if (regimen == "single_320") { times <- 0 dose <- 320 metric_interval <- 84 label <- "Single 320 mg SC dose" } else if (regimen == "hs_regimen") { induction <- c(0, 4, 8, 12) * 7 maintenance <- seq(24, ceiling(duration_weeks) + 12, by = 12) * 7 times <- sort(unique(c(induction, maintenance))) times <- times[times <= duration_days] if (length(times) == 0) { times <- 0 } dose <- 320 metric_interval <- if (length(times) > 1 && max(times) >= 24 * 7) 84 else 28 label <- "HS regimen: 320 mg at Weeks 0, 4, 8, and 12, then every 12 weeks" } else { interval_days <- custom_interval * 7 times <- seq(0, duration_days, by = interval_days) dose <- custom_dose metric_interval <- interval_days label <- paste0("Custom SC regimen: ", custom_dose, " mg every ", custom_interval, " weeks") } list( times = times, dose = dose, metric_interval = metric_interval, label = label ) } trap_auc <- function(time, conc) { if (length(time) < 2 || length(conc) < 2) { return(NA_real_) } sum(diff(time) * (head(conc, -1) + tail(conc, -1)) / 2) } ui <- page_sidebar( title = "ORKA-002 HS PK Simulator", theme = app_theme, sidebar = sidebar( title = "Simulation Settings", width = 340, selectInput("regimen", "Regimen", choices = regimen_choices, selected = "hs_regimen"), conditionalPanel( condition = "input.regimen == 'custom'", sliderInput("custom_dose", "Dose (mg)", min = 80, max = 640, value = 320, step = 20), sliderInput("custom_interval", "Interval (weeks)", min = 2, max = 24, value = 12, step = 1) ), numericInput("duration_weeks", "Simulation duration (weeks)", value = 72, min = 12, max = 156, step = 4), checkboxInput("log_scale", "Log scale (Y-axis)", value = FALSE), div( class = "small-note", "This simulator uses the hidradenitis suppurativa-adjusted ORKA-002 PK summary values provided in the uploaded manuscript." ) ), layout_column_wrap( width = 1 / 4, fill = FALSE, div(class = "metric-card metric-success", div(class = "metric-value", textOutput("cmax")), div(class = "metric-label", "Last-interval Cmax (ug/mL)")), div(class = "metric-card metric-warning", div(class = "metric-value", textOutput("ctrough")), div(class = "metric-label", "Last-interval Ctrough (ug/mL)")), div(class = "metric-card metric-primary", div(class = "metric-value", textOutput("auc")), div(class = "metric-label", "Last-interval AUC (ug*day/mL)")), div(class = "metric-card metric-info", div(class = "metric-value", textOutput("thalf")), div(class = "metric-label", "Terminal t1/2 (days)")) ), card( card_header("Concentration-Time Profile"), full_screen = TRUE, plotOutput("pkPlot", height = "500px"), div(class = "small-note", textOutput("plot_note")) ), navset_card_underline( title = "Drug Information", nav_panel("Model Information", uiOutput("model_info")), nav_panel("References", uiOutput("references")) ), 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"), " • Built by Sunny ☀️ (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_bundle <- reactive({ schedule <- build_regimen_schedule( regimen = input$regimen, duration_weeks = input$duration_weeks, custom_dose = input$custom_dose, custom_interval = input$custom_interval ) event_df <- data.frame( ID = 1, time = schedule$times, amt = schedule$dose, cmt = 1, evid = 1 ) sim_end <- max(input$duration_weeks * 7, max(schedule$times) + schedule$metric_interval) sim <- mod %>% data_set(event_df) %>% mrgsim(end = sim_end, delta = 0.25) %>% as.data.frame() |> mutate( time_days = time, time_weeks = time / 7 ) last_dose_time <- max(schedule$times) metric_end <- last_dose_time + schedule$metric_interval interval_data <- sim |> dplyr::filter(time_days >= last_dose_time, time_days <= metric_end) list( sim = sim, schedule = schedule, plot_end = input$duration_weeks * 7, interval_data = interval_data, last_dose_time = last_dose_time, metric_end = metric_end ) }) output$cmax <- renderText({ d <- sim_bundle()$interval_data shiny::req(nrow(d) > 0) sprintf("%.1f", max(d$CP, na.rm = TRUE)) }) output$ctrough <- renderText({ d <- sim_bundle()$interval_data shiny::req(nrow(d) > 0) sprintf("%.1f", d$CP[nrow(d)]) }) output$auc <- renderText({ d <- sim_bundle()$interval_data shiny::req(nrow(d) > 1) sprintf("%.1f", trap_auc(d$time_days, d$CP)) }) output$thalf <- renderText({ sprintf("%.1f", log(2) * 7.44 / 0.0739) }) output$plot_note <- renderText({ paste0( "Metrics are calculated over the final dosing interval after the last simulated dose. Current regimen: ", sim_bundle()$schedule$label ) }) output$pkPlot <- renderPlot({ bundle <- sim_bundle() d <- bundle$sim |> dplyr::filter(time_days <= bundle$plot_end) shiny::req(nrow(d) > 0) d_plot <- if (input$log_scale) { d |> dplyr::filter(CP > 0.001) } else { d } shiny::req(nrow(d_plot) > 0) dose_df <- data.frame(time_weeks = bundle$schedule$times / 7) p <- ggplot(d_plot, aes(x = time_weeks, y = CP)) + geom_vline(data = dose_df, aes(xintercept = time_weeks), color = "#cbd5e1", linetype = "dashed", linewidth = 0.4) + geom_line(color = "#8b5cf6", linewidth = 1) + labs( x = "Time (weeks)", y = "Plasma concentration (ug/mL)", title = "ORKA-002 hidradenitis suppurativa concentration-time profile" ) + theme_minimal(base_size = 14) if (input$regimen == "single_320") { cmax_ref <- max(bundle$interval_data$CP, na.rm = TRUE) p <- p + geom_hline(yintercept = cmax_ref, color = "#10b981", linetype = "dotted", linewidth = 0.8) + annotate( "text", x = 2, y = cmax_ref * 1.07, label = paste0("Model-predicted single-dose Cmax ~", sprintf("%.1f", cmax_ref), " ug/mL"), color = "#10b981", hjust = 0, size = 3.4 ) } if (input$log_scale) { p <- p + scale_y_log10() } p }) output$model_info <- renderUI({ bundle <- sim_bundle() div( tags$h4("ORKA-002 — pragmatic HS-adjusted SC biologic PK model"), tags$p("This simulator implements the uploaded ORKA-002 manuscript summary as a one-compartment subcutaneous biologic model with first-order absorption."), tags$table( class = "info-grid", tags$tr(tags$td("Drug"), tags$td("ORKA-002")), tags$tr(tags$td("Class"), tags$td("Humanized IgG1 monoclonal antibody against IL-17A / IL-17F with YTE half-life extension")), tags$tr(tags$td("Route"), tags$td("Subcutaneous")), tags$tr(tags$td("Use case"), tags$td("Hidradenitis suppurativa exposure simulation")), tags$tr(tags$td("Model structure"), tags$td("1-compartment SC absorption model")), tags$tr(tags$td("Bioavailability (F)"), tags$td("0.70")), tags$tr(tags$td("Absorption rate (Ka)"), tags$td("0.542 day^-1")), tags$tr(tags$td("Effective volume (V)"), tags$td("7.44 L")), tags$tr(tags$td("Effective clearance (CL)"), tags$td("0.0739 L/day")), tags$tr(tags$td("Elimination rate constant"), tags$td("0.00993 day^-1")), tags$tr(tags$td("Terminal half-life"), tags$td("~69.8 days")), tags$tr(tags$td("Modeled regimen"), tags$td(bundle$schedule$label)) ), tags$div( class = "ref-box", tags$strong("Calibration notes"), tags$ul( tags$li("The uploaded summary states that the model was calibrated to a Phase 1 healthy-volunteer PK curve and a sponsor-reported half-life of 75 to 80 days."), tags$li("The HS version applies a disease-state exposure adjustment with higher clearance and higher volume, producing an HS-adjusted terminal half-life of about 70 days."), tags$li("This is a pragmatic exposure simulator intended for exploratory PK visualization, not a proprietary full population PK reconstruction.") ) ) ) }) output$references <- renderUI({ div( class = "ref-box", tags$h5("Key sources"), tags$ol( tags$li("Uploaded manuscript summary: ORKA-002 population PK summary for hidradenitis suppurativa (project file ORKA-002_HS.pdf)."), tags$li( tags$a(href = "https://orukatx.com/our-pipeline/", target = "_blank", "Oruka Therapeutics pipeline page"), " — confirms ORKA-002 as a half-life-extended IL-17A/F monoclonal antibody under Phase 1 development." ), tags$li( tags$a(href = "https://ir.orukatx.com/news-releases/news-release-details/oruka-therapeutics-announces-first-participants-dosed-phase-1-0", target = "_blank", "Oruka Phase 1 announcement"), " — supports the clinical development context and extended-dosing positioning." ) ), tags$h5("What this app covers"), tags$ul( tags$li("Subcutaneous ORKA-002 exposure under the manuscript's HS-adjusted regimen and custom fixed-interval regimens."), tags$li("Relative accumulation and washout across long-interval dosing schedules."), tags$li("Exploratory PK simulation only; no direct efficacy or safety threshold modeling.") ) ) }) } shinyApp(ui = ui, server = server)