garthtarr / edgebundleR

Circle plot with bundled edges
http://garthtarr.github.io/edgebundleR/
66 stars 12 forks source link

Uncaught TypeError: Cannot read property 'cluster' of undefined #13

Open jiansongatnih opened 6 years ago

jiansongatnih commented 6 years ago

edgebundleR worked fine by itself in my ShinyApp, but I could not display a D3 network generated by networkD3. No error in my ShinyApp, but got the following javascript error in my browser. Apparently there is a conflict between edgebundleR and networkD3. I want to display my network in both on two different tabs. I would greatly appreciate it if you could help me to find a solution!

Uncaught TypeError: Cannot read property 'cluster' of undefined edgebundleR.js:30 at Object.drawGraphic (http://127.0.0.1:6080/edgebundleR-binding-0.1.4/edgebundleR.js:30:29) at Object.renderValue (http://127.0.0.1:6080/edgebundleR-binding-0.1.4/edgebundleR.js:12:10) at exports.OutputBinding.shinyBinding.renderValue (http://127.0.0.1:6080/htmlwidgets-0.9/htmlwidgets.js:516:20) at exports.OutputBinding.onValueChange (http://127.0.0.1:6080/shared/shiny.min.js:4:9871) at exports.OutputBinding.delegator.(anonymous function) [as onValueChange] (http://127.0.0.1:6080/htmlwidgets-0.9/htmlwidgets.js:112:23) at OutputBindingAdapter.onValueChange (http://127.0.0.1:6080/shared/shiny.min.js:4:29679) at ShinyApp.receiveOutput (http://127.0.0.1:6080/shared/shiny.min.js:3:26802) at ShinyApp. (http://127.0.0.1:6080/shared/shiny.min.js:3:28780) at ShinyApp._sendMessagesToHandlers (http://127.0.0.1:6080/shared/shiny.min.js:3:28585) at ShinyApp.dispatchMessage (http://127.0.0.1:6080/shared/shiny.min.js:3:28375)

garthtarr commented 6 years ago

This is one where @timelyportfolio or @ramnathv might be able to help

timelyportfolio commented 6 years ago

Without a reproducible example, not much I can do unfortunately.

jiansongatnih commented 6 years ago

Thank you @garthtarr. I added 'd3r' and 'htmlwidgets', but they did not solve my problem.

garthtarr commented 6 years ago

@jiansongatnih could you provide a reproducible example filling in the app.R script below (where I've put ##)?

library(edgebundleR)
library(shiny)
library(networkD3)

server <- function(input, output) {

  ##

}

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      ##
    ),
    mainPanel(
      tabsetPanel(
        tabPanel("edgebundle",
                 ##
        ),
        tabPanel("d3network",
                 ##
        )
      )
    )
  )
)

shinyApp(ui = ui, server = server)
jiansongatnih commented 6 years ago

@garthtarr I really appreciate your help on this! I was thinking about how to provide you an example to show what's my problem. It gave me the same javascript error as I notice with my app in a browser (Chrome).

library(edgebundleR)
library(shiny)
library(networkD3)

data(MisLinks)
data(MisNodes)

server <- function(session, input, output) {

  ## Build igraph
  d <- structure(list(ID = c("KP1009", "GP3040", "KP1757", "GP2243",
                             "KP682", "KP1789", "KP1933", "KP1662", "KP1718", "GP3339", "GP4007",
                             "GP3398", "GP6720", "KP808", "KP1154", "KP748", "GP4263", "GP1132",
                             "GP5881", "GP6291", "KP1004", "KP1998", "GP4123", "GP5930", "KP1070",
                             "KP905", "KP579", "KP1100", "KP587", "GP913", "GP4864", "KP1513",
                             "GP5979", "KP730", "KP1412", "KP615", "KP1315", "KP993", "GP1521",
                             "KP1034", "KP651", "GP2876", "GP4715", "GP5056", "GP555", "GP408",
                             "GP4217", "GP641"),
                      Type = c("B", "A", "B", "A", "B", "B", "B",
                               "B", "B", "A", "A", "A", "A", "B", "B", "B", "A", "A", "A", "A",
                               "B", "B", "A", "A", "B", "B", "B", "B", "B", "A", "A", "B", "A",
                               "B", "B", "B", "B", "B", "A", "B", "B", "A", "A", "A", "A", "A",
                               "A", "A"),
                      Set = c(15L, 1L, 10L, 21L, 5L, 9L, 12L, 15L, 16L,
                              19L, 22L, 3L, 12L, 22L, 15L, 25L, 10L, 25L, 12L, 3L, 10L, 8L,
                              8L, 20L, 20L, 19L, 25L, 15L, 6L, 21L, 9L, 5L, 24L, 9L, 20L, 5L,
                              2L, 2L, 11L, 9L, 16L, 10L, 21L, 4L, 1L, 8L, 5L, 11L),
                      Loc = c(3L, 2L, 3L, 1L, 3L, 3L, 3L, 1L, 2L,
                              1L, 3L, 1L, 1L, 2L, 2L, 1L, 3L,
                              2L, 2L, 2L, 3L, 2L, 3L, 2L, 1L, 3L, 3L, 3L, 2L, 3L, 1L, 3L, 3L,
                              1L, 3L, 2L, 3L, 1L, 1L, 1L, 2L, 3L, 3L, 3L, 2L, 2L, 3L, 3L)),
                 .Names = c("ID", "Type", "Set", "Loc"), class = "data.frame",
                 row.names = c(NA, -48L))
  # let's add Loc to our ID
  d$key <- d$ID
  d$ID <- paste0(d$Loc,".",d$ID)
  # Get vertex relationships
  sets <- unique(d$Set[duplicated(d$Set)])
  rel <-  vector("list", length(sets))
  for (i in 1:length(sets)) {
    rel[[i]] <- as.data.frame(t(combn(subset(d, d$Set ==sets[i])$ID, 2)))
  }
  rel <- rbindlist(rel)
  # Get the graph
  g <- graph.data.frame(rel, directed=F, vertices=d)
  clr <- as.factor(V(g)$Loc)
  levels(clr) <- c("salmon", "wheat", "lightskyblue")
  V(g)$color <- as.character(clr)
  V(g)$size = degree(g)*5
  # igraph static plot
  # plot(g, layout = layout.circle, vertex.label=NA)

  observeEvent(input$goButton1, {
    output$igraph <- renderEdgebundle({
      edgebundle(g, tension = 0.8, fontsize = 8)
    })
    updateTabsetPanel(session, "inTabset", selected = "igraph")
  })

  ## Build D3 network
  observeEvent(input$goButton2, {
    output$d3network <- renderForceNetwork({
      forceNetwork(Links = MisLinks, Nodes = MisNodes, Source = "source", Target = "target", Value = "value", NodeID = "name", Group = "group", opacity = 0.4, zoom = TRUE)
    })
    updateTabsetPanel(session, "inTabset", selected = "d3network")
  })
}

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      actionButton("goButton1", "Display network with EdgebundleR"),
      actionButton("goButton2", "  Dispaly network with networkD3")
    ),
    mainPanel(
        tabsetPanel(id = "inTabset",
          tabPanel("edgebundle",
             edgebundleOutput("igraph", width = "100%", height = "600px")     
          ),
          tabPanel("d3network",
             forceNetworkOutput("d3network", width = "100%", height = "700px")
          )
        )
      )
   )
)

shinyApp(ui = ui, server = server) 
jiansongatnih commented 6 years ago

Thank you @garthtarr! If I comment out all 'networkD3' codes, the igraph created by 'edgebundleR' will show up.

garthtarr commented 6 years ago

Thanks for the reprex @jiansongatnih I see the issue. Unfortunately, there's no quick fix, an option might be to use an iframe ramnathv/htmlwidgets#58

As @timelyportfolio mentions here #12 ,

guessing d3v3 from edgebundler conflicting with d3v4 from networkD3. See christophergandrud/networkD3#162 for discussion but no resolution.

I guess I should move edgebundleR to d3v4, but then it looks like we'd have a similar issue with other htmlwidgets that were still using d3v3.

jiansongatnih commented 6 years ago

Thank you @garthtarr! Followed your suggestion, I was able to display my igraph in iframe. But I had to save the igraph to a html file and move the file to 'www' folder in Shiny. Again thanks!

library(edgebundleR)
library(shiny)
library(networkD3)
library(igraph)

data(MisLinks)
data(MisNodes)

server <- function(session, input, output) {

  ## Build igraph
  d <- structure(list(ID = c("KP1009", "GP3040", "KP1757", "GP2243",
                             "KP682", "KP1789", "KP1933", "KP1662", "KP1718", "GP3339", "GP4007",
                             "GP3398", "GP6720", "KP808", "KP1154", "KP748", "GP4263", "GP1132",
                             "GP5881", "GP6291", "KP1004", "KP1998", "GP4123", "GP5930", "KP1070",
                             "KP905", "KP579", "KP1100", "KP587", "GP913", "GP4864", "KP1513",
                             "GP5979", "KP730", "KP1412", "KP615", "KP1315", "KP993", "GP1521",
                             "KP1034", "KP651", "GP2876", "GP4715", "GP5056", "GP555", "GP408",
                             "GP4217", "GP641"),
                      Type = c("B", "A", "B", "A", "B", "B", "B",
                               "B", "B", "A", "A", "A", "A", "B", "B", "B", "A", "A", "A", "A",
                               "B", "B", "A", "A", "B", "B", "B", "B", "B", "A", "A", "B", "A",
                               "B", "B", "B", "B", "B", "A", "B", "B", "A", "A", "A", "A", "A",
                               "A", "A"),
                      Set = c(15L, 1L, 10L, 21L, 5L, 9L, 12L, 15L, 16L,
                              19L, 22L, 3L, 12L, 22L, 15L, 25L, 10L, 25L, 12L, 3L, 10L, 8L,
                              8L, 20L, 20L, 19L, 25L, 15L, 6L, 21L, 9L, 5L, 24L, 9L, 20L, 5L,
                              2L, 2L, 11L, 9L, 16L, 10L, 21L, 4L, 1L, 8L, 5L, 11L),
                      Loc = c(3L, 2L, 3L, 1L, 3L, 3L, 3L, 1L, 2L,
                              1L, 3L, 1L, 1L, 2L, 2L, 1L, 3L,
                              2L, 2L, 2L, 3L, 2L, 3L, 2L, 1L, 3L, 3L, 3L, 2L, 3L, 1L, 3L, 3L,
                              1L, 3L, 2L, 3L, 1L, 1L, 1L, 2L, 3L, 3L, 3L, 2L, 2L, 3L, 3L)),
                 .Names = c("ID", "Type", "Set", "Loc"), class = "data.frame",
                 row.names = c(NA, -48L))
  # let's add Loc to our ID
  d$key <- d$ID
  d$ID <- paste0(d$Loc,".",d$ID)
  # Get vertex relationships
  sets <- unique(d$Set[duplicated(d$Set)])
  rel <-  vector("list", length(sets))
  for (i in 1:length(sets)) {
    rel[[i]] <- as.data.frame(t(combn(subset(d, d$Set ==sets[i])$ID, 2)))
  }
  rel <- rbindlist(rel)
  # Get the graph
  g <- graph.data.frame(rel, directed=F, vertices=d)
  clr <- as.factor(V(g)$Loc)
  levels(clr) <- c("salmon", "wheat", "lightskyblue")
  V(g)$color <- as.character(clr)
  V(g)$size = degree(g)*5

  myIgraph <- edgebundleR::edgebundle(g, tension = 0.8, fontsize = 8)
  saveEdgebundle(myIgraph, "myIgraph.html", selfcontained = TRUE)
  file.copy("myIgraph.html", "./www/myIgraph.html")

  ## Build D3 network
  observeEvent(input$goButton1, {
    output$d3network <- renderForceNetwork({
      forceNetwork(Links = MisLinks, Nodes = MisNodes, Source = "source", Target = "target", Value = "value", NodeID = "name", Group = "group", opacity = 0.4, zoom = TRUE)
    })
    updateTabsetPanel(session, "inTabset", selected = "networkD3")
  })

  # observeEvent(input$goButton2, {
  #   output$igraph <- renderEdgebundle({
  #     edgebundle(g, tension = 0.8, fontsize = 8)
  #   })
  # 
  #   updateTabsetPanel(session, "inTabset", selected = "edgebundleR")
  # })

  observeEvent(input$goButton2, {
    output$igraph <- renderUI({
      tags$iframe(
        seamless = "seamless",
        src="myIgraph.html",
        scrolling = 'no',
        height=700, 
        width=700
      )
    })
    updateTabsetPanel(session, "inTabset", selected = "edgebundleR")
  })
}

ui <- fluidPage(theme = "triage.css",
  sidebarLayout(
    sidebarPanel(
      actionButton("goButton1", "  Dispaly network with networkD3"),
      actionButton("goButton2", "Display network with EdgebundleR")
    ),
    mainPanel(
        tabsetPanel(id = "inTabset",
          tabPanel("networkD3",
              forceNetworkOutput("d3network", width = "100%", height = "700px")
          ),
          # tabPanel("edgebundleR",
          #     edgebundleOutput("igraph", width = "100%", height = "600px")     
          # )
          tabPanel("edgebundleR",
              htmlOutput("igraph", width = "100%", height = "600px")     
          )          
        )
      )
   )
)

shinyApp(ui = ui, server = server)