BioTooltipR adds small HTML spans to R Markdown output
and lets the browser-side bio-tooltips
JavaScript library perform the lookup and rendering.
BioTooltipR vendors the required browser assets, so
rendered vignettes do not need to download JavaScript or CSS at build
time.
Genes can be included inline:
cat("The tumour suppressor ", gene_tt("TP53", species = "human"), " is central to DNA damage responses.", sep = "")The tumour suppressor TP53 is central to DNA damage responses.
Chemicals can use stable identifiers:
A chemical example: aspirin.
top_genes <- data.frame(
symbol = c("TP53", "BRCA1", "GADD45A"),
log2FoldChange = c(2.1, -1.4, 1.2),
padj = c(0.0004, 0.002, 0.01)
)
top_genes |>
gene_column(symbol, species = "human") |>
bt_kable(include_setup = FALSE)| symbol | log2FoldChange | padj |
|---|---|---|
| TP53 | 2.1 | 4e-04 |
| BRCA1 | -1.4 | 2e-03 |
| GADD45A | 1.2 | 1e-02 |
The important detail is that HTML escaping must be disabled for the
table cell containing tooltip spans. bt_kable() does this
by default.
use_bio_tooltips() uses vendored
bio-tooltips 1.1.1, D3 7.9.0, and Ideogram 1.53.0 browser
assets by default, so building this vignette does not download
JavaScript or CSS files. D3 and Ideogram are included automatically when
the gene module is enabled because they render the gene model and
chromosome ideogram. To use jsDelivr-hosted assets in a rendered report,
opt in explicitly:
Interactive plotting libraries usually own their hover labels, so the most reliable pattern is to let Plotly handle the plot hover event and update a real HTML Bio Tooltip span next to the plot.
if (!requireNamespace("plotly", quietly = TRUE) ||
!requireNamespace("htmlwidgets", quietly = TRUE)) {
htmltools::tags$p(
"Install the optional plotly and htmlwidgets packages to render this interactive example."
)
} else {
set.seed(42)
volcano_genes <- c(
"TP53", "BRCA1", "BRCA2", "EGFR", "MYC", "PTEN", "KRAS", "NRAS",
"BRAF", "CDK1", "CCND1", "CDKN1A", "CDKN2A", "MDM2", "RB1", "ATM",
"ATR", "CHEK1", "CHEK2", "GADD45A", "VEGFA", "HIF1A", "IL6", "TNF",
"CXCL8", "STAT3", "JAK2", "AKT1", "MTOR", "PIK3CA", "FOXO3", "ESR1",
"AR", "ERBB2", "MET", "ALK", "ROS1", "NTRK1", "RET", "APC",
"CTNNB1", "SMAD4", "TGFB1", "MMP2", "MMP9", "COL1A1", "COL3A1",
"FN1", "VIM", "CDH1", "EPCAM", "SOX2", "NANOG", "POU5F1", "MKI67",
"AURKA", "TOP2A", "BCL2", "BAX"
)
volcano <- data.frame(
symbol = volcano_genes,
log2FoldChange = rnorm(length(volcano_genes), sd = 0.75),
padj = runif(length(volcano_genes), min = 0.08, max = 0.95)
)
interesting <- data.frame(
symbol = c("MYC", "EGFR", "VEGFA", "IL6", "MMP9", "MKI67",
"TP53", "BRCA1", "CDKN1A", "PTEN", "CDH1", "BAX"),
log2FoldChange = c(2.6, 1.9, 1.7, 2.2, 1.5, 2.9,
-2.1, -1.8, -1.4, -1.7, -2.4, -1.3),
padj = c(0.00012, 0.0018, 0.006, 0.0009, 0.014, 0.00004,
0.0007, 0.003, 0.018, 0.009, 0.0002, 0.022)
)
volcano[match(interesting$symbol, volcano$symbol), c("log2FoldChange", "padj")] <-
interesting[c("log2FoldChange", "padj")]
volcano$neg_log10_padj <- -log10(volcano$padj)
volcano$direction <- ifelse(
volcano$padj < 0.05 & volcano$log2FoldChange >= 1,
"Up-regulated",
ifelse(
volcano$padj < 0.05 & volcano$log2FoldChange <= -1,
"Down-regulated",
"Not significant"
)
)
volcano$direction <- factor(
volcano$direction,
levels = c("Up-regulated", "Down-regulated", "Not significant")
)
volcano$label <- ifelse(volcano$symbol %in% interesting$symbol, volcano$symbol, "")
volcano_plot <- plotly::plot_ly(
volcano,
x = ~log2FoldChange,
y = ~neg_log10_padj,
key = ~symbol,
type = "scatter",
mode = "markers+text",
text = ~label,
textposition = "top center",
color = ~direction,
colors = c(
"Up-regulated" = "#b91c1c",
"Down-regulated" = "#2563eb",
"Not significant" = "#7a7f87"
),
marker = list(size = 9, opacity = 0.82, line = list(width = 0)),
textfont = list(size = 10, color = "#24292f")
) |>
plotly::layout(
xaxis = list(title = "log2 fold change", zeroline = TRUE),
yaxis = list(title = "-log10 adjusted p-value"),
legend = list(orientation = "h", x = 0, y = 1.12),
margin = list(t = 60),
shapes = list(
list(type = "line", x0 = -1, x1 = -1, y0 = 0, y1 = 4.6,
line = list(color = "#b7bdc5", width = 1, dash = "dot")),
list(type = "line", x0 = 1, x1 = 1, y0 = 0, y1 = 4.6,
line = list(color = "#b7bdc5", width = 1, dash = "dot")),
list(type = "line", x0 = -3.2, x1 = 3.2, y0 = -log10(0.05), y1 = -log10(0.05),
line = list(color = "#b7bdc5", width = 1, dash = "dot"))
)
)
bt_plotly_gene_hover(volcano_plot, species = "human", include_setup = FALSE)
}Plotly still owns the hover event, but its default hover card is
suppressed. bt_plotly_gene_hover() reads the gene symbol
from Plotly’s key field and updates a tiny fixed-position
Bio Tooltip span at the cursor.
If prose is already rendered, auto_gene_tooltips() can
wrap a supplied vocabulary of gene symbols in a constrained selector.
This should be used carefully because some gene symbols are ordinary
words.
The following sentence is ordinary Markdown rather than a collection
of calls to gene_tt(). Hover over a mouse gene symbol to
see the auto-linking in action.
In mouse, Trp53 and Brca1 help maintain genome integrity, while Gadd45a is involved in the response to DNA damage.
auto_gene_tooltips(
genes = c("Trp53", "Brca1", "Gadd45a"),
species = "mouse",
selector = ".auto-link-demo",
include_setup = FALSE
)Using a dedicated selector keeps the scan inside this example. The mouse-specific vocabulary also avoids matching the human gene symbols used in earlier sections of the vignette.