I would like to upload a phylogentic tree via RShiny and use the brushPoints function to allow a user to select the tips of the phylogenetic tree. Ultimately, the tips selected will be used as information to update the tree via annotation. My thought was to display the tips that are selected to confirm the selection but I am unable to generate the verbatiumTextOutput. Suggestions
Below is my attempt:
library(shiny)
library(ggplot2)
library(treeio)
library(ggtree)
library(tidytree)
tree <- treeio::read.newick("1509MLJF6-1.dnd")
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Select Individuals and Display Data"),
# Show a plot and output table
mainPanel(
plotOutput("treeDisplay", brush = "plot_brush"),
verbatimTextOutput("selectedIndivs")
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$treeDisplay <- renderPlot({
ggplot(tree) + geom_tree() + geom_tiplab()
})
output$selectedIndivs <- renderPrint({
brushedPoints(tree, input$plot_brush)
})
}
# Run the application
shinyApp(ui = ui, server = server)
Upon running the App, the error is: Warning: Error in [: incorrect number of dimensions
and upon selecting individuals the error is: Error in rep: invalid 'times' argument
If needed, the phylogenetic tree is located here:
ape
approachTo get the tips brushed by the user you need to know the x and y coordinates of the internal and terminal nodes on the plot. You can get these using the ape
package. Then, once you have the coordinates of the brushed area, you can subset the phylo coordinate table to only the brushed tips. In the example below we have to explicitly tell brushedPoints
where to look for the x
and y
coordinates (xvar
and yvar
columns in the data frame). Depending on the number of species on the tree, you might need to expand the plotting area to avoid overlap, so that species can be brushed over easily.
Code:
library(shiny)
library(ape)
Tree <- rtree(n=20)
Tree <- ladderize(Tree)
ui <- basicPage(
plotOutput("plot1", brush = "plot_brush"),
tableOutput("brushed_subtree")
)
server <- function(input, output) {
output$plot1 <- renderPlot({
plot(Tree)
})
getTreeInfo <- reactive({
plot(Tree)
plotinfo <- get("last_plot.phylo", envir = .PlotPhyloEnv)
tips_xy <- data.frame(Tip=Tree$tip.label,
xvar=plotinfo$xx[1:Ntip(Tree)],
yvar=plotinfo$yy[1:Ntip(Tree)])
return(tips_xy)
})
# render selected tips table
output$brushed_subtree <- renderTable({
brushedPoints(getTreeInfo(), input$plot_brush, xvar = "xvar", yvar = "yvar")
})
}
shinyApp(ui, server)
ggtree
approachThe ggtree
approach is easier. In fact, you were close already, except instead of passing your tree to brushedPoints
you need to supply the $data
component of the ggtree
plot. Note that in this case the brushed area has to include the terminal branch of the wanted tip, because the coordinates of the plot are given by the edge data frame, and the tips are a separate geom plotted relative to the previously plotted (terminal) edges.
Code
library(shiny)
library(ggplot2)
library(treeio)
library(ggtree)
library(tidytree)
tree <- treeio::read.newick("1509MLJF6-1.dnd")
treedt <- as.treedata(tree)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Select Individuals and Display Data"),
# Show a plot and output table
mainPanel(
plotOutput("treeDisplay", brush = "plot_brush"),
verbatimTextOutput("selectedIndivs")
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
make_tree <- reactive({
ggplot(tree) + geom_tree() + geom_tiplab()
})
output$treeDisplay <- renderPlot({
make_tree()
})
output$selectedIndivs <- renderPrint({
brushedPoints(make_tree()$data, input$plot_brush)
})
}
# Run the application
shinyApp(ui = ui, server = server)
Gif: