library(igraph) # 1) Read DOT file dot <- readLines("ductNet.dot", warn = FALSE) # 2) Basic cleanup dot <- sub("//.*$", "", dot) # remove // comments dot <- trimws(dot) dot <- dot[nzchar(dot)] # drop empty lines # 3) Keep only edge lines (directed -> or undirected --) edge_lines <- dot[grepl("->|--", dot)] # 4) Extract from/to (handles optional quotes and ignores attributes like [label=...]) m <- regexec('^\\s*"?([^"\\s]+)"?\\s*(->|--)\\s*"?([^"\\s\\[;]+)"?', edge_lines) mm <- regmatches(edge_lines, m) edges_df <- data.frame( from = vapply(mm, function(x) if (length(x) >= 2) x[2] else NA_character_, ""), to = vapply(mm, function(x) if (length(x) >= 4) x[4] else NA_character_, ""), stringsAsFactors = FALSE ) edges_df <- na.omit(edges_df) # 5) Build igraph directed_flag <- any(grepl("->", edge_lines)) # if any directed edges exist g <- graph_from_data_frame(edges_df, directed = directed_flag) # 6) Plot plot(g, layout = layout_as_tree(g, root = which(V(g)$name == "A"))) # 6) Save as JPEG library(DiagrammeR) graph <- create_graph() |> add_edges_from_table( table = g, from_col = from, to_col = to ) graph <- add_global_graph_attrs(graph, "layout", "dot", "graph") graph <- add_global_graph_attrs(graph, "rankdir", "TB", "graph") render_graph(graph) jpeg("map.jpg", width = 1200, height = 900, res = 150) plot( g, layout = layout_as_tree(g, root = which(V(g)$name == "A")), vertex.size = 30, vertex.label.cex = 1.2, edge.arrow.size = 0.6 ) dev.off()