Skip to content

Commit 39da599

Browse files
authored
Improve Shiny page population performance (#314)
* perf: reduce Shiny page load latency * fix: stabilize loading feedback across panels * fix: unify page loading feedback * fix: restore loader across menu panels * perf: remove remaining page-load overhead * fix: render panels after inputs initialise * fix: stabilize dynamic panel rendering * fix: initialise enrichment overview controls * test: serialize enrichment overview browser coverage * test: limit enrichment browser regression to current R * ci: serialize browser tests on R 4.1 * test: restore eager browser fixture setup
1 parent 3f426f3 commit 39da599

69 files changed

Lines changed: 1984 additions & 284 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

R/assaydatatable.R

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,10 @@ assaydatatableOutput <- function(id) {
7070

7171
moduleMain(
7272
NULL,
73-
htmlOutput(ns("assaydatatable")),
73+
simpletableOutput(
74+
ns("assaydatatable"),
75+
tabletitle = textOutput(ns("assaydatatable_title"), inline = TRUE)
76+
),
7477
help = modalInput(ns(assaydatatable_modal$id), "help", "help")
7578
)
7679
}
@@ -111,17 +114,16 @@ assaydatatable <- function(id, eselist) {
111114

112115
# Render the output area - and provide an input-dependent title
113116

114-
output$assaydatatable <- renderUI({
115-
ns <- session$ns
116-
117-
simpletableOutput(ns("assaydatatable"), tabletitle = paste("Assay data", selectmatrix_reactives$getAssay(), sep = ": "), spinner = TRUE)
117+
output$assaydatatable_title <- renderText({
118+
paste("Assay data", selectmatrix_reactives$getAssay(), sep = ": ")
118119
})
119120

120121
# Pass the matrix to the simpletable module for display
121122

122123
simpletable("assaydatatable",
123124
downloadMatrix = selectmatrix_reactives$selectLabelledMatrix, displayMatrix = selectmatrix_reactives$selectLabelledLinkedMatrix,
124-
filename = selectmatrix_reactives$getAssay(), rownames = FALSE
125+
filename = selectmatrix_reactives$getAssay(), rownames = FALSE,
126+
ready = selectmatrix_reactives$inputsReady
125127
)
126128
})
127129
}

R/barplot.R

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,13 @@ barplotOutput <- function(id, height = 400) {
4141
#' @param getPlotmatrix Reactive supplying a matrix to plot
4242
#' @param getYLabel Reactive supplying the Y axis label
4343
#' @param barmode Bar mode: 'stack', 'group' or 'overlay'
44+
#' @param ready Reactive that returns TRUE when the plot data and controls are
45+
#' fully initialised.
4446

45-
barplot <- function(id, getPlotmatrix, getYLabel, barmode = "stack") {
47+
barplot <- function(id, getPlotmatrix, getYLabel, barmode = "stack", ready = reactive(TRUE)) {
4648
moduleServer(id, function(input, output, session) {
4749
output$barPlot <- renderPlotly({
48-
validate(need(input$barMode, "Waiting for bar mode"))
50+
req(ready(), inputsInitialised(input$barMode))
4951

5052
interactive_barchart(getPlotmatrix(), barmode = input$barMode, ylab = getYLabel()) %>%
5153
shinyngsPlotlyConfig("barplot", format = session$userData$plotFormat())

R/boxplot.R

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,19 @@ boxplot <- function(id, eselist) {
140140
selectmatrix_reactives <- selectmatrix("sampleBoxplot", eselist, select_genes = FALSE)
141141
groupby_reactives <- groupby("boxplot", eselist = eselist, group_label = "Color by", selectColData = selectmatrix_reactives$selectColData)
142142

143+
inputsReady <- reactive({
144+
req(
145+
selectmatrix_reactives$inputsReady(),
146+
groupby_reactives$inputsReady(),
147+
inputsInitialised(input$plotType, input$whiskerDistance)
148+
)
149+
TRUE
150+
})
151+
143152
# Render the plot
144153

145154
output$quartilesPlot <- renderUI({
155+
req(inputsReady())
146156
ns <- session$ns
147157
plotOutputId <- if (input$plotType == "boxes") {
148158
"sampleBoxplot"
@@ -151,17 +161,19 @@ boxplot <- function(id, eselist) {
151161
} else {
152162
"quartilesPlotly"
153163
}
154-
shinycssloaders::withSpinner(plotlyOutput(ns(plotOutputId), height = "600px"), color = shinyngsSpinnerColor())
164+
plotlyOutput(ns(plotOutputId), height = "600px")
155165
})
156166

157167
output$quartilesPlotly <- renderPlotly({
168+
req(inputsReady())
158169
selected_matrix <- selectmatrix_reactives$selectMatrix()
159170
ese <- selectmatrix_reactives$getExperiment()
160171
interactive_quartiles(selected_matrix, id_to_label(rownames(selected_matrix), ese), selectmatrix_reactives$getAssayMeasure(), whisker_distance = input$whiskerDistance) %>%
161172
shinyngsPlotlyConfig("quartiles", format = session$userData$plotFormat())
162173
})
163174

164175
output$densityPlotly <- renderPlotly({
176+
req(inputsReady())
165177
interactive_densityplot(selectmatrix_reactives$selectMatrix(), selectmatrix_reactives$selectColData(), groupby_reactives$getGroupby(), expressiontype = selectmatrix_reactives$getAssayMeasure(), palette = groupby_reactives$getPalette()) %>%
166178
shinyngsPlotlyConfig("density", format = session$userData$plotFormat())
167179
})
@@ -198,6 +210,7 @@ boxplot <- function(id, eselist) {
198210
})
199211

200212
output$sampleBoxplot <- renderPlotly({
213+
req(inputsReady())
201214
withProgress(message = "Making sample boxplot", value = 0, {
202215
interactive_boxplot_from_statistics(list(" " = getBoxplotStatistics()), selectmatrix_reactives$selectColData(), groupby_reactives$getGroupby(),
203216
expressiontype = selectmatrix_reactives$getAssayMeasure(),
@@ -221,7 +234,7 @@ boxplot <- function(id, eselist) {
221234
downloadMatrix = getDistributionSummary,
222235
displayMatrix = getDistributionSummary,
223236
filename = "distribution_summary", rownames = FALSE,
224-
server = FALSE, initial_order = list()
237+
server = FALSE, initial_order = list(), ready = inputsReady
225238
)
226239
})
227240
}

R/categorycountplot.R

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ categorycountplotOutput <- function(id) {
3434
ns <- NS(id)
3535

3636
list(
37-
shinycssloaders::withSpinner(plotlyOutput(ns("plot"), height = "500px"), color = shinyngsSpinnerColor()),
38-
simpletableOutput(ns("table"), tabletitle = "Counts", spinner = TRUE)
37+
plotlyOutput(ns("plot"), height = "500px"),
38+
simpletableOutput(ns("table"), tabletitle = "Counts")
3939
)
4040
}
4141

@@ -110,6 +110,13 @@ categorycountplot <- function(id, getAnnotation, filename = "categorycounts") {
110110
if (is.null(input$barmode)) "group" else input$barmode
111111
})
112112

113+
inputsReady <- reactive({
114+
if (!inputsInitialised(input$category, input$fill)) {
115+
return(FALSE)
116+
}
117+
identical(input$fill, "none") || inputsInitialised(input$barmode)
118+
})
119+
113120
# The tally itself only depends on category/fill, not on barmode - shared so the table and plot (and a barmode-only change) don't each
114121
# re-tally the annotation data frame independently
115122

@@ -135,12 +142,13 @@ categorycountplot <- function(id, getAnnotation, filename = "categorycounts") {
135142
})
136143

137144
output$plot <- renderPlotly({
145+
req(inputsReady())
138146
title <- paste("Counts by", prettify_variable_name(input$category))
139147

140148
interactive_barchart(getCountMatrix(), barmode = getBarmode(), ylab = "Count", title = title) %>%
141149
shinyngsPlotlyConfig(filename, format = session$userData$plotFormat())
142150
})
143151

144-
simpletable("table", displayMatrix = countTable, filename = filename, rownames = FALSE)
152+
simpletable("table", displayMatrix = countTable, filename = filename, rownames = FALSE, ready = inputsReady)
145153
})
146154
}

R/clustering.R

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,9 @@ clusteringOutput <- function(id) {
7979
moduleMain(
8080
NULL,
8181
uiOutput(ns("geneClusteringTitle")),
82-
shinycssloaders::withSpinner(plotlyOutput(ns("geneClusteringPlot"), height = "600px"), color = shinyngsSpinnerColor()),
82+
plotlyOutput(ns("geneClusteringPlot"), height = "600px"),
8383
h4("Table of values by cluster"),
84-
simpletableOutput(ns("geneClusteringTable"), spinner = TRUE),
84+
simpletableOutput(ns("geneClusteringTable")),
8585
help = modalInput(ns(clustering_modal$id), "help", "help")
8686
)
8787
}
@@ -118,6 +118,18 @@ clustering <- function(id, eselist) {
118118

119119
getPalette <- colormaker("clustering", getNumberCategories = getClusterNumber)
120120

121+
inputsReady <- reactive({
122+
req(
123+
selectmatrix_reactives$inputsReady(),
124+
inputsInitialised(
125+
input$cluster_number, input$cluster_display,
126+
input$average_type, input$limits,
127+
input[["clustering-palette_name"]]
128+
)
129+
)
130+
TRUE
131+
})
132+
121133
############################################################################# Form accessors
122134

123135
# The number of clusters
@@ -234,6 +246,7 @@ clustering <- function(id, eselist) {
234246
)
235247

236248
output$geneClusteringPlot <- renderPlotly({
249+
req(inputsReady())
237250
getClusterPlot() %>% shinyngsPlotlyConfig("clustering", format = session$userData$plotFormat())
238251
})
239252

@@ -261,7 +274,7 @@ clustering <- function(id, eselist) {
261274

262275
# Render the table and provide for download, using the simpletable module.
263276

264-
simpletable("geneClusteringTable", downloadMatrix = makeMatrixWithClusters, displayMatrix = makeLinkedMatrixWithClusters, filter = "top", filename = "clustered_matrix", rownames = FALSE)
277+
simpletable("geneClusteringTable", downloadMatrix = makeMatrixWithClusters, displayMatrix = makeLinkedMatrixWithClusters, filter = "top", filename = "clustered_matrix", rownames = FALSE, ready = inputsReady)
265278
})
266279
}
267280

0 commit comments

Comments
 (0)