Search code examples
rggplot2plotlygggenes

Is it possible to plot arrows in plotly in such a format as geom_gene_arrow from gggenes?


I would love to incorporate arrow shapes in plotly plots to represent genes as is possible with gggenes geom_gene_arrow, that is, thick arrows that can preferably overlap bars. Is this possible?

enter image description here

https://cran.r-project.org/web/packages/gggenes/vignettes/introduction-to-gggenes.html


Solution

  • An obvious way round this is to make the arrows yourself as polygons. The following function will handle the geometry:

    make_arrows <- function(start, stop, yvals, groups, head_length = 500,
                            body_width = 0.1, head_width = 0.15) {
      
      dfs <- Map(function(start, stop, yval, group, arrow_num) {
        if(stop - start > head_length) {
        x <- c(start, start, stop - head_length, stop - head_length, stop,
               stop - head_length, stop - head_length, start, start)
        y <- c(yval, yval + body_width/2, yval + body_width/2, yval + head_width/2,
               yval, yval - head_width/2, yval - body_width/2, yval- body_width/2,
               yval)
        } else {
          x <- c(start, start, stop, start, start)
          y <- c(yval, yval + head_width/2, yval, yval - head_width/2, yval)
        }
        data.frame(x = x, y = y, arrow_num = arrow_num, group = group)
      }, start = start, stop = stop, yval = yvals, 
      group = groups, arrow_num = seq_along(start))
      do.call(rbind, dfs)
    }
    

    Then, suppose you have data like this:

    df <- data.frame(start = c(15200, 17000, 18000, 18400, 19000, 22300, 22400,
                               23500, 25000),
                     stop = c(17000, 18000, 18400, 19000, 22300, 22400, 
                              23500, 25000, 27000),
                     Gene = LETTERS[1:9])
    

    Then you can plot it as follows:

    library(ggplot2)
    
    p <- ggplot(make_arrows(df$start, df$stop, 1, df$Gene), aes(x, y, fill = group)) +
      geom_polygon(color = "black") +
      scale_y_continuous(NULL, limits = c(0.7, 1.3), 
                         breaks = 1, labels = "Genome1") +
      labs(x = NULL, y = NULL) +
      scale_fill_manual(values = c("#8cd2c6", "#fdfcb3", "#bdb9da", "#fa7f72",
                                   "#7fb0d2", "#fbb361", "#feea6e", "#bb7ebd",
                                   "#cceac3"), guide = "none") +
      facet_wrap(.~"Genome1") +
      theme_gray(base_size = 20) +
      theme(legend.position = "none")
    
    p
    

    enter image description here

    And you get a nice result in plotly:

    plotly::ggplotly(p)
    

    enter image description here