Dowmload libraries
library(survival)
library(survminer)
library(rms)
library(shiny)
library(readxl)
library(DynNom)
# You need to create an account in Shinyapps- they host DynNom apps. https://www.shinyapps.io/admin/#/login?redirect=%2Fdashboard
# DynNom documentation https://cran.r-project.org/web/packages/DynNom/DynNom.pdf
Nomogram
data <- read.csv("user/documents/data.csv")
ddist <- datadist(data)
options(datadist = 'ddist')
model <-
cph(
Surv(time = time, event = event) ~
x1 +
x2 +
x3,
data = data,
x = TRUE,
y = TRUE,
surv = TRUE,
time.inc = 5 ## time frame to evaluate
)
model$Design$label <-
c(
"Variable 1",
"Variable 2",
"Variable 3",
)
surv.model <- Survival(model)
nomogram <-
nomogram(
model,
fun = list(function(x)
surv.model(2, x), #add as many time frames as needed
funlabel = c(
"2-year risk"),
lp = F,
fun.at = c(0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2)
)
# to export as pdf
pdf(
"nomogram.pdf",
width = cm(17),
height = cm(10)
)
plot(
nomogram,
cex.axis = 4 ,
cex.var = 4.5 ,
col.grid = gray(c(0.8, 0.95)),
theme(text = element_text(
family = "Times New Roman",
face = "bold",
size = 20)
)
)
dev.off
Dynamic Nomogram
data <- read.csv("user/documents/data.csv")
ddist <- datadist(data)
options(datadist = 'ddist')
tool <- cph(
Surv(time = time, event = event) ~
x1 +
x2 +
x3,
data = data
)
DNbuilder( #this uses DynNom and will create 3 new files: ui.R, server.R, global.R. These will be the scripts needed to run the app.
tool,
data = data,
clevel = 0.95,
covariate = c("numeric"),
ptype = c("1-st") # or st
)
Example of DynNom scripts
GLOBAL.R
library(ggplot2)
library(shiny)
library(shinythemes)
library(plotly)
library(stargazer)
library(compare)
library(prediction)
library(rms)
library(shinythemes)
#######################################################
#### Before publishing your dynamic nomogram:
####
#### - You may need to edit the following lines if
#### data or model objects are not defined correctly
#### - You could modify ui.R or server.R for
#### making any required changes to your app
#######################################################
load('data.RData')
source('functions.R')
data=data
t.dist <- datadist(data)
options(datadist = 't.dist')
model <- coxph(Surv(Time, event) ~ x1 +x2 +x3 , data = data)
modellabels <- c("variable 1", "variable 2", "variable 3")
m.summary <- 'raw'
covariate <- 'numeric'
clevel <- 0.95
UI.R
ui = bootstrapPage(fluidPage(
theme=shinytheme("cyborg"),
titlePanel(
'gf'
),
p("This is an example.", style=" padding:10px; color: lightgrey; height: 60px",
br(),
br(),
"This is an example how to use it :", style="padding:20px; " ),
actionButton('showEligibility', 'Eligibility', style="color: black; background-color: lightblue; border-color: white"),
actionButton('showLimitations', 'Limitations', style="color: black; background-color: lightblue; border-color: white"),
actionButton('showPerformance', 'Performance', style="color: black; background-color: lightblue; border-color: white"),
actionButton('readArticle', 'Reference Manuscript', style="color: black; background-color: lightblue; border-color: white", onclick="window.open('https://drive.google.com/file/dk6UQT/view?usp=sharing', '_blank')"),
p("Instructions on how to use this tool can be found here:", style=" padding:20px; color: lightgrey;"),
actionButton('showHowtouse', "How to use",style="color: white; background-color:green; border-color: white"),
br(),
br(),
sidebarLayout(
sidebarPanel(
uiOutput('manySliders.f'),
uiOutput('manySliders.n'),
checkboxInput('trans', 'Ready!', value = FALSE),
actionButton('add', 'Predict', style="color: white; background-color: green;, border-color: white"),
style="color: black; background-color: #298AAE ; border-color: black"),
mainPanel(
tabsetPanel(
id = 'tabs',
tabPanel('Predicted Survival', plotOutput('plot')),
tabPanel('95% Confidence Interval', plotlyOutput('plot2')),
tabPanel('Numerical Summary', verbatimTextOutput('data.pred')),
sidebarPanel(
p("How to interpret the results?", style="color: lightgrey;"),
actionButton('showInterpret', "Interpret",style="color: white; background-color:green; border-color: white")
)
)
)
)))
Server.R
server = function(input, output) {
observeEvent(input$showPerformance, {
showModal(modalDialog(
title = "Performance",
p(
"This is an example."
),
easyClose = TRUE
))
})
observeEvent(input$showHowtouse, {
showModal(
modalDialog(
title = "How to use", style="color: white; background-color: black; border-color: black",
p(
"This is a step-by-step guide on how to use this interactive clinical tool.",
tags$br(),
tags$br(),
"Once",tags$strong("all"), "the boxes are filled-in, check the", tags$strong("'Ready!'"), "box and click",
tags$strong("'Predict.'")),
easyClose = TRUE
))
})
neededVar <- n.mterms[-1]
if (length(mtermslab) == 1) {
input.data <<- data.frame(data[1, neededVar])
names(input.data)[1] <<- n.mterms[-1]
} else {
input.data <<- data[1, neededVar]
}
input.data[1, ] <<- NA
b <- 1
i.factor <- NULL
i.numeric <- NULL
for (j in 2:length(mterms)) {
for (i in 1:length(data)) {
if (n.mterms[j] == names(data)[i]) {
if (mterms[[j]] == 'factor' |
mterms[[j]] == 'ordered' |
mterms[[j]] == 'logical') {
i.factor <- rbind(i.factor, c(n.mterms[j], j, i, b))
(break)()
}
if (mterms[[j]] == 'numeric') {
i.numeric <- rbind(i.numeric, c(n.mterms[j], j, i))
b <- b
(break)()
}
#etc etc
LS0tCnRpdGxlOiAiTm9tb2dyYW0gYW5kIG9ubGluZSB0b29sIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKLS0tCgoKIyMjRG93bWxvYWQgbGlicmFyaWVzCgpgYGB7cn0KbGlicmFyeShzdXJ2aXZhbCkKbGlicmFyeShzdXJ2bWluZXIpCmxpYnJhcnkocm1zKQpsaWJyYXJ5KHNoaW55KQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShEeW5Ob20pCiMgWW91IG5lZWQgdG8gY3JlYXRlIGFuIGFjY291bnQgaW4gU2hpbnlhcHBzLSB0aGV5IGhvc3QgRHluTm9tIGFwcHMuIGh0dHBzOi8vd3d3LnNoaW55YXBwcy5pby9hZG1pbi8jL2xvZ2luP3JlZGlyZWN0PSUyRmRhc2hib2FyZAojIER5bk5vbSBkb2N1bWVudGF0aW9uIGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9EeW5Ob20vRHluTm9tLnBkZgpgYGAKCiMjTm9tb2dyYW0KYGBge3IsIHdhcm5pbmc9IEZBTFNFfSAKCmRhdGEgPC0gcmVhZC5jc3YoInVzZXIvZG9jdW1lbnRzL2RhdGEuY3N2IikKCmRkaXN0IDwtIGRhdGFkaXN0KGRhdGEpCm9wdGlvbnMoZGF0YWRpc3QgPSAnZGRpc3QnKQoKbW9kZWwgPC0KICBjcGgoCiAgICBTdXJ2KHRpbWUgPSB0aW1lLCBldmVudCA9IGV2ZW50KSB+IAogICAgICB4MSArIAogICAgICB4MiArIAogICAgICB4MywKICAgIGRhdGEgPSBkYXRhLAogICAgeCA9IFRSVUUsCiAgICB5ID0gVFJVRSwKICAgIHN1cnYgPSBUUlVFLAogICAgdGltZS5pbmMgPSA1ICMjIHRpbWUgZnJhbWUgdG8gZXZhbHVhdGUgCikKCm1vZGVsJERlc2lnbiRsYWJlbCA8LQogIGMoCiAgICAiVmFyaWFibGUgMSIsCiAgICAiVmFyaWFibGUgMiIsCiAgICAiVmFyaWFibGUgMyIsCiAgKQoKc3Vydi5tb2RlbCA8LSBTdXJ2aXZhbChtb2RlbCkKCm5vbW9ncmFtIDwtCiAgbm9tb2dyYW0oCiAgICBtb2RlbCwKICAgIGZ1biA9IGxpc3QoZnVuY3Rpb24oeCkKICAgICAgc3Vydi5tb2RlbCgyLCB4KSwgI2FkZCBhcyBtYW55IHRpbWUgZnJhbWVzIGFzIG5lZWRlZAogICAgICBmdW5sYWJlbCA9IGMoCiAgICAgICIyLXllYXIgcmlzayIpLAogICAgICBscCA9IEYsCiAgICAgIGZ1bi5hdCA9IGMoMC45LCAwLjgsIDAuNywgMC42LCAwLjUsIDAuNCwgMC4zLCAwLjIpCiAgICAgICkKICAgIAojIHRvIGV4cG9ydCBhcyBwZGYgCgpwZGYoCiAgIm5vbW9ncmFtLnBkZiIsCiAgd2lkdGggPSBjbSgxNyksCiAgaGVpZ2h0ID0gY20oMTApCikKCnBsb3QoCiAgbm9tb2dyYW0sCiAgY2V4LmF4aXMgPSA0ICwKICBjZXgudmFyID0gNC41ICwKICBjb2wuZ3JpZCA9IGdyYXkoYygwLjgsIDAuOTUpKSwKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KAogICAgZmFtaWx5ID0gIlRpbWVzIE5ldyBSb21hbiIsCiAgICBmYWNlID0gImJvbGQiLAogICAgc2l6ZSA9IDIwKQogICAgKQogICkKCmRldi5vZmYKCgpgYGAKIyMgRHluYW1pYyBOb21vZ3JhbSAKCmBgYHtyLCB3YXJuaW5nID0gRkFMU0V9CgpkYXRhIDwtIHJlYWQuY3N2KCJ1c2VyL2RvY3VtZW50cy9kYXRhLmNzdiIpCmRkaXN0IDwtIGRhdGFkaXN0KGRhdGEpCm9wdGlvbnMoZGF0YWRpc3QgPSAnZGRpc3QnKQoKdG9vbCA8LSBjcGgoCiAgU3Vydih0aW1lID0gdGltZSwgZXZlbnQgPSBldmVudCkgfiAKICAgICAgeDEgKyAKICAgICAgeDIgKyAKICAgICAgeDMsCiAgZGF0YSA9IGRhdGEKICApCgpETmJ1aWxkZXIoICN0aGlzIHVzZXMgRHluTm9tIGFuZCB3aWxsIGNyZWF0ZSAzIG5ldyBmaWxlczogdWkuUiwgc2VydmVyLlIsIGdsb2JhbC5SLiBUaGVzZSB3aWxsIGJlIHRoZSBzY3JpcHRzIG5lZWRlZCB0byBydW4gdGhlIGFwcC4gCiAgdG9vbCwgCiAgZGF0YSA9IGRhdGEsIAogIGNsZXZlbCA9IDAuOTUsIAogIGNvdmFyaWF0ZSA9IGMoIm51bWVyaWMiKSwKICBwdHlwZSA9IGMoIjEtc3QiKSAjIG9yIHN0CiAgKQpgYGAKIyNFeGFtcGxlIG9mIER5bk5vbSBzY3JpcHRzCmBgYHtyfQoKCgpHTE9CQUwuUgoKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHNoaW55KQpsaWJyYXJ5KHNoaW55dGhlbWVzKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShzdGFyZ2F6ZXIpCmxpYnJhcnkoY29tcGFyZSkKbGlicmFyeShwcmVkaWN0aW9uKQpsaWJyYXJ5KHJtcykKbGlicmFyeShzaGlueXRoZW1lcykKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyBCZWZvcmUgcHVibGlzaGluZyB5b3VyIGR5bmFtaWMgbm9tb2dyYW06CiMjIyMKIyMjIyAtIFlvdSBtYXkgbmVlZCB0byBlZGl0IHRoZSBmb2xsb3dpbmcgbGluZXMgaWYKIyMjIyBkYXRhIG9yIG1vZGVsIG9iamVjdHMgYXJlIG5vdCBkZWZpbmVkIGNvcnJlY3RseQojIyMjIC0gWW91IGNvdWxkIG1vZGlmeSB1aS5SIG9yIHNlcnZlci5SIGZvcgojIyMjIG1ha2luZyBhbnkgcmVxdWlyZWQgY2hhbmdlcyB0byB5b3VyIGFwcAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgpsb2FkKCdkYXRhLlJEYXRhJykgIApzb3VyY2UoJ2Z1bmN0aW9ucy5SJykgCmRhdGE9ZGF0YQp0LmRpc3QgPC0gZGF0YWRpc3QoZGF0YSkKb3B0aW9ucyhkYXRhZGlzdCA9ICd0LmRpc3QnKQptb2RlbCA8LSBjb3hwaChTdXJ2KFRpbWUsIGV2ZW50KSB+IHgxICt4MiAreDMgLCBkYXRhID0gZGF0YSkKCm1vZGVsbGFiZWxzIDwtIGMoInZhcmlhYmxlIDEiLCAidmFyaWFibGUgMiIsICJ2YXJpYWJsZSAzIikKbS5zdW1tYXJ5IDwtICdyYXcnCmNvdmFyaWF0ZSA8LSAnbnVtZXJpYycKY2xldmVsIDwtIDAuOTUKCgpVSS5SIAoKCnVpID0gYm9vdHN0cmFwUGFnZShmbHVpZFBhZ2UoCiAgdGhlbWU9c2hpbnl0aGVtZSgiY3lib3JnIiksCiAgdGl0bGVQYW5lbCgKICAgICdnZicKICApLAogIHAoIlRoaXMgaXMgYW4gZXhhbXBsZS4iLCBzdHlsZT0iIHBhZGRpbmc6MTBweDsgY29sb3I6IGxpZ2h0Z3JleTsgaGVpZ2h0OiA2MHB4IiwKICBicigpLAogIGJyKCksCiAgIlRoaXMgaXMgYW4gZXhhbXBsZSBob3cgdG8gdXNlIGl0IDoiLCBzdHlsZT0icGFkZGluZzoyMHB4OyAiICksCiAgYWN0aW9uQnV0dG9uKCdzaG93RWxpZ2liaWxpdHknLCAnRWxpZ2liaWxpdHknLCBzdHlsZT0iY29sb3I6IGJsYWNrOyBiYWNrZ3JvdW5kLWNvbG9yOiBsaWdodGJsdWU7IGJvcmRlci1jb2xvcjogd2hpdGUiKSwKICBhY3Rpb25CdXR0b24oJ3Nob3dMaW1pdGF0aW9ucycsICdMaW1pdGF0aW9ucycsIHN0eWxlPSJjb2xvcjogYmxhY2s7IGJhY2tncm91bmQtY29sb3I6IGxpZ2h0Ymx1ZTsgYm9yZGVyLWNvbG9yOiB3aGl0ZSIpLAogIGFjdGlvbkJ1dHRvbignc2hvd1BlcmZvcm1hbmNlJywgJ1BlcmZvcm1hbmNlJywgc3R5bGU9ImNvbG9yOiBibGFjazsgYmFja2dyb3VuZC1jb2xvcjogbGlnaHRibHVlOyBib3JkZXItY29sb3I6IHdoaXRlIiksCiAgYWN0aW9uQnV0dG9uKCdyZWFkQXJ0aWNsZScsICdSZWZlcmVuY2UgTWFudXNjcmlwdCcsIHN0eWxlPSJjb2xvcjogYmxhY2s7IGJhY2tncm91bmQtY29sb3I6IGxpZ2h0Ymx1ZTsgYm9yZGVyLWNvbG9yOiB3aGl0ZSIsIG9uY2xpY2s9IndpbmRvdy5vcGVuKCdodHRwczovL2RyaXZlLmdvb2dsZS5jb20vZmlsZS9kazZVUVQvdmlldz91c3A9c2hhcmluZycsICdfYmxhbmsnKSIpLAogIHAoIkluc3RydWN0aW9ucyBvbiBob3cgdG8gdXNlIHRoaXMgdG9vbCBjYW4gYmUgZm91bmQgaGVyZToiLCBzdHlsZT0iIHBhZGRpbmc6MjBweDsgY29sb3I6IGxpZ2h0Z3JleTsiKSwKICBhY3Rpb25CdXR0b24oJ3Nob3dIb3d0b3VzZScsICJIb3cgdG8gdXNlIixzdHlsZT0iY29sb3I6IHdoaXRlOyBiYWNrZ3JvdW5kLWNvbG9yOmdyZWVuOyBib3JkZXItY29sb3I6IHdoaXRlIiksCiAgYnIoKSwKICBicigpLCAKICBzaWRlYmFyTGF5b3V0KAogICAgc2lkZWJhclBhbmVsKCAKICAgICAgdWlPdXRwdXQoJ21hbnlTbGlkZXJzLmYnKSwKICAgICAgdWlPdXRwdXQoJ21hbnlTbGlkZXJzLm4nKSwKICAgICAgY2hlY2tib3hJbnB1dCgndHJhbnMnLCAnUmVhZHkhJywgdmFsdWUgPSBGQUxTRSksCiAgICAgIGFjdGlvbkJ1dHRvbignYWRkJywgJ1ByZWRpY3QnLCBzdHlsZT0iY29sb3I6IHdoaXRlOyBiYWNrZ3JvdW5kLWNvbG9yOiBncmVlbjssICBib3JkZXItY29sb3I6IHdoaXRlIiksCiAgICAgIHN0eWxlPSJjb2xvcjogYmxhY2s7IGJhY2tncm91bmQtY29sb3I6IAkjMjk4QUFFIDsgYm9yZGVyLWNvbG9yOiBibGFjayIpLAogICAgbWFpblBhbmVsKAogICAgICB0YWJzZXRQYW5lbCgKICAgICAgICBpZCA9ICd0YWJzJywKICAgICAgICB0YWJQYW5lbCgnUHJlZGljdGVkIFN1cnZpdmFsJywgcGxvdE91dHB1dCgncGxvdCcpKSwKICAgICAgICB0YWJQYW5lbCgnOTUlIENvbmZpZGVuY2UgSW50ZXJ2YWwnLCBwbG90bHlPdXRwdXQoJ3Bsb3QyJykpLAogICAgICAgIHRhYlBhbmVsKCdOdW1lcmljYWwgU3VtbWFyeScsIHZlcmJhdGltVGV4dE91dHB1dCgnZGF0YS5wcmVkJykpLAogICAgc2lkZWJhclBhbmVsKCAKICAgICAgcCgiSG93IHRvIGludGVycHJldCB0aGUgcmVzdWx0cz8iLCBzdHlsZT0iY29sb3I6IGxpZ2h0Z3JleTsiKSwKICAgICAgYWN0aW9uQnV0dG9uKCdzaG93SW50ZXJwcmV0JywgIkludGVycHJldCIsc3R5bGU9ImNvbG9yOiB3aGl0ZTsgYmFja2dyb3VuZC1jb2xvcjpncmVlbjsgYm9yZGVyLWNvbG9yOiB3aGl0ZSIpCgogICAgICApCiAgICApCiAgKQopKSkKCgoKU2VydmVyLlIKCnNlcnZlciA9IGZ1bmN0aW9uKGlucHV0LCBvdXRwdXQpIHsKICBvYnNlcnZlRXZlbnQoaW5wdXQkc2hvd1BlcmZvcm1hbmNlLCB7CiAgICBzaG93TW9kYWwobW9kYWxEaWFsb2coCiAgICAgIHRpdGxlID0gIlBlcmZvcm1hbmNlIiwKICAgICAgcCgKICAgICAgICAiVGhpcyBpcyBhbiBleGFtcGxlLiIKICAgICAgKSwKICAgICAgZWFzeUNsb3NlID0gVFJVRQogICAgKSkKICB9KQogIAogIG9ic2VydmVFdmVudChpbnB1dCRzaG93SG93dG91c2UsIHsKICAgIHNob3dNb2RhbCggCiAgICAgIG1vZGFsRGlhbG9nKCAKICAgICAgICB0aXRsZSA9ICJIb3cgdG8gdXNlIiwgc3R5bGU9ImNvbG9yOiB3aGl0ZTsgYmFja2dyb3VuZC1jb2xvcjogYmxhY2s7IGJvcmRlci1jb2xvcjogYmxhY2siLAogICAgICAgIHAoCiAgICAgICAgICAiVGhpcyBpcyBhIHN0ZXAtYnktc3RlcCBndWlkZSBvbiBob3cgdG8gdXNlIHRoaXMgaW50ZXJhY3RpdmUgY2xpbmljYWwgdG9vbC4iLAogICAgICAgICAgdGFncyRicigpLAogICAgICAgICAgdGFncyRicigpLAogICAgICAgICAgIk9uY2UiLHRhZ3Mkc3Ryb25nKCJhbGwiKSwgInRoZSBib3hlcyBhcmUgZmlsbGVkLWluLCBjaGVjayB0aGUiLCB0YWdzJHN0cm9uZygiJ1JlYWR5ISciKSwgImJveCBhbmQgY2xpY2siLAogICAgICAgICAgdGFncyRzdHJvbmcoIidQcmVkaWN0LiciKSksCiAgICBlYXN5Q2xvc2UgPSBUUlVFCiAgICApKQogICAgCiAgfSkKICAKCiAgCgogIAogIG5lZWRlZFZhciA8LSBuLm10ZXJtc1stMV0KICBpZiAobGVuZ3RoKG10ZXJtc2xhYikgPT0gMSkgewogICAgaW5wdXQuZGF0YSA8PC0gZGF0YS5mcmFtZShkYXRhWzEsIG5lZWRlZFZhcl0pCiAgICBuYW1lcyhpbnB1dC5kYXRhKVsxXSA8PC0gbi5tdGVybXNbLTFdCiAgfSBlbHNlIHsKICAgIGlucHV0LmRhdGEgPDwtIGRhdGFbMSwgbmVlZGVkVmFyXQogIH0KICAKICBpbnB1dC5kYXRhWzEsIF0gPDwtIE5BCiAgYiA8LSAxCiAgaS5mYWN0b3IgPC0gTlVMTAogIGkubnVtZXJpYyA8LSBOVUxMCiAgZm9yIChqIGluIDI6bGVuZ3RoKG10ZXJtcykpIHsKICAgIGZvciAoaSBpbiAxOmxlbmd0aChkYXRhKSkgewogICAgICBpZiAobi5tdGVybXNbal0gPT0gbmFtZXMoZGF0YSlbaV0pIHsKICAgICAgICBpZiAobXRlcm1zW1tqXV0gPT0gJ2ZhY3RvcicgfAogICAgICAgICAgICBtdGVybXNbW2pdXSA9PSAnb3JkZXJlZCcgfAogICAgICAgICAgICBtdGVybXNbW2pdXSA9PSAnbG9naWNhbCcpIHsKICAgICAgICAgIGkuZmFjdG9yIDwtIHJiaW5kKGkuZmFjdG9yLCBjKG4ubXRlcm1zW2pdLCBqLCBpLCBiKSkKICAgICAgICAgIChicmVhaykoKQogICAgICAgIH0KICAgICAgICBpZiAobXRlcm1zW1tqXV0gPT0gJ251bWVyaWMnKSB7CiAgICAgICAgICBpLm51bWVyaWMgPC0gcmJpbmQoaS5udW1lcmljLCBjKG4ubXRlcm1zW2pdLCBqLCBpKSkKICAgICAgICAgIGIgPC0gYiAKICAgICAgICAgIChicmVhaykoKQogICAgICAgIH0KCiNldGMgZXRjCmBgYAo=