Open maelle opened 6 years ago
Hi Maëlle! Glad you like the package and thanks for the good words!
The short answer to your question is that currently (and I do hope to change this!) images or icons as nodes do not work.
Fontawesome icons and local images used to work (way back...) but because a dependency that enabled those icons was determined by CRAN to be difficult to install for Linux users, I had to remove support for FontAwesome and local images. Graphviz generally has support for images in nodes but my version of viz.js does not have that functionality.
I do think that this should all come back (along with much-needed documentation updates, since they are very stale), and some new packages and new ideas could make this possible. I'm going to work on this next.
Thanks for your answer and good luck with the updates! 🙂
Going to add updates here, every now and then, and I believe I made some progress toward a usable method for getting images back into nodes. It'll again involve use of the DiagrammeRsvg pkg (functionality which was spun off into a secondary package due to its dependencies on V8) to extract the SVG from the render process and insert images from an image
attribute.
I've been playing around with the output SVG (which is now much faster to generate since I recently upgraded viz.js to a very recent version) and I think this minimal work needs to be done:
Here is an image showing that this approach is possible:
The nice thing with the
🎉👏
Hi Rich, Is it possible to use different fonts for different nodes? In this way, could a font-awesome code be passed as the node name for users with FA installed? Thanks! (also) Rich
Hello Rich, I didn't get it all, I'm sorry. Can you re-explain how DiagrammeRsvg can help to import an image when using DiagrammeR::grViz(".dot")?? Thanks in advance :)
Are there any updates to this capability? I'd love to substitute graphs of probability distributions as node images for Bayesian networks.
library(shiny) library(DiagrammeR) library(visNetwork)
ui <- fluidPage( textInput("node_A", " A:",width = '50px'), textInput("node_B", " B:",width = '50px'),
textInput("node_d", " d:",width = '5px'), grVizOutput("my_graphviz"),
)
server <- function(input, output) { output$my_graphviz <- renderDiagrammeR({
node_A <- as.integer(input$node_A) node_B <- as.integer(input$node_B) node_d<-(input$node_d)
node_c <- node_A + node_B
my_graphviz <- grViz(paste0("digraph {
graph[rankdir = LR]
node[shape = ellipse]
d[image ='D:/desktop/images/Screenshot (918).png', label = '", node_d, "',width=5,height=1]
node[shape = ellipse, style = filled]
A[label = '", node_A, "']
B[label = '", node_B, "']
c[label = '", node_c, "']
edge[color = black]
A->d
B->d
d->c
}"))
my_graphviz }) }
shinyApp(ui, server) why image is not visible when i executed this code
Hi Maëlle! Glad you like the package and thanks for the good words!
The short answer to your question is that currently (and I do hope to change this!) images or icons as nodes do not work.
Fontawesome icons and local images used to work (way back...) but because a dependency that enabled those icons was determined by CRAN to be difficult to install for Linux users, I had to remove support for FontAwesome and local images. Graphviz generally has support for images in nodes but my version of viz.js does not have that functionality.
I do think that this should all come back (along with much-needed documentation updates, since they are very stale), and some new packages and new ideas could make this possible. I'm going to work on this next.
i have added my code at bottom why it is not working?
For those interested, I've written a workaround using JavaScript to plot posterior distributions for each node image (as requested by @sb3rg - though I did it for my own selfish purposes!). This works for my complicated Bayes net, but no promises for anyone else's! The variable networkModel
here is a HydeNetwork from the HydeNet package, and posts
is a data frame of posteriors with column names equal to the node names (in my case, generated using HydeNet's bindSim function).
The general idea is to let DiagrammeR and htmltools do the work of generating a HTML file, then to write a script to modify the HTML with images after the fact. I've used SVGs here but nothing stopping you from using <img src="file.jpg">
etc.
@rich-iannone if you don't think you'll get to the image capability anytime soon (and given the age of this thread I'm guessing you won't 😆), and you think this workaround is worth using, I can put something more general together and make a branch or something?
# set individual posterior plots to be 7 inches wide, 4 inches high
HydePlotOptions(variable = list(width = "7", height = "4", shape = "rectangle", fontcolor = "black", color = "black"),
determ = list(width = "7", height = "4", shape = "rectangle", fontcolor = "black", color = "black"),
decision = list(width = "7", height = "4", shape = "rectangle", fontcolor = "black", color = "black"),
utility = list(width = "7", height = "4", shape = "rectangle", fontcolor = "black", color = "black"))
# Draw an initial plot with nodes as correct-sized rectangles (but not to screen)
test = plot(networkModel)
# Extract the node names from the plot
pattern = 'label[ ]*=[ ]*"([^"]*)"'
labels = gsub(pattern, "\\1", regmatches(test$x$diagram, gregexpr(pattern, test$x$diagram))[[1]], perl = TRUE)
# create a temporary file to store each SVG output temporarily
tmp = tempfile(fileext = ".svg");
# create a character array to store SVGs before adding to HTML
svgs = character(length(labels))
# Loop over each node name
for (i in 1:length(labels)){
# create 7 inch x 4 inch SVG file with suitable plotting parameters
svg(tmp, 7, 4); par(lwd = 2, cex = 1.5, mar = c(3,4,2,1)+0.1);
# plot density of posterior
plot(density(posts[[labels[i]]]), xlab = "", main = labels[i]); dev.off()
# Read created SVG file, remove first line with xml tag, make into one char string
X = readLines(tmp); X = paste0(X[-1], collapse = "\n");
# SVG uses pts, remove these to make consistent with network plot which uses px (the default unit)
svgs[i] = gsub("([0-9]+)pt", "\\1", X, perl = TRUE)
# Give labels for "glyph" references in SVG files unique names for each SVG
# as they'll all be lumped together in the same HTML file
svgs[i] = gsub("glyph", paste0("node", i, "-glyph"), svgs[i])
}
# Convert to HTML tags
tags = htmltools::as.tags(test, standalone = TRUE)
# Create JavaScript script to add to HTML, to be run after all page elements are loaded
script = '<script>document.addEventListener("DOMContentLoaded", function(event) {'
# Loop over each node name,
# adding a script to extract the coordinates of the rectangle in the network
# and replace the HTML node element with the SVG plot of the posterior
# at those coordinates
for (i in 1:length(labels))
script = paste0(script,
'xmin = document.getElementById("node', i, '").getElementsByTagName("polygon")[0].points[1].x;
xmax = document.getElementById("node', i, '").getElementsByTagName("polygon")[0].points[0].x;
ymin = document.getElementById("node', i, '").getElementsByTagName("polygon")[0].points[0].y;
ymax = document.getElementById("node', i, '").getElementsByTagName("polygon")[0].points[2].y;
document.getElementById("node', i, '").innerHTML =
`<svg x = "\` + xmin + `" y = "` + ymin + `" width = "` + (xmax - xmin) +
`" height = "` + (ymax - ymin) + `" viewbox = "0 0 504 288">
', svgs[i], '</svg>`\n')
# Add closing parentheses, braces and tags to script
script = paste0(script, ';});</script>')
# Add script to HTML tags
tags[[4]] = HTML(script)
# Run HTML in RStudio viewer (or browser if desired)
filename = htmltools::html_print(tags)
Thanks for a great package!
I'm trying to illustrate the nodes with emoji/image/icon (any would do) and encounter a few issues. I'm writing a .gv that I then render using the package. Maybe I'm trying to do things that aren't supported (yet) by the package, or maybe they are but by using R syntax directly, not a .gv file?
I wasn't able to add images. From the examples I saw online I should use the
image
attribute or maybe html-like labels but the image attribute is ignored when I set it, and no matter my combination of '/" using html syntax in thelabel
attribute give me syntax errors withDiagrammeR::grViz
("Error: syntax error in line X near blabla"). Cf #286 and #203I don't see documentation for adding icons cf #238 and #148 I can't add the html font-awesome code directly since it's html syntax. Icons are described as attributes in the nice illustration of http://rich-iannone.github.io/DiagrammeR/graphviz_and_mermaid.html#attributes (whereas images aren't).
I couldn't figure how to use an emoji font. What does work is using symbols via their html text (because it has no '/" I guess?)
Thanks in advance for any guidance.