--- title: "Implement interactive heatmap from scratch" author: "Zuguang Gu ( z.gu@dkfz.de )" date: "`r Sys.Date()`" output: rmarkdown::html_vignette: width: 8 fig_width: 5 vignette: > %\VignetteIndexEntry{7. Implement interactive heatmap from scratch} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- In **InteractiveComplexHeatmap**, we mainly use the combination of `InteractiveComplexHeatmapOutput()` and `makeInteractiveComplexHeatmap()` to create the interactive heatmap widget in the Shiny application. The interactive widgets contains many tools for manipulating heatmaps. However, sometimes users may want to build their own interactive heatmap widget, e.g. to define their own logic to respond to the clicking or brushing event on heatmaps, while not use the one provided by **InteractiveComplexHeatmap**. What they only want is the information of the heatmap cells that were selected from heatmaps. **InteractiveComplexHeatmap** also provides low-level functions that directly return the information of rows and columns that were selected from heatmap. I demonstrate the usage in the next example where `ui` and `server` are defined as follows: ```{r, eval = FALSE} ui = fluidPage( ..., plotOutput("heatmap", click = "heatmap_click") ) server = function(input, output, session) { ht_obj = reactiveVal(NULL) ht_pos_obj = reactiveVal(NULL) output$heatmap = renderPlot({ ... ht = draw(Heatmap(mat)) ht_pos = htPositionsOnDevice(ht) ht_obj(ht) ht_pos_obj(ht_pos) }) observeEvent(input$heatmap_click, { pos = getPositionFromClick(input$heatmap_click) df = selectPosition(ht_obj(), pos, mark = FALSE, ht_pos = ht_pos_obj(), verbose = FALSE) # do something with `df` ... }) } ``` There are two points that need to be noted. 1. `draw()` and `htPositionsOnDevice()` should always be executed together and be put inside `renderPlot()` so that positions of all heatmap slices can be correctly calculated. 2. Use `getPositionFromClick()` to retrieve the position of the click on heatmap, then the position can be sent to `selectPosition()` to correspond to the original matrix. Similarly, `getPositionFromBrush()` and `selectArea()` work together to retrieve rows and columns of the matrix that correspond to the area selected from heatmap. The variable `df` contains row indices and column indices for the cells that were selected (check the help page of `selectPosition()` and `selectArea()` to see the format of `df`). With this information, it is possible to implement the interactive heatmap widget from scratch. `htShinyExample(5.8)` demonstrates an example where the interactivity of the heatmap is only implemented with the functions from **shiny**. In this example, the main heatmap visualizes a 2D density distribution, and brushing on heatmap triggers a new 2D density estimation but only on the selected subset of data. The source code that generates this example is also includes in this web application.