Nothing
#' Inline \code{textInputs}.
#'
#' By default, \code{\link[shiny]{textInput}} objects are added to the page
#' below each other. This function allows for inline \code{textInput} fields.
#'
#' @param inputId The identifier for the textInput object.
#' @param label The text label to display alongside.
#' @param value The default value of the textInput.
#' @param size The size (width) and maxlength.
#'
#' @return A \code{div} with the appropriate label and input field.
#'
#' @references Adapted from: http://stackoverflow.com/a/21132918/1262569
textInputRow <- function (inputId, label, value="", size=NULL) {
div(style="display:inline-block",
tags$label(label, `for` = inputId),
tags$input(id = inputId, type="text", value=value,
class="input-small", size=size, maxlength=size)
)
}
#' Inline \code{numericInputs}.
#'
#' By default, \code{\link[shiny]{numericInput}} objects are added to the page
#' below each other. This function allows for inline \code{numericInput}
#' fields.
#'
#' @param inputId The identifier for the numericInput object.
#' @param label The text label to display alongside.
#' @param value The default value of the numericInput.
#' @param size The size (width) and maxlength.
#'
#' @return A \code{div} with the appropriate label and input field.
#'
#' @references Adapted from: http://stackoverflow.com/a/21132918/1262569
numericInputRow <- function (inputId, label, value="", size=NULL) {
div(style="display:inline-block",
tags$label(label, `for` = inputId),
tags$input(id = inputId, type="number", value=value,
class="input-small", size=size, maxlength=size)
)
}
#' Shiny visualisation UI.
#'
#' A Shiny UI for interactive ddPCR droplet classification.
#'
#' @return A Shiny UI.
#'
#' @import shiny
#' @include shinyVisGlobal.R
#'
#' @author Anthony Chiu, \email{anthony.chiu@cruk.manchester.ac.uk}
#'
#' @export
shinyVisUI <- function() {
tagList(
tags$head(
tags$style(
HTML("
.help-block ul, .help-block ol {
padding-left: 1.2em;
}
.multicol {
height: auto;
-webkit-column-count: 4;
-moz-column-count: 4;
column-count: 4;
}
div.checkbox {
margin-top: 0px;
}
.shiny-output-error-validation {
color: #D8006B;
}
"
)
)
),
navbarPage(title="twoddpcr", id="tdNavbarPage",
tabPanel("Input",
sidebarLayout(
sidebarPanel(width=3,
radioButtons("datasetType", "Dataset to Use", inline=TRUE,
c("From File", "Sample KRAS")
),
conditionalPanel("input.datasetType == 'From File'",
fileInput("inFile", "Choose Amplitude CSV Files",
accept=c("text/csv",
"text/comma-separated-values,text/plain",
".csv"),
multiple=TRUE
)
),
uiOutput("useThisDatasetPH"),
div(style="margin-top: 2ex",
strong("Help"),
helpText(
tags$ol(
tags$li(
"Upload your own dataset or use the supplied KRAS sample ",
"dataset."
),
tags$li(
"Click the 'Use This Dataset' button to load it."
)
),
"Note that empty wells will be ignored."
)
),
radioButtons("sortWellsBy", "Sort Wells By:",
c("Numbers First", "Letters First")
)
), # sidebarPanel
mainPanel(width=8,
div(
h4("About"),
p(
"A Shiny web application for ddPCR analysis. It is part of
the ",
a(
href="https://bioconductor.org/packages/twoddpcr/",
"twoddpcr", target="_blank"
),
"Bioconductor package. If you use this package, please ",
a(
href="https://bioconductor.org/packages/release/bioc/vignettes/twoddpcr/inst/doc/twoddpcr.html#citing-twoddpcr",
"cite it.", target="_blank"
)
),
h4("General Usage"),
helpText(
"Work your way along the tabs. For more detailed help, see ",
"the 'Help' section in each tab's side panel."
)
),
div(style="padding-bottom: 2ex",
h4("Labels"),
"Set the labels for the channels. These will be printed on ",
"the plots and the summary tables generated."
),
div(
textInputRow("ch1Label", "Ch1 Label", "Mt Amplitude"),
textInputRow("ch1Abbrev", "Abbreviation", "Mt", size=4)
),
div(style="padding-bottom: 2ex",
textInputRow("ch2Label", "Ch2 Label", "Wt Amplitude"),
textInputRow("ch2Abbrev", "Abbreviation", "Wt", size=4)
),
uiOutput("setChLabelsPH")
)
) # sidebarLayout
), # tabPanel "input"
tabPanel("Select Wells",
sidebarLayout(
sidebarPanel(width=3,
conditionalPanel("output.datasetSelectionSuccess",
textInput("plateName", "Plate name", ""),
radioButtons("viewMode", "Samples to Use",
c("All", "Manual Selection"), inline=TRUE
),
conditionalPanel("input.viewMode == 'Manual Selection'",
strong("Wells"),
uiOutput("wellSelectionPH")
),
actionButton("useTheseWells", "Use These Wells"),
div(style="margin-top: 2ex",
strong("Help"),
helpText(
tags$ol(
tags$li(
"Choose the wells that you wish to classify."
),
tags$li(
"Click the 'Use These Wells' button to confirm the ",
"choice."
)
),
"Use the 'Plate View' options to show/hide empty wells."
)
),
radioButtons("plateViewMode", "Plate View",
c("Show All Wells", "Hide Empty Wells")
)
)
), # sidebarPanel
mainPanel(width=8,
h4("Wells in Plate"),
p("This shows an overview of the plate. Each of the smaller boxes
represents a well in the plate. Droplet amplitudes are plotted
for wells that were used."),
plotOutput("plotFacetGrid", height="650")
) # mainPanel
) #sidebarLayout
), #tabPanel "Select Wells"
tabPanel("Classify",
sidebarLayout(
sidebarPanel(width=3,
conditionalPanel("output.wellSelectionSuccess",
selectInput("classifyMode", "Classification Mode",
shinyVis$classifyModes
),
checkboxInput("normalise", "Normalise data", FALSE),
uiOutput("normaliseCheck"),
conditionalPanel("input.classifyMode == 'Thresholds'",
div(class="row-fluid",
div(class="span3",
numericInput("ch1Threshold", "Ch1 Threshold",
shinyVis$threshDefault$ch1,
min=shinyVis$threshLimits$ch1$min,
max=shinyVis$threshLimits$ch1$max, step=1
)
),
div(class="span3",
numericInput("ch2Threshold", "Ch2 Threshold",
shinyVis$threshDefault$ch2,
min=shinyVis$threshLimits$ch2$min,
max=shinyVis$threshLimits$ch2$max, step=1
)
)
)
),
conditionalPanel(
"input.classifyMode == 'K-Nearest Neighbour'",
numericInput("knnK", "k (# of nearest neighbours)", 1),
checkboxInput("knnProb", "Use k-NN Confidence", FALSE),
conditionalPanel("input.knnProb",
sliderInput("knnConf", "Confidence Level",
0.0, 1.0, 0.7
)
)
),
conditionalPanel(
"input.classifyMode == 'K-means Clustering' ||
input.classifyMode == 'Grid'",
uiOutput("selectedClassPH")
),
conditionalPanel(
"input.classifyMode == 'K-means Clustering'",
checkboxInput("removeThisClass", "Remove This Class",
FALSE
),
tags$strong("Initial Centres"),
verbatimTextOutput("centresOutput")
),
conditionalPanel(
"input.classifyMode == 'Grid'",
strong("Grid Thresholds"),
verbatimTextOutput("gridThesholdsOutput")
),
actionButton("classify", "Run Classification"),
div(style="margin-top: 2ex",
strong("Help"),
helpText(
"Choose a 'Classification Mode'. ",
tags$ul(
tags$li("'K-means Clustering' works well in most cases."),
tags$li("'Thresholds' works well if the clusters ",
"are well-separated.")
),
"See the",
a(href="https://bioconductor.org/packages/release/bioc/vignettes/twoddpcr/inst/doc/twoddpcr.html#analysis-of-the-data",
"Bioconductor vignette", target="_blank"
),
"for a discussion comparing these two approaches.",
p(
"Use 'Normalise data' to minimise variations between
clusters in different wells."
)
)
),
conditionalPanel(
"input.classifyMode == 'K-means Clustering'",
div(
strong("K-means Clustering Help"),
helpText(
"K-means clustering requires well-selected cluster ",
"centres.",
br(),
tags$ol(
tags$li("Choose a class from 'Selected Class'."),
tags$li("Click on the plot to set a new centre.")
),
p("Use the 'Remove This Class' checkbox if there is no
cluster."),
p(
"Note that badly chosen centres could lead to error
messages. In this case, try setting centres close to the
centres of clusters and remove classes if they are not
present."
)
)
)
),
conditionalPanel("input.classifyMode == 'Thresholds'",
div(
strong("Thresholds Help"),
helpText(
tags$ul(
tags$li("Divide the plot into four quadrants."),
tags$li("Click on the plot to set new thresholds.")
)
)
)
),
conditionalPanel("input.classifyMode == 'Grid'",
div(
strong("Grid Help"),
helpText(
"Divide the plot into four regions ",
"(droplets not in the regions are treated as rain).",
tags$ol(
tags$li("Select a class."),
tags$li(
"Click on the plot to set new thresholds for this ",
"class."
)
)
)
)
),
conditionalPanel(
"input.classifyMode == 'K-Nearest Neighbour'",
div(
strong("K-Nearest Neighbour Help"),
helpText(
tags$ul(
tags$li("Use training data."),
tags$li(
"The k-nearest neighbours in the training data are ",
"used to decide on the class of each droplet."
),
tags$li(
"'Use k-NN Confidence' for setting the fraction of ",
"votes required for classification."
)
)
)
)
),
sliderInput("heatWidth", "Bin Width", 50, 500, 100)
)
), # sidebarPanel
mainPanel(width=8,
h4("Droplets in Selected Wells"),
p("A density plot of the selected wells."),
plotOutput("plotSelectedWells", height="650",
click="plot_click")
) # mainPanel
) #sidebarLayout
), #tabPanel "Classify"
tabPanel("Results",
sidebarLayout(
sidebarPanel(width=3,
conditionalPanel("output.datasetSelectionSuccess",
selectInput("clToShow", "Classification To Show",
c("None")
),
radioButtons("resultsViewMode", "Sample to View",
c("All", "Manual Selection"), inline=TRUE
),
conditionalPanel(
"input.resultsViewMode == 'Manual Selection'",
div(style="padding-bottom: 2ex",
strong("Wells"),
uiOutput("resultsWellsPH"),
actionButton("showResultsWells", "Show Wells")
)
),
conditionalPanel("output.thresholdsSet",
checkboxInput("showThresholds", "Show Thresholds", FALSE)
),
checkboxInput("finalCentres", "Show Final Centres", FALSE),
radioButtons("rainType", "Rain Type",
c("No Rain", "Mahalanobis", "Standard Deviation")
),
conditionalPanel("input.rainType == 'Mahalanobis'",
uiOutput("mvnRainNNPH"), uiOutput("mvnRainNPPH"),
uiOutput("mvnRainPNPH"), uiOutput("mvnRainPPPH")
),
conditionalPanel("input.rainType == 'Standard Deviation'",
uiOutput("sdRainNNPH"), uiOutput("sdRainNPPH"),
uiOutput("sdRainPNPH"), uiOutput("sdRainPPPH")
),
conditionalPanel("input.rainType != 'No Rain'",
div(style="padding-bottom: 2ex",
actionButton("makeItRain", "Make it Rain")
)
),
div(
strong("Help"),
helpText(
tags$ul(
tags$li(
"The 'Export Amplitudes to File' button creates a zip ",
"file containing CSV droplet amplitude files."
),
tags$li(
"Note: the exported amplitudes are classifed as 'NN',
'NP', 'PN' and 'PP' (N=Negative, P=Positive). Using the
default labels, these are abbreviations for 'Mt-Wt-',
'Mt-Wt'+, 'Mt+Wt-' and 'Mt+Wt+', respectively."
),
tags$li(
"The 'Set as Training Data' button creates training ",
"data to be used with the K-NN algorithm."
)
)
)
),
div(
strong("Rain Help"),
helpText(
tags$ul(
tags$li(
"Droplets can fall between clusters and therefore have
classifications that can be subjective. Defining these
droplets as 'rain' helps to remove ambiguity."
),
tags$li(
"Recommended: 'Mahalanobis' takes cluster rotations into
account."
),
tags$li(
"'Standard Deviation' gives linear cut-offs."
)
)
)
)
)
), # sidebarPanel
mainPanel(width=8,
h4("Classification"),
p("The outcome of the chosen classification method."),
plotOutput("plotClassification", height="650"),
uiOutput("exportAmplitudesPH")
) # mainPanel
) #sidebarLayout
), #tabPanel "Results"
tabPanel("Summary",
sidebarLayout(
sidebarPanel(width=3,
conditionalPanel("output.uploadSuccess ||
input.datasetType == 'Sample KRAS'",
div(
conditionalPanel("output.summarySet",
strong("File Options"),
div(style="padding-bottom: 2ex",
downloadButton("exportSummaryButton",
"Export Summary to File"
)
),
div(style="padding-bottom: 2ex",
downloadButton("generateHtmlReport",
"Generate HTML Report"
)
)
),
strong("Help"),
helpText(
tags$ul(
tags$li(
"Positive/negative droplets counts are summarised here."
),
tags$li(
"The summary can be exported to a CSV file or a report
generated using the buttons above."
),
tags$li(
"'AcceptedDroplets' is the total number of droplets in
each well (if necessary, after subtracting rain)."
),
tags$li(
"The 'Concentration' figures are estimates for the number
of starting molecules per uL."
),
tags$li(
"The 'CopiesPer20uLWell' figures are estimates for the
number of starting molecules in a 20uL well."
),
tags$li(
"'Ratio' is the ratio of channel 1 molecules to channel 2
molecules."
),
tags$li(
"'FracAbun' is short for 'fractional abundance'. It
estimates how many starting channel 1 molecules there
were out of all molecules. The reported figure is a
percentage."
)
)
)
)
)
), # sidebarPanel
mainPanel(width=8,
h4("Plate summary"),
p("A summary of the number of droplets in each of the chosen wells.
Poisson estimates of the starting numbers of molecules is also
provided."),
dataTableOutput("wellsSummary")
) # mainPanel
) #sidebarLayout
), #tabPanel "Summary"
navbarMenu("Advanced",
tabPanel("Options",
sidebarLayout(
sidebarPanel(width=3,
strong("Help"),
helpText(
p(
"The options here are global variables used for calculations
and plotting."
),
h5("Droplet Volume"),
p("The volume of each droplet. Defaults to 0.85nl."),
h5("Minimum Cluster Separation"),
p(
"This figure is used for normalisation. Each well has
k-means clustering run on the NN/NP and NN/PN clusters
separately. If two cluster centres are less than the
'Minimum Separation' figure apart, then the clustering
result is rejected."
),
h5("Plot limits"),
p(
"The minimum and maximum values for Ch1 and Ch2 to plot.
This allows us to increase the size of the plot only, not
decrease it. If droplets lie outside the defined min/max
values, the plot area will be increased automatically."
)
)
), # sidebarPanel
mainPanel(width=8,
h4("Options"),
div(
numericInput("dropletVolume", "Droplet Volume (nl)", 0.85),
uiOutput("setDropletVolumePH")
),
div(
numericInput(
"minSeparation", "Minimum Cluster Separation", 2000
),
uiOutput("setMinSeparationPH")
),
div(
strong("Plot limits")
),
div(
numericInputRow("ch1min", "Ch1 min", 3000),
numericInputRow("ch1max", "Ch1 max", 13500)
),
div(style="padding-bottom: 2ex",
numericInputRow("ch2min", "Ch2 min", 1000),
numericInputRow("ch2max", "Ch2 max", 9000)
),
uiOutput("setPlotLimitsPH")
) # mainPanel
) # sidebarLayout
), # tabPanel "Options"
tabPanel("View Training",
sidebarLayout(
sidebarPanel(width=3,
div(
strong("Help"),
helpText(
tags$ul(
tags$li(
"The current training data will be shown in the plot on
the right."
),
tags$li(
"To create new training data, classify some data and in
the 'Results' tab click the 'Set as Training Data'
button."
)
)
)
)
), # sidebarPanel
mainPanel(width=8,
h4("Current training data"),
p("If set, the current training data will be shown below. This
will be used as training data for the k-nearest neighbour
alogrithm."),
plotOutput("plotTraining", height="650")
) # mainPanel
) # sidebarLayout
) # tabPanel "View Training"
), # navbarMenu "More"
tabPanel("Help",
sidebarLayout(
sidebarPanel(width=3,
div(
"Options appear here."
),
div(
strong("Help"),
helpText("Help information for each panel appears here.")
)
), # sidebarPanel
mainPanel(width=8,
h4("About"),
p(
"A Shiny web application for ddPCR analysis. It is part of
the ",
a(
href="https://bioconductor.org/packages/twoddpcr/",
"twoddpcr", target="_blank"
),
"Bioconductor package. If you use this package, please ",
a(
href="https://bioconductor.org/packages/release/bioc/vignettes/twoddpcr/inst/doc/twoddpcr.html#citing-twoddpcr",
"cite it.", target="_blank"
)
),
p(
"The package and this Shiny app are maintained by Anthony
Chiu. It was developed using ddPCR experiments performed by
Mahmood Ayub. The project was managed by Caroline Dive,
Ged Brady (",
a(href="http://www.cruk.manchester.ac.uk/Research/CRUK-MI-Groups/CEP/Home",
"Clinical and Experimental Pharmacology Group, Cancer
Research UK Manchester Institute", target="_blank"),
") and Crispin J. Miller (",
a(href="http://www.cruk.manchester.ac.uk/Research/CRUK-MI-Groups/RNA-Biology-Computational-Biology/Home",
"RNA Biology Group, Cancer Research UK Manchester
Institute", target="_blank"),
")."
),
h4("General Usage"),
p(
"Work your way along the tabs from left-to-right. Help
information is available in the side-panel on each tab.
Each tab can be summarised as:"
),
tags$ol(
tags$li("Input: Select the dataset."),
tags$li("Select Wells: Choose the wells to use"),
tags$li("Classify: Gate the wells."),
tags$li("Results: View the results."),
tags$li("Summary: View/extract the computed figures.")
),
h4("Input"),
p("Select the dataset to use. This can be:"),
tags$ul(
tags$li(
"Loaded from droplet amplitude CSV files. These can be
exported from Bio-Rad's QuantaSoft software but must be two
channel data; further instructions can be found in the ",
a(
href="https://bioconductor.org/packages/release/bioc/vignettes/twoddpcr/inst/doc/twoddpcr.html#exporting-droplet-amplitudes-from-quantasoft-to-csv-files",
"twoddpcr package vignette.", target="_blank"
),
"Note that empty wells will be ignored."
),
tags$li(
"The sample KRAS dataset can be used as a toy example."
)
),
p(
"The labels for the two targets (in the two channels) can be
customised."
),
tags$ul(
tags$li(
"'Ch1/Ch2 Label' are used in the plots of the droplet
amplitudes."
),
tags$li(
"The corresponding 'Abbreviation' field is used in the
summary of computed figures. They are prefixed to various
column names."
)
),
h4("Select Wells"),
p(
"This tab shows an overview of the wells that were loaded.
From here, we select the samples/wells to be used:"
),
tags$ul(
tags$li("'All' uses all of the wells."),
tags$li(
"'Manual Selection' allows the selection of individual wells."
)
),
p(
"We can choose to view the nonempty wells by changing the
'Plate View' to 'Hide Empty Wells'."
),
h4("Classify"),
p(
"This tab is used for the gating of the droplets. The 'K-means
Clustering' and 'Thresholds' approaches are discussed in the ",
a(href="https://bioconductor.org/packages/release/bioc/vignettes/twoddpcr/inst/doc/twoddpcr.html#analysis-of-the-data",
"Bioconductor vignette.", target="_blank"
),
"In general, 'K-means Clustering' should work without any
modifications if the data forms four clear clusters; just click
'Run Classification'."
),
p(
"If the clusters are well separated, 'Thresholds' should work
too."
),
h5("K-means Clustering"),
p(
"K-means clustering generally works well but it requires
well-selected cluster centres. To do this:"
),
tags$ol(
tags$li("Choose a class from 'Selected Class'."),
tags$li(
"Click on the density plot to set a new centre for the
selected class."
)
),
p(
"Use the 'Remove This Class' checkbox if there is no cluster."
),
p(
"Note that badly chosen centres could lead to error messages. In
this case, try setting centres close to the centres of clusters
and remove classes if they are not present."
),
h5("Thresholds"),
p(
"This works well if the clusters are well separated. This mode
sets thresholds to divide the plot into four quadrants. To do
this, either"
),
tags$ul(
tags$li("Click on the plot to set the new thresholds."),
tags$li(
"Manually change the 'Ch1 Threshold' and 'Ch2 Threshold'
figures."
)
),
h5("Grid"),
p(
"This mode divides the plot into four regions, each
corresponding to one of the four classes. Any droplets
not included in these regions are treated as 'rain'. To
change the regions:"
),
tags$ol(
tags$li("Choose a class from 'Selected Class'."),
tags$li(
"Click on the density plot to set a new region for the
selected class."
)
),
h5("K-Nearest Neighbour"),
p(
"This method requires the use of training data. This method
should only be used by experts. The full work-flow is as
follows:"
),
tags$ol(
tags$li(
"To set training data: classify some wells (e.g. one or two
wells with little noise) and then 'Set as Training Data' in
the 'Results' tab. The resulting training data can be viewed
in 'Advanced > View Training'."
),
tags$li(
"The parameter 'k' can be adjusted, i.e. for each droplet,
the k-NN algorithm finds the k-nearest training droplets and
decides on the classification by majority vote."
),
tags$li(
"'Use k-NN Confidence' refines the majority required, i.e.
if the proportion of the winning class does not exceed the
'Confidence Level', then no classification is assigned."
)
),
h4("Results"),
p(
"This tab shows the resulting classification. Which wells to
show can be changed under 'Sample to View'."
),
p(
"The ambiguous regions between clusters ('Rain') can be removed
using two methods. The 'Mahalanobis' method is recommended with
some manual tweaking of the parameters. It fits clusters to
ellipses, while the 'Standard Deviation' method is restricted to
linear cut-offs."
),
tags$ul(
tags$li(
"Mahalanobis: This is based on Mahalanobis distance. It fits
each cluster to a distribution and removes droplets too far
from the cluster centre. This can be adjusted for each cluster
with the sliders."
),
tags$li(
"Standard Deviation: This works calculated the mean and
standard deviation of each cluster in both channels. These
two figures are used to find linear cut-offs."
)
),
"The classification can be exported as a CSV file for later use.
It can also be set as training data for the k-nearest neighbour
classification method.",
h4("Summary"),
p(
"This tab shows a summarised count of the numbers of droplets in
each class and the resulting estimates of the concentration of
mutants in each sample. It also reports the fractional abundance
('FracAbun') of the channel 1 target. In some use cases, this
corresponds to the variant allele frequency."
),
p(
"This summary table can be exported as a CSV file, which can
then be imported in a spreadsheet. The results and summary table
can also be used to create an HTML report."
)
)
) # sidebarLayout
) # tabPanel "input"
) # navbarPage
) # tagList
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.