---
title: "Risk Stratification and IOL Power Calculation Tool for Marfan Syndrome Patients with Ectopia Lentis"
author: Xinshen
date: 2025/05/17
date-format: long
filters:
- shinylive
---
```{shinylive-r}
#| standalone: true
#| viewerHeight: 200
library(shiny)
library(ggplot2)
library(shinyjs)
ui <- fluidPage(
useShinyjs(),
actionButton("cal", "Estimate IOL Power"),
imageOutput("img1_ui"),
imageOutput("img2_ui"),
imageOutput("img3_ui"),
uiOutput("words")
)
server <- function(input, output, session) {
rdata_file1 <- tempfile(fileext = ".png")
correct_url1 <- "https://raw.githubusercontent.com/XinshenFD/data-save/main/sup1.png"
download.file(correct_url1, destfile = rdata_file1, mode = "wb")
rdata_file2 <- tempfile(fileext = ".png")
correct_url2 <- "https://raw.githubusercontent.com/XinshenFD/data-save/main/Logo-Department.png"
download.file(correct_url2, destfile = rdata_file2, mode = "wb")
rdata_file3 <- tempfile(fileext = ".png")
correct_url3 <- "https://raw.githubusercontent.com/XinshenFD/data-save/main/sup2.png"
download.file(correct_url3, destfile = rdata_file3, mode = "wb")
output$img1_ui <- renderImage({
list(
src = rdata_file1,
contentType = "image/png",
style = "width:100%; height:auto;"
)
}, deleteFile = FALSE)
output$img2_ui <- renderImage({
list(
src = rdata_file2,
contentType = "image/png",
style = "width:100%; height:auto;"
)
}, deleteFile = FALSE)
output$img3_ui <- renderImage({
list(
src = rdata_file3,
contentType = "image/png",
style = "width:100%; height:auto;"
)
}, deleteFile = FALSE)
observeEvent(input$cal, {
shinyjs::show("img1_ui")
output$words <- renderUI({
HTML("Calculation completed!")
})
})
}
shinyApp(ui = ui, server = server)
```
```{shinylive-r}
#| standalone: true
#| viewerHeight: 2000
library(bslib)
library(shiny)
library(gt)
library(tidyverse)
library(magick)
library(shinyjs)
library(DT)
library(ggplot2)
#####IOL power calculation
######predicted ALP
ALP_min24 <- function(AL, K1, K2){
Km <- 2/(1/K1 + 1/K2)
CCR <- 337.5/Km
ALP <- 0.26755 *AL -0.35626 * CCR +1.56317
return(ALP)
}
##IOL : PCB00/ZCB00 = 1
##Procedure :MCTR = 1
ALP_maj24 <- function(WTW, Age, IOL, Procedure){
ALP <- 0.190810 * WTW + 0.007952 * Age + 0.297651 * IOL - 0.263585 * Procedure
return(ALP)
}
#####predicted ELP
ELP_min24 <- function(ALP, AL, K1, K2, WTW){
Km <- 2/(1/K1 + 1/K2)
CCR <- 337.5/Km
H <- CCR - ((CCR)^2 - ((WTW - 1)/2)^2)^(1/2)
ELP <- ALP *0.45967 + H * 0.79294 + AL *0.27593 -0.23519 *CCR -3.49273
return(ELP)
}
ELP_maj24 <- function(ALP, AL, K1, K2){
Km <- 2/(1/K1 + 1/K2)
CCR <- 337.5/Km
ELP <- ALP * 0.7368 + 0.3152 * AL -0.5416 * CCR -1.5633
return(ELP)
}
####adjust AL
AL_optimized_min24 <- function(AL){
AL_O <- 1.10766 * AL - 2.17799
return(AL_O)
}
AL_optimized_maj24 <- function(AL){
AL_O <- 0.99574 * AL + 0.53407
return(AL_O)
}
#######MFFF
refraction <- function(IOL_power, K1, K2, ELP, AL){
na <- 1.336
nc <- 1.333
ncm1 <- nc - 1
K <- 2/(1/K1 + 1/K2)
V <- 0.012
R <- (337.5/K)
R <- R*0.001
ELP <- ELP* 0.001
AL <- AL*0.001
m <- na/(AL - ELP) - IOL_power
mm <- na/m + ELP
mmm <- na/mm - (ncm1/R)
mmmm <- 1/mmm + V
ref <- 1/mmmm
return(ref)
}
######calculate IOL power
IOL_power_ref_0 <- function(K1, K2, ELP, AL){
na <- 1.336
nc <- 1.333
ncm1 <- nc - 1
K <- 2/(1/K1 + 1/K2)
V <- 0.012
R <- (337.5/K)
R <- R*0.001
ELP <- ELP* 0.001
AL <- AL*0.001
aa <- (na/(AL - ELP))
bb <- na/(na/(ncm1/R) - ELP)
P <- aa - bb
return(P)
}
IOL_power_ref <- function(ref, K1, K2, ELP, AL){
na <- 1.336
nc <- 1.333
ncm1 <- nc - 1
K <- 2/(1/K1 + 1/K2)
V <- 0.012
R <- (337.5/K)
R <- R*0.001
ELP <- ELP* 0.001
AL <- AL*0.001
aa <- (na/(AL - ELP))
cc <- ncm1/R + 1/(1/ref - V)
bb <- na/(na/cc - ELP)
P <- aa - bb
return(P)
}
####T2_optimizAL
refraction_T2 <- function(IOL_power, K1, K2, A, AL, AL_O){
na <- 1.336
nc <- 1.333
ncm1 <- nc - 1
K <- 2/(1/K1 + 1/K2)
V <- 0.012
R <- (337.5/K)
L <- AL
ifelse(
L <= 24.2,
LCOR <- L,
ifelse(L <36.2,
LCOR <- 1.716*L-3.446-0.0237*L*L,
LCOR <- 27.62)
)
H <- -10.326 + 0.32630 * AL + 0.13533 * K
ACDcon <- 0.62467*A - 68.747
offset_SRTK <- ACDcon - 3.336
ACDest <- (H + offset_SRTK) * 0.001
ACDest <- ACDest
rethick <- 0.65696 - 0.02020 * L
LOPT <- (L + rethick) * 0.001
R <- R *0.001
AL_O <- AL_O * 0.001
m <- na/(AL_O - ACDest) - IOL_power
mm <- na/m + ACDest
mmm <- na/mm - ncm1/R
mmmm <- 1/mmm + V
ref <- 1/mmmm
return(ref)
}
######calculate IOL power
IOL_power_ref_0_T2 <- function(K1, K2, A, AL_O, AL){
na <- 1.336
nc <- 1.333
ncm1 <- nc - 1
K <- 2/(1/K1 + 1/K2)
V <- 0.012
R <- (337.5/K)
L <- AL
ifelse(
L <= 24.2,
LCOR <- L,
ifelse(L <36.2,
LCOR <- 1.716*L-3.446-0.0237*L*L,
LCOR <- 27.62)
)
H <- -10.326 + 0.32630 * AL + 0.13533 * K
ACDcon <- 0.62467*A - 68.747
offset_SRTK <- ACDcon - 3.336
ACDest <- (H + offset_SRTK) * 0.001
ACDest <- ACDest
rethick <- 0.65696 - 0.02020 * L
LOPT <- (L + rethick) * 0.001
R <- R *0.001
ELP <- ACDest
AL_O <- AL_O * 0.001
aa <- (na/(AL_O - ELP))
bb <- na/(na/(ncm1/R) - ELP)
P <- aa - bb
return(P)
}
IOL_power_ref_T2 <- function(ref, K1, K2, AL_O, A, AL){
na <- 1.336
nc <- 1.333
ncm1 <- nc - 1
K <- 2/(1/K1 + 1/K2)
V <- 0.012
R <- (337.5/K)
L <- AL
ifelse(
L <= 24.2,
LCOR <- L,
ifelse(L <36.2,
LCOR <- 1.716*L-3.446-0.0237*L*L,
LCOR <- 27.62)
)
H <- -10.326 + 0.32630 * AL + 0.13533 * K
ACDcon <- 0.62467*A - 68.747
offset_SRTK <- ACDcon - 3.336
ACDest <- (H + offset_SRTK) * 0.001
ACDest <- ACDest
rethick <- 0.65696 - 0.02020 * L
LOPT <- (L + rethick) * 0.001
R <- R *0.001
ELP <- ACDest
AL_O <- AL_O * 0.001
aa <- (na/(AL_O - ELP))
cc <- ncm1/R + 1/(1/ref - V)
bb <- na/(na/cc - ELP)
P <- aa - bb
return(P)
}
Z_AL <- function(Age, AL){
aget <- Age
alt <- AL
Z_AL <- NA
Z_AL <- ifelse(aget >= 18,
(alt - 24.50)/1.03,
ifelse(aget >= 17,
(alt - 24.58)/1.14,
ifelse(aget >= 16,
(alt - 24.65)/1.22,
ifelse(aget>= 15,
(alt - 24.50)/1.21,
ifelse(aget>=14,
(alt - 24.41)/1.30,
ifelse(aget>=13,
(alt - 24.10)/1.17,
ifelse(aget>= 12,
(alt - 23.94)/1.08,
ifelse(aget>= 11,
(alt - 23.77)/1.03,
ifelse(aget>= 10,
(alt - 23.58)/1.01,
ifelse(
aget>= 9,
(alt - 23.34)/0.89,
ifelse(
aget>=8,
(alt - 23.06)/0.88,
ifelse(
aget>=7,
(alt - 22.76)/0.79,
ifelse(
aget>=6,
(alt - 22.49)/0.75,
ifelse(
aget>=5,
(alt - 22.31)/0.68,
ifelse(
aget>=4,
(alt - 22.15)/0.72,
ifelse(
aget>=3,
(alt - 22.10)/0.72,
cccc <- 1
)
)
)
)
)
)
)
)
)
)
)
))
)
))
return(Z_AL)
}
clustertree <- function(Age, Z_AL, AL, Apex, CCR){
cluster <- NA
cluster <- ifelse(Age <12 & Z_AL <1.5 & CCR <8.5,
"A",
ifelse(Age <12 & Z_AL <1.5 & CCR >= 8.5 & Apex >=526,
"A",
ifelse(Age <12 & Z_AL <1.5 & CCR >= 8.5 & Apex <526,
"B",
ifelse(Age <12 & Z_AL >= 1.5 & Z_AL >= 9,
"D",
ifelse(Age <12 & Z_AL >= 2.6 & Z_AL < 9 ,
"B",
ifelse(Age <12 & Z_AL >= 1.5 & Z_AL < 2.6 &CCR<8.1,
"A",
ifelse(
Age <12 & Z_AL >= 1.5 & Z_AL < 2.6 &CCR>=8.1 &Apex >= 577,
"A",
ifelse(Age <12 & Z_AL >= 1.5 & Z_AL < 2.6 &CCR>=8.1 &Apex < 577,
"B",
ifelse(
Age >= 12 & AL <28,
"C",
"D"
)
)
)
)
)
)
)
))
return(cluster)
}
# Define UI for application that draws a histogram
gender_female_male <- c("Female", "Male")
eye_side <- c("Right", "Left")
procedures <- c("MCTR", "CTR-CH", "SF-IOL")
ui <- page_fixed(
useShinyjs(),
tags$style( "
html, body {
max-width: 1300px; /* 设置页面最大宽度 */
margin: auto; /* 居中 */
width: 100%; /* 确保宽度为 100% */
}
"),
layout_columns(
col_widths = c(4, 8),
card(
full_screen = TRUE,
imageOutput("img1_ui",, inline = TRUE),
style = "margin-top: 10px; display: flex; justify-content: center; align-items: center;"
),
card_body(
# 使用 HTML 和 CSS 来设置字号、居中、首行缩进和两侧对齐
HTML(
'
Welcome to the MFS with EL Clustering Tool! This website provides an innovative platform for risk stratification and treatment decision-making for patients with Marfan syndrome and ectopia lentis. Based on data from the EL cohort, our research leverages machine learning to identify four distinct clinical phenotypes, offering valuable insights into prognosis and therapeutic response. By integrating real-world data and combining it with published IOL power calculation tools, the platform supports clinicians in tailoring personalized treatment strategies, including postoperative PCO risk estimation and IOL power calculation.
'
)
)
)
,
card(
full_screen = TRUE,
card_body(
fluidRow(
column(4, textInput("name", label = span("Patient's name", class = "label custom-input"), value = "")),
column(4, dateInput("dob", label = span("Patient's birthday", class = "label custom-input"), value = "1993-12-22")),
column(4, selectInput("Gender", label = span("Patient's gender", class = "label custom-input"), gender_female_male))
),
fluidRow(
column(4, selectInput("eyeside", label = span("Laterality", class = "label custom-input"), eye_side)),
column(4, textInput("surger", label = span("Doctor's name", class = "label custom-input"), value = "")),
column(4, dateInput("Sob", label = span("Surgery date", class = "label custom-input"), value = "2025-5-15"))
),
fluidRow(
column(4, numericInput("AL", label = span("AL (mm)", class = "label custom-input"), value = "24.03", step = 0.01)),
column(4, numericInput("WTW", label = span("WTW (mm)", class = "label custom-input"), value = "12.32", step = 0.01)),
column(4, numericInput("APEX", label = span("APEX (µm)", class = "label custom-input"), value = "553",step = 1))
),
fluidRow(
column(4, numericInput("K1", label = span("K1 (D)", class = "label custom-input"), value = "41.21",step = 0.01)),
column(4, numericInput("K2", label = span("K2 (D)", class = "label custom-input"), value = "42.33",step = 0.01)),
column(4, numericInput("ref", label = span("Target refraction (D)", class = "label custom-input"), value = "-1",step = 0.01))
),
fluidRow(
column(4,offset = 2, selectInput("procedure",label = span( "Procedure", class = "label custom-input"),choices = c("MCTR", "CTR-CH",
"SF-IOL"))),
column(4, selectInput("IOL_type",label = span( "IOL", class = "label custom-input"),
choices = c("DCB00/ICB00/ZCB00", "SN60AT/SN60WF","Rayner 920H/970C"))
)
)))
,
card(
actionButton("cal", label = span("Extimate cluster and calculate IOL power",class = "label custom-input"), class = "btn-success",
icon = shiny::icon("calculator"))
),
tags$div(
id = "plot_div",
style = "display:none;",
layout_columns(
col_widths = c(4, 8),
card(
div(
style = "display: flex; justify-content: center; align-items: center; height: 100%;",
uiOutput("words_cluster")
)
),
card(
div(
style = "margin-top: 10px; display: flex; justify-content: center; align-items: center;",
imageOutput("PCO_sur", inline = TRUE)
)
)
)
),
tags$div(
style = "display: flex; justify-content: center; align-items: center; height: 100%;",
uiOutput("conditional_layout")
)
)
server <- function(input, output, session) {
rdata_file1 <- tempfile(fileext = ".png")
correct_url1 <- "https://raw.githubusercontent.com/XinshenFD/data-save/main/sup1.png"
download.file(correct_url1, destfile = rdata_file1, mode = "wb")
rdata_file2 <- tempfile(fileext = ".png")
correct_url2 <- "https://raw.githubusercontent.com/XinshenFD/data-save/main/Logo-Department.png"
download.file(correct_url2, destfile = rdata_file2, mode = "wb")
rdata_file3 <- tempfile(fileext = ".png")
correct_url3 <- "https://raw.githubusercontent.com/XinshenFD/data-save/main/sup2.png"
download.file(correct_url3, destfile = rdata_file3, mode = "wb")
observeEvent(input$procedure, {
if (input$procedure %in% c("MCTR", "CTR-CH")) {
# If the first input is A or B, update second input to D and E
updateSelectInput(session, "IOL_type", choices = c("DCB00/ICB00/ZCB00", "SN60AT/SN60WF"))
} else if (input$procedure == "SF-IOL") {
# If the first input is C, update second input to F
updateSelectInput(session, "IOL_type", choices = "Rayner 920H/970C")
}
})
observeEvent(input$cal, {
shinyjs::show(id = "plot_div")
})
calculateValues <- eventReactive(input$cal, {
if(input$Gender == "Female") {
gg <- 0
} else {
gg <- 1
}
today <- Sys.Date()
dob <- as.Date(input$dob)
surgery_date <- as.Date(input$Sob)
aa <- as.numeric(difftime(surgery_date, dob, units = "days")) / 365.25
ccrz <- 337.5/(2/(1/input$K1 + 1/input$K2))
# 执行全部计算逻辑,并将结果作为列表返回
ALP_M_P = if(input$AL > 24) {
ALP_maj24(WTW = input$WTW, Age = aa, IOL = 1, Procedure = 1)
} else {
ALP_min24(AL = input$AL, K1 = input$K1, K2 = input$K2 )
}
ALP_M_S = if(input$AL > 24) {
ALP_maj24(WTW = input$WTW, Age = aa, IOL = 0, Procedure = 1)
} else {
ALP_min24(AL = input$AL, K1 = input$K1, K2 = input$K2 )
}
ALP_C_P = if(input$AL > 24) {
ALP_maj24(WTW = input$WTW, Age = aa, IOL = 1, Procedure = 0)
} else {
ALP_min24(AL = input$AL, K1 = input$K1, K2 = input$K2 )
}
ALP_C_S = if(input$AL > 24) {
ALP_maj24(WTW = input$WTW, Age = aa, IOL = 0, Procedure = 0)
} else {
ALP_min24(AL = input$AL, K1 = input$K1, K2 = input$K2 )
}
ELP_M_P = if(input$AL > 24) {
ELP_maj24(ALP = ALP_M_P, AL = input$AL, K1 = input$K1, K2 = input$K2)
} else {
ELP_min24(ALP = ALP_M_P, AL = input$AL, K1 = input$K1, K2 = input$K2,
WTW = input$WTW)
}
ELP_M_S = if(input$AL > 24) {
ELP_maj24(ALP = ALP_M_S, AL = input$AL, K1 = input$K1, K2 = input$K2)
} else {
ELP_min24(ALP = ALP_M_S, AL = input$AL, K1 = input$K1, K2 = input$K2,
WTW = input$WTW)
}
ELP_C_P = if(input$AL > 24) {
ELP_maj24(ALP = ALP_C_P, AL = input$AL, K1 = input$K1, K2 = input$K2)
} else {
ELP_min24(ALP = ALP_C_P, AL = input$AL, K1 = input$K1, K2 = input$K2,
WTW = input$WTW)
}
ELP_C_S = if(input$AL > 24) {
ELP_maj24(ALP = ALP_C_S, AL = input$AL, K1 = input$K1, K2 = input$K2)
} else {
ELP_min24(ALP = ALP_C_S, AL = input$AL, K1 = input$K1, K2 = input$K2,
WTW = input$WTW)
}
AL_optimized = if(input$AL > 24) {
AL_optimized_maj24(AL = input$AL)
} else {
AL_optimized_min24(AL = input$AL)
}
ZAL = Z_AL(Age = aa,
AL = input$AL)
clus = clustertree(AL = input$AL,
Z_AL = ZAL,
Age = aa,
Apex = input$APEX,
CCR = ccrz
)
return(list(
ALP_M_P = ALP_M_P,
ALP_M_S = ALP_M_S,
ALP_C_P = ALP_C_P,
ALP_C_S = ALP_C_S,
ELP_M_P = ELP_M_P,
ELP_M_S = ELP_M_S,
ELP_C_P = ELP_C_P,
ELP_C_S = ELP_C_S,
AL_optimized = AL_optimized,
aa = aa,
ZAL = ZAL,
clus = clus
))
}
)
table_reactive <- eventReactive(input$cal,{
values <- calculateValues()
aa <- values$aa
clus <- values$clus
if(aa <= 15){
if(clus == "A"){
AL_15 <- 1.67 * log10(aa +0.6) +21.71
}else{
if(clus == "B"){
AL_15 <- 7.2 * log10(aa +0.6) +19.69
}else{
AL_15 <- input$AL
}
}
}else(
AL_15 <- input$AL
)
if(AL_15 > 24) {
AL_optimized_15 <-AL_optimized_maj24(AL = AL_15)
} else {
AL_optimized_15 <-AL_optimized_min24(AL = AL_15)
}
table_M_S <- data.frame(x = c(NA, NA, NA, NA, NA, NA),
y = NA, z = NA, d = NA, e = NA,
f = NA, g =NA, t = NA, n = NA)
colnames(table_M_S) <- c("IOL", "IOL Power", "Refraction",
"AL", "K1", "K2", "WTW", "Gender", "ELP")
table_M_S$IOL <- "SN60AT/SN60WT"
table_M_S$AL <- input$AL
table_M_S$K1 <- input$K1
table_M_S$K2 <- input$K2
table_M_S$WTW <- input$WTW
table_M_S$Gender <- input$Gender
table_M_S$ELP <- values$ELP_M_S
IOLPref0_M_S <- IOL_power_ref_0(AL = input$AL,
K1 = input$K1,
K2 = input$K2,
ELP = values$ELP_M_S)
table_M_S[6, 2] <- IOLPref0_M_S
table_M_S[6, 3] <- 0
if(input$ref == 0){
med_IOLP_M_S <- as.numeric((round(IOLPref0_M_S/0.5))*0.5)
M_S_list <- c(med_IOLP_M_S +1, med_IOLP_M_S+0.5, med_IOLP_M_S, med_IOLP_M_S-0.5,med_IOLP_M_S-1)
table_M_S[1:5, 2] <- M_S_list
table_M_S[1:5, 3] <- refraction(
IOL_power = table_M_S[1:5, 2],
K1 = table_M_S[1:5, 5],
K2 = table_M_S[1:5, 6],
ELP = table_M_S[1:5, 9],
AL = table_M_S[1:5, 4])}else{
IOLP_M_S_ref <- IOL_power_ref(
ref = input$ref,
K1 = input$K1,
K2 = input$K2,
ELP = values$ELP_M_S,
AL = input$AL
)
med_IOLP_M_S <- as.numeric((round(IOLP_M_S_ref/0.5))*0.5)
M_S_list <- c(med_IOLP_M_S +1, med_IOLP_M_S+0.5, med_IOLP_M_S, med_IOLP_M_S-0.5,med_IOLP_M_S-1)
table_M_S[1:5, 2] <- M_S_list
table_M_S[1:5, 3] <- refraction(
IOL_power = table_M_S[1:5, 2],
K1 = table_M_S[1:5, 5],
K2 = table_M_S[1:5, 6],
ELP = table_M_S[1:5, 9],
AL = table_M_S[1:5, 4])}
tableM_S <- table_M_S
tableM_S <- tableM_S[, 2:3]
tableM_S_15 <- tableM_S
tableM_S_15$`Refraction at 15y` <- refraction(
IOL_power = tableM_S_15[,1],
K1 = input$K1,
K2 = input$K2,
ELP = values$ELP_M_S,
AL = AL_15)
tableM_S <- as.data.frame(tableM_S)
tableM_S[, 1] <- round(tableM_S[, 1], 2)
tableM_S[, 2] <- round(tableM_S[, 2], 2)
tableM_S_15 <- as.data.frame(tableM_S_15)
tableM_S_15[,1] <- round(tableM_S_15[,1],2)
tableM_S_15[,2]<- round(tableM_S_15[,2],2)
tableM_S_15[,3]<- round(tableM_S_15[,3],2)
table_M_P <- data.frame(x = c(NA, NA, NA, NA, NA, NA),
y = NA, z = NA, d = NA, e = NA,
f = NA, g =NA, t = NA, n = NA)
colnames(table_M_P) <- c("IOL", "IOL Power", "Refraction",
"AL", "K1", "K2", "WTW", "Gender", "ELP")
table_M_P$IOL <- "SN60AT/SN60WT"
table_M_P$AL <- input$AL
table_M_P$K1 <- input$K1
table_M_P$K2 <- input$K2
table_M_P$WTW <- input$WTW
table_M_P$Gender <- input$Gender
table_M_P$ELP <- values$ELP_M_P
IOLPref0_M_P <- IOL_power_ref_0(AL = input$AL,
K1 = input$K1,
K2 = input$K2,
ELP = values$ELP_M_P)
table_M_P[6, 2] <- IOLPref0_M_P
table_M_P[6, 3] <- 0
if(input$ref == 0){
med_IOLP_M_P <- as.numeric((round(IOLPref0_M_P/0.5))*0.5)
M_P_list <- c(med_IOLP_M_P +1, med_IOLP_M_P+0.5, med_IOLP_M_P, med_IOLP_M_P-0.5,med_IOLP_M_P-1)
table_M_P[1:5, 2] <- M_P_list
table_M_P[1:5, 3] <- refraction(
IOL_power = table_M_P[1:5, 2],
K1 = table_M_P[1:5, 5],
K2 = table_M_P[1:5, 6],
ELP = table_M_P[1:5, 9],
AL = table_M_P[1:5, 4])}else{
IOLP_M_P_ref <- IOL_power_ref(
ref = input$ref,
K1 = input$K1,
K2 = input$K2,
ELP = values$ELP_M_P,
AL = input$AL
)
med_IOLP_M_P <- as.numeric((round(IOLP_M_P_ref/0.5))*0.5)
M_P_list <- c(med_IOLP_M_P +1, med_IOLP_M_P+0.5, med_IOLP_M_P, med_IOLP_M_P-0.5,med_IOLP_M_P-1)
table_M_P[1:5, 2] <- M_P_list
table_M_P[1:5, 3] <- refraction(
IOL_power = table_M_P[1:5, 2],
K1 = table_M_P[1:5, 5],
K2 = table_M_P[1:5, 6],
ELP = table_M_P[1:5, 9],
AL = table_M_P[1:5, 4])}
tableM_P <- table_M_P
tableM_P <- tableM_P[, 2:3]
tableM_P_15 <- tableM_P
tableM_P_15$`Refraction at 15y` <- refraction(
IOL_power = tableM_P_15[,1],
K1 = input$K1,
K2 = input$K2,
ELP = values$ELP_M_P,
AL = AL_15)
tableM_P <- as.data.frame(tableM_P)
tableM_P[, 1] <- round(tableM_P[, 1], 2)
tableM_P[, 2] <- round(tableM_P[, 2], 2)
tableM_P_15 <- as.data.frame(tableM_P_15)
tableM_P_15[,1] <- round(tableM_P_15[,1],2)
tableM_P_15[,2]<- round(tableM_P_15[,2],2)
tableM_P_15[,3]<- round(tableM_P_15[,3],2)
table_C_S <- data.frame(x = c(NA, NA, NA, NA, NA, NA),
y = NA, z = NA, d = NA, e = NA,
f = NA, g =NA, t = NA, n = NA)
colnames(table_C_S) <- c("IOL", "IOL Power", "Refraction",
"AL", "K1", "K2", "WTW", "Gender", "ELP")
table_C_S$IOL <- "SN60AT/SN60WT"
table_C_S$AL <- input$AL
table_C_S$K1 <- input$K1
table_C_S$K2 <- input$K2
table_C_S$WTW <- input$WTW
table_C_S$Gender <- input$Gender
table_C_S$ELP <- values$ELP_C_S
IOLPref0_C_S <- IOL_power_ref_0(AL = input$AL,
K1 = input$K1,
K2 = input$K2,
ELP = values$ELP_C_S)
table_C_S[6, 2] <- IOLPref0_C_S
table_C_S[6, 3] <- 0
if(input$ref == 0){
med_IOLP_C_S <- as.numeric((round(IOLPref0_C_S/0.5))*0.5)
C_S_list <- c(med_IOLP_C_S +1, med_IOLP_C_S+0.5, med_IOLP_C_S, med_IOLP_C_S-0.5,med_IOLP_C_S-1)
table_C_S[1:5, 2] <- C_S_list
table_C_S[1:5, 3] <- refraction(
IOL_power = table_C_S[1:5, 2],
K1 = table_C_S[1:5, 5],
K2 = table_C_S[1:5, 6],
ELP = table_C_S[1:5, 9],
AL = table_C_S[1:5, 4])}else{
IOLP_C_S_ref <- IOL_power_ref(
ref = input$ref,
K1 = input$K1,
K2 = input$K2,
ELP = values$ELP_C_S,
AL = input$AL
)
med_IOLP_C_S <- as.numeric((round(IOLP_C_S_ref/0.5))*0.5)
C_S_list <- c(med_IOLP_C_S +1, med_IOLP_C_S+0.5, med_IOLP_C_S, med_IOLP_C_S-0.5,med_IOLP_C_S-1)
table_C_S[1:5, 2] <- C_S_list
table_C_S[1:5, 3] <- refraction(
IOL_power = table_C_S[1:5, 2],
K1 = table_C_S[1:5, 5],
K2 = table_C_S[1:5, 6],
ELP = table_C_S[1:5, 9],
AL = table_C_S[1:5, 4])}
tableC_S <- table_C_S
tableC_S <- tableC_S[, 2:3]
tableC_S_15 <- tableC_S
tableC_S_15$`Refraction at 15y` <- refraction(
IOL_power = tableC_S_15[,1],
K1 = input$K1,
K2 = input$K2,
ELP = values$ELP_C_S,
AL = AL_15)
tableC_S <- as.data.frame(tableC_S)
tableC_S[, 1] <- round(tableC_S[, 1], 2)
tableC_S[, 2] <- round(tableC_S[, 2], 2)
tableC_S_15 <- as.data.frame(tableC_S_15)
tableC_S_15[,1] <- round(tableC_S_15[,1],2)
tableC_S_15[,2]<- round(tableC_S_15[,2],2)
tableC_S_15[,3]<- round(tableC_S_15[,3],2)
table_C_P <- data.frame(x = c(NA, NA, NA, NA, NA, NA),
y = NA, z = NA, d = NA, e = NA,
f = NA, g =NA, t = NA, n = NA)
colnames(table_C_P) <- c("IOL", "IOL Power", "Refraction",
"AL", "K1", "K2", "WTW", "Gender", "ELP")
table_C_P$IOL <- "SN60AT/SN60WT"
table_C_P$AL <- input$AL
table_C_P$K1 <- input$K1
table_C_P$K2 <- input$K2
table_C_P$WTW <- input$WTW
table_C_P$Gender <- input$Gender
table_C_P$ELP <- values$ELP_C_P
IOLPref0_C_P <- IOL_power_ref_0(AL = input$AL,
K1 = input$K1,
K2 = input$K2,
ELP = values$ELP_C_P)
table_C_P[6, 2] <- IOLPref0_C_P
table_C_P[6, 3] <- 0
if(input$ref == 0){
med_IOLP_C_P <- as.numeric((round(IOLPref0_C_P/0.5))*0.5)
C_P_list <- c(med_IOLP_C_P +1, med_IOLP_C_P+0.5, med_IOLP_C_P, med_IOLP_C_P-0.5,med_IOLP_C_P-1)
table_C_P[1:5, 2] <- C_P_list
table_C_P[1:5, 3] <- refraction(
IOL_power = table_C_P[1:5, 2],
K1 = table_C_P[1:5, 5],
K2 = table_C_P[1:5, 6],
ELP = table_C_P[1:5, 9],
AL = table_C_P[1:5, 4])}else{
IOLP_C_P_ref <- IOL_power_ref(
ref = input$ref,
K1 = input$K1,
K2 = input$K2,
ELP = values$ELP_C_P,
AL = input$AL
)
med_IOLP_C_P <- as.numeric((round(IOLP_C_P_ref/0.5))*0.5)
C_P_list <- c(med_IOLP_C_P +1, med_IOLP_C_P+0.5, med_IOLP_C_P, med_IOLP_C_P-0.5,med_IOLP_C_P-1)
table_C_P[1:5, 2] <- C_P_list
table_C_P[1:5, 3] <- refraction(
IOL_power = table_C_P[1:5, 2],
K1 = table_C_P[1:5, 5],
K2 = table_C_P[1:5, 6],
ELP = table_C_P[1:5, 9],
AL = table_C_P[1:5, 4])}
tableC_P <- table_C_P
tableC_P <- tableC_P[, 2:3]
tableC_P_15 <- tableC_P
tableC_P_15$`Refraction at 15y` <- refraction(
IOL_power = tableC_P_15[,1],
K1 = input$K1,
K2 = input$K2,
ELP = values$ELP_C_P,
AL = AL_15)
tableC_P <- as.data.frame(tableC_P)
tableC_P[, 1] <- round(tableC_P[, 1], 2)
tableC_P[, 2] <- round(tableC_P[, 2], 2)
tableC_P_15 <- as.data.frame(tableC_P_15)
tableC_P_15[,1] <- round(tableC_P_15[,1],2)
tableC_P_15[,2]<- round(tableC_P_15[,2],2)
tableC_P_15[,3]<- round(tableC_P_15[,3],2)
table_R <- data.frame(x = c(NA, NA, NA, NA, NA, NA),
y = NA, z = NA, d = NA, e = NA,
f = NA, g =NA, t = NA, n = NA)
colnames(table_R) <- c("IOL", "IOL Power", "Refraction",
"AL", "K1", "K2", "WTW", "Gender", "ALP_O")
table_R$IOL <- "SN60AT/SN60WT"
table_R$AL <- input$AL
table_R$K1 <- input$K1
table_R$K2 <- input$K2
table_R$WTW <- input$WTW
table_R$Gender <- input$Gender
table_R$ALP_O <- values$AL_optimized
IOLPref0_R <- IOL_power_ref_0_T2(AL = input$AL,
K1 = input$K1,
K2 = input$K2,
AL_O = values$AL_optimized,
A = 118.3)
table_R[6, 2] <- IOLPref0_R
table_R[6, 3] <- 0
if(input$ref == 0){
med_IOLP_R <- as.numeric((round(IOLPref0_R/0.5))*0.5)
R_list <- c(med_IOLP_R +1, med_IOLP_R+0.5, med_IOLP_R, med_IOLP_R-0.5,med_IOLP_R-1)
table_R[1:5, 2] <- R_list
table_R[1:5, 3] <- refraction_T2(
IOL_power = table_R[1:5, 2],
K1 = table_R[1:5, 5],
K2 = table_R[1:5, 6],
AL_O = table_R[1:5, 9],
AL = table_R[1:5, 4],
A = 118.3)}else{
IOLP_R_ref <- IOL_power_ref_T2(
ref = input$ref,
K1 = input$K1,
K2 = input$K2,
AL_O = values$AL_optimized,
AL = input$AL,
A = 118.3
)
med_IOLP_R <- as.numeric((round(IOLP_R_ref/0.5))*0.5)
R_list <- c(med_IOLP_R +1, med_IOLP_R+0.5, med_IOLP_R, med_IOLP_R-0.5,med_IOLP_R-1)
table_R[1:5, 2] <- R_list
table_R[1:5, 3] <- refraction_T2(
IOL_power = table_R[1:5, 2],
K1 = table_R[1:5, 5],
K2 = table_R[1:5, 6],
AL_O = table_R[1:5, 9],
AL = table_R[1:5, 4],
A = 118.3)
}
tableR <- table_R
tableR <- tableR[, 2:3]
tableR_15 <- tableR
tableR_15$`Refraction at 15y` <- refraction_T2(
IOL_power = tableR_15[,1],
K1 = input$K1,
K2 = input$K2,
AL_O = AL_optimized_15,
AL = AL_15,
A = 118.3)
tableR <- as.data.frame(tableR)
tableR[, 1] <- round(tableR[, 1], 2)
tableR[, 2] <- round(tableR[, 2], 2)
tableR_15 <- as.data.frame(tableR_15)
tableR_15[,1] <- round(tableR_15[,1],2)
tableR_15[,2]<- round(tableR_15[,2],2)
tableR_15[,3]<- round(tableR_15[,3],2)
table <- if(aa > 15){if(input$procedure == "MCTR" & input$IOL_type == "DCB00/ICB00/ZCB00"){
table <- tableM_P
} else if(input$procedure == "MCTR" & input$IOL_type == "SN60AT/SN60WF"){
table <- tableM_S
} else if(input$procedure == "CTR-CH" & input$IOL_type == "DCB00/ICB00/ZCB00"){
table <- tableC_P
} else if(input$procedure == "CTR-CH" & input$IOL_type == "SN60AT/SN60WF"){
table <- tableC_S
} else if(input$procedure == "SF-IOL" & input$IOL_type == "Rayner 920H/970C"){
table <- tableR
}}else{
if(clus %in% c("C", "D")){
if(input$procedure == "MCTR" & input$IOL_type == "DCB00/ICB00/ZCB00"){
table <- tableM_P
} else if(input$procedure == "MCTR" & input$IOL_type == "SN60AT/SN60WF"){
table <- tableM_S
} else if(input$procedure == "CTR-CH" & input$IOL_type == "DCB00/ICB00/ZCB00"){
table <- tableC_P
} else if(input$procedure == "CTR-CH" & input$IOL_type == "SN60AT/SN60WF"){
table <- tableC_S
} else if(input$procedure == "SF-IOL" & input$IOL_type == "Rayner 920H/970C"){
table <- tableR
}
}else{
if(input$procedure == "MCTR" & input$IOL_type == "DCB00/ICB00/ZCB00"){
table <- tableM_P_15
} else if(input$procedure == "MCTR" & input$IOL_type == "SN60AT/SN60WF"){
table <- tableM_S_15
} else if(input$procedure == "CTR-CH" & input$IOL_type == "DCB00/ICB00/ZCB00"){
table <- tableC_P_15
} else if(input$procedure == "CTR-CH" & input$IOL_type == "SN60AT/SN60WF"){
table <- tableC_S_15
} else if(input$procedure == "SF-IOL" & input$IOL_type == "Rayner 920H/970C"){
table <- tableR_15
}
}
}
table
datatable(table,
selection = 'none') %>%
formatStyle(
columns = 1:ncol(table), # 应用到所有列
valueColumns = NULL, # 或者指定单列:比如 c('column_name')
target = 'row',
backgroundColor = styleEqual(3, '#D3D3D3')# 第三行的背景颜色加深
)%>%
formatStyle(
columns = 1:ncol(table), # 应用到所有列
valueColumns = NULL, # 或者指定单列:比如 c('column_name')
target = 'row',
backgroundColor = styleEqual(6, '#D3D3D3')# 第三行的背景颜色加深
)
# 返回处理和格式化后的 data.frame,以便用于渲染或传递
datatable(table, selection = 'none')
})
#A = 118.3
IOL_types <- eventReactive(input$cal, {
IOL_types <- c("PCB00/ZCB00","SN60AT/SN60WF")
})
words_M_P_val <- eventReactive(input$cal, {
# 构建 words_P 字符串或者 HTML 内容
HTML(paste0("MCTR","
",
"
",
"IOL: ", "PCB00/ZCB00", "
",
"
",
"Patient: ", input$name, "
",
"
",
"DOB: ", format(input$dob, "%Y-%m-%d"), "
",
"
",
"Doctor: ", input$surger, "
",
"
",
"Surgery Date: ", format(input$Sob, "%Y-%m-%d")))
})
words_M_S_val <- eventReactive(input$cal, {
# 构建 words_P 字符串或者 HTML 内容
HTML(paste0("MCTR","
",
"
",
"IOL: ", "SN60AT/SN60WF", "
",
"
",
"Patient: ", input$name, "
",
"
",
"DOB: ", format(input$dob, "%Y-%m-%d"), "
",
"
",
"Doctor: ", input$surger, "
",
"
",
"Surgery Date: ", format(input$Sob, "%Y-%m-%d")))
})
words_C_P_val <- eventReactive(input$cal, {
# 构建 words_P 字符串或者 HTML 内容
HTML(paste0("CTR-CH","
",
"
",
"IOL: ", "PCB00/ZCB00", "
",
"
",
"Patient: ", input$name, "
",
"
",
"DOB: ", format(input$dob, "%Y-%m-%d"), "
",
"
",
"Doctor: ", input$surger, "
",
"
",
"Surgery Date: ", format(input$Sob, "%Y-%m-%d")))
})
words_C_S_val <- eventReactive(input$cal, {
# 构建 words_P 字符串或者 HTML 内容
HTML(paste0("CTR-CH","
",
"
",
"IOL: ", "SN60AT/SN60WF", "
",
"
",
"Patient: ", input$name, "
",
"
",
"DOB: ", format(input$dob, "%Y-%m-%d"), "
",
"
",
"Doctor: ", input$surger, "
",
"
",
"Surgery Date: ", format(input$Sob, "%Y-%m-%d")))
})
words_R_val <- eventReactive(input$cal, {
# 构建 words_P 字符串或者 HTML 内容
HTML(paste0("SF-IOL","
",
"
",
"IOL: ", "SN60AT/SN60WF", "
",
"
",
"Patient: ", input$name, "
",
"
",
"DOB: ", format(input$dob, "%Y-%m-%d"), "
",
"
",
"Doctor: ", input$surger, "
",
"
",
"Surgery Date: ", format(input$Sob, "%Y-%m-%d")))
})
word_val <- eventReactive(input$cal, {
# 构建 words_P 字符串或者 HTML 内容
HTML(paste0("Patient: ", input$name, " ","DOB: ", format(input$dob, "%Y-%m-%d"), "
",
"
",
"Procedure:",input$procedure," ", "IOL: ", input$IOL_type, "
",
"
",
"Doctor: ", input$surger, " ","Surgery Date: ", format(input$Sob, "%Y-%m-%d")))
})
word_val_15 <- eventReactive(input$cal, {
values <- calculateValues()
aa <- values$aa
clus <- values$clus
if(aa <= 15){
if(clus == "A"){
AL_15 <- 1.67 * log10(aa +0.6) +21.71
}else{
if(clus == "B"){
AL_15 <- 7.2 * log10(aa +0.6) +19.69
}else{
AL_15 <- input$AL
}
}
}else(
AL_15 <- input$AL
)
AL_15 <- round(AL_15, 2)
# 构建 words_P 字符串或者 HTML 内容
HTML(paste0("Patient: ", input$name, " ","DOB: ", format(input$dob, "%Y-%m-%d"), "
",
"
",
"Procedure:",input$procedure," ", "IOL: ", input$IOL_type, "
",
"
",
"Doctor: ", input$surger, " ","Surgery Date: ", format(input$Sob, "%Y-%m-%d"),"
",
"
",
"The patient is expected to have AL of ", AL_15, "mm at the age of 15"))
})
#words_M_P,words_M_S,words_C_P, words_C_S, words_R
output$table <- renderDataTable({
table_reactive()
})
word_val_ff <- eventReactive(input$cal, {
today <- Sys.Date()
dob <- as.Date(input$dob)
surgery_date <- as.Date(input$Sob)
aa <- as.numeric(difftime(surgery_date, dob, units = "days")) / 365.25
values <- calculateValues()
clus <- values$clus
if(clus == "A") {
C_ph <- 0
} else {
if(clus %in% c("C","D")){
C_ph <- 3
}else{
C_ph <- 1
}}
if( aa >15 ){
word_val()
}else{
if(C_ph == 3){
word_val()
}else{
word_val_15()
}
}
})
output$words <- renderUI({
word_val_ff()
})
output$conditional_layout <- renderUI({
values <- calculateValues()
aa <- values$aa
clus <- values$clus
if (aa > 15 || clus %in% c("C", "D")) {
div(
style = "width: 100%; max-width: 1300px; margin: 0 auto;", # 外层容器最大1300px
card(
style = "width: 100%; max-width: 1300px; margin: 0 auto;", # card充满容器
fluidRow(
div(
style = "width: 600px; margin: 0 auto;", # 固定内容宽度600px
uiOutput("words")
)
),
fluidRow(
div(
style = "width: 600px; margin: 0 auto;", # 固定内容宽度600px
DTOutput("table")
)
)
)
)
} else {
div(
style = "width: 100%; max-width: 1300px; margin: 0 auto; margin-top: 20px;",
card(
fluidRow(
div(
style = "width: 600px; margin: 0 auto;",
uiOutput("words")
)
),
fluidRow(
column(
width = 6,
div(
style = "width: 550px;", # 表格区域固定宽度
DTOutput("table")
)
),
column(
width = 6,
imageOutput("cluster_image") # 动态显示图片
)
)
)
)
}
})
output$cluster_image <- renderImage({
list(
src = rdata_file3,
contentType = "image/png",
style = "width:100%; height:auto;"
)
}, deleteFile = FALSE)
output$words_cluster <- renderUI({
clus <- calculateValues()$clus
description <- switch(clus,
"A" = "Cluster A: Pediatric Patients with Ectopia Lentis and Minimal Other Ocular Features of Marfan Syndrome. This subtype primarily includes children under 12 years of age whose axial length (AL) is generally within the normal range for age. Some patients may exhibit mildly elongated AL but lack other characteristic features such as corneal flattening or thinning. Postoperative visual recovery in this group tends to be faster compared to Type B patients. The incidence of posterior capsular opacification (PCO) is similar to that of Type B, with approximately 30% requiring Nd:YAG laser treatment within two years after surgery.
",
"B" = "Cluster B: Pediatric Patients with Ectopia Lentis, Long Axial Length, Flat Cornea, and Thin Cornea. Also primarily involving children under 12 years, this subtype is characterized by significantly elongated AL compared to age-matched norms. Some patients may present with normal AL but exhibit other features such as a flatter and thinner cornea. Compared to Type A, visual recovery is slower in this group, while the incidence of PCO remains comparable, with about 30% of patients requiring laser capsulotomy within two years postoperatively.
",
"C" = "Cluster C: Adolescent and Adult Patients with Ectopia Lentis and Normal to Moderately Long Axial Length. This group includes patients aged 12 years and older, with axial lengths typically not exceeding 28 mm. Postoperative visual recovery in this subtype is the most rapid among all clusters, and the incidence of PCO is the lowest, with only approximately 13% of patients requiring laser treatment within two years after surgery.
",
"D" = "Cluster D: Patients with Ectopia Lentis and Markedly Elongated Axial Length. This subtype includes adults with AL greater than 28 mm and children whose AL is substantially longer than age-matched peers. These patients show the slowest postoperative visual improvement and the highest risk of PCO, with approximately 45% requiring Nd:YAG laser capsulotomy within two years postoperatively.
",
"No cluster information available.
"
)
HTML(description)
})
# PCO_sur 输出逻辑
output$PCO_sur <- -renderImage({
list(
src = rdata_file1,
contentType = "image/png",
style = "width:100%; height:auto;"
)
}, deleteFile = FALSE)
output$img1_ui <-renderImage({
list(
src = rdata_file2,
contentType = "image/png",
style = "width:100%; height:auto;"
)
}, deleteFile = FALSE)
}
shinyApp(ui = ui, server = server)
```
```{shinylive-r}
#| standalone: true
#| viewerHeight: 200
library(shiny)
library(ggplot2)
library(shinyjs)
ui <- fluidPage(
useShinyjs(),
actionButton("cal", "Estimate IOL Power"),
imageOutput("img1_ui"),
imageOutput("img2_ui"),
imageOutput("img3_ui"),
uiOutput("words")
)
server <- function(input, output, session) {
rdata_file1 <- tempfile(fileext = ".png")
correct_url1 <- "https://raw.githubusercontent.com/XinshenFD/data-save/main/sup1.png"
download.file(correct_url1, destfile = rdata_file1, mode = "wb")
rdata_file2 <- tempfile(fileext = ".png")
correct_url2 <- "https://raw.githubusercontent.com/XinshenFD/data-save/main/Logo-Department.png"
download.file(correct_url2, destfile = rdata_file2, mode = "wb")
rdata_file3 <- tempfile(fileext = ".png")
correct_url3 <- "https://raw.githubusercontent.com/XinshenFD/data-save/main/sup2.png"
download.file(correct_url3, destfile = rdata_file3, mode = "wb")
output$img1_ui <- renderImage({
list(
src = rdata_file1,
contentType = "image/png",
style = "width:100%; height:auto;"
)
}, deleteFile = FALSE)
output$img2_ui <- renderImage({
list(
src = rdata_file2,
contentType = "image/png",
style = "width:100%; height:auto;"
)
}, deleteFile = FALSE)
output$img3_ui <- renderImage({
list(
src = rdata_file3,
contentType = "image/png",
style = "width:100%; height:auto;"
)
}, deleteFile = FALSE)
observeEvent(input$cal, {
shinyjs::show("img1_ui")
output$words <- renderUI({
HTML("Calculation completed!")
})
})
}
shinyApp(ui = ui, server = server)
```