Nothing
################################################################################
### Main constructor of GraphSpace-class objects
################################################################################
.buildGraphSpace <- function(g, layout = NULL, verbose = TRUE) {
gg <- .validate_igraph(g, layout, verbose)
nodes <- .get_nodes(gg)
edges <- .get_edges(gg)
if(verbose) message("Creating a 'GraphSpace' object...")
instance_id <- .generate_gs_uuid()
pars <- list(is.directed = is_directed(gg),
is.normalized = FALSE, image.layer = FALSE)
gs <- new(Class = "GraphSpace",
nodes = nodes,
edges = edges,
graph = gg,
image = as.raster(matrix()),
pars = pars,
misc = list(g = g),
uuid = instance_id
)
return(gs)
}
################################################################################
### Get nodes and edges in a df object
################################################################################
.get_nodes <- function(gg){
lt <- vertex_attr(gg)
nodes <- data.frame(row.names = seq_along(lt[[1]]))
for(nm in names(lt)){
nodes[[nm]] <- lt[[nm]]
}
vertex <- seq_len(igraph::vcount(gg))
nodes <- cbind(vertex = vertex, nodes)
rownames(nodes) <- nodes$name
return(nodes)
}
.get_edges <- function(gg){
if (igraph::is_directed(gg)) {
edges <- .get_directed_edges(gg)
} else {
edges <- .get_undirected_edges(gg)
}
return(edges)
}
################################################################################
### Get edges in a df object
################################################################################
.get_undirected_edges <- function(g){
if(ecount(g)>0){
vertex <- igraph::V(g)$name
edges <- igraph::as_edgelist(g, names = FALSE)
rownames(edges) <- colnames(edges) <- NULL
edges <- as.data.frame(edges)
colnames(edges) <- c("vertex1", "vertex2")
edges$name1 <- vertex[edges$vertex1]
edges$name2 <- vertex[edges$vertex2]
atts <- .get_eatt(g)
if(!all(atts[,c(1,2)]==edges[,c(1,2)])){
rlang::abort("unexpected indexing during edge attribute combination.")
}
edges <- cbind(edges, atts[,-c(1,2), drop = FALSE])
edges <- edges[order(edges$vertex1,edges$vertex2), ]
idx <- colnames(edges) %in% names(.get_empty_edgedf())
edges <- edges[, c(which(idx), which(!idx))]
rownames(edges) <- NULL
} else {
edges <- .get_empty_edgedf()
}
return(edges)
}
.get_eatt <- function(g){
lt <- igraph::edge_attr(g)
atts <- data.frame(row.names = seq_along(lt[[1]]))
for(nm in names(lt)){
atts[[nm]] <- lt[[nm]]
}
e <- igraph::as_edgelist(g, names = FALSE)
colnames(e) <- c("vertex1", "vertex2")
atts <- cbind(e, atts)
return(atts)
}
.get_empty_edgedf <- function(){
n <- numeric(); c <- character()
edges <- data.frame(n, n, c, c, c, c, n, n, n)
colnames(edges) <- c("vertex1","vertex2", "name1", "name2",
"edgeLineType", "edgeLineColor", "edgeLineWidth",
"arrowType", "weight")
return(edges)
}
################################################################################
### Get undirected edges in a df object
################################################################################
.get_directed_edges <- function(g) {
if (ecount(g) > 0) {
atts <- .extract_directed_att(g)
vertex <- igraph::V(g)$name
E(g)$emode <- 1
E(g)$emode[igraph::which_mutual(g)] <- 3
e <- emode <- .adjacency(g, attr = "emode")
bl <- lower.tri(emode) & emode == 3
emode[bl] <- 0
edges <- arrayInd(seq_len(prod(dim(emode))), dim(emode),
useNames = TRUE)
edges <- as.data.frame(edges)
colnames(edges) <- c("vertex1", "vertex2")
edges$emode <- as.numeric(emode)
edges$name1 <- vertex[edges$vertex1]
edges$name2 <- vertex[edges$vertex2]
edges$e <- as.numeric(e > 0)
eid <- e; eid[,] <- 0
ut <- upper.tri(eid)
eid[ut] <- seq_len(sum(ut))
eid <- t(eid)
eid[ut] <- seq_len(sum(ut))
edges$eid <- as.numeric(eid)
edges$ut <- as.numeric(upper.tri(e))
edges$lt <- as.numeric(lower.tri(e))
if (!all(atts[, c(1, 2)] == edges[, c(1, 2)])) {
rlang::abort("unexpected indexing during edge attribute combination.")
}
edges <- cbind(edges, atts[, -c(1, 2), drop=FALSE])
eid <- unique(edges$eid[edges$e > 0])
edges <- edges[edges$eid %in% eid, ]
edges <- edges[order(edges$eid), ]
rownames(edges) <- NULL
edges <- .set_arrowtype_dir(edges)
idx <- colnames(edges) %in% names(.get_empty_edgedf())
edges <- edges[, c(which(idx), which(!idx))]
rownames(edges) <- NULL
} else {
edges <- .get_empty_edgedf()
}
return(edges)
}
.set_arrowtype_dir <- function(edges) {
# Flip ut/lt from single-edge arrows; this
# for collecting arrows from the same mtx side
idx <- which(edges$emode == 1 & edges$lt == 1)
if (length(idx) > 0) {
for (i in idx) {
ii <- which(edges$eid == edges$eid[i])
edges[ii, c("ut", "lt")] <- edges[ii, c("lt", "ut")]
}
}
# collect left-side arrows
arrow1 <- edges[edges$lt == 1, "arrowType"]
arrow1[is.na(arrow1)] <- 0
# collect right-side arrows
arrow2 <- edges[edges$ut == 1, "arrowType"]
arrow2[is.na(arrow2)] <- 0
# get single-edge assignments
edges <- edges[edges$e == 1, ]
eid <- sort(unique(edges$eid))
edges <- edges[order(-edges$ut, edges$eid), ]
edges <- edges[match(eid, edges$eid), ]
# add arrows and remove intermediate columns
edges <- .merge_arrowtypes_dir(edges, arrow1, arrow2)
edges <- edges[, -which(colnames(edges) %in%
c("e", "eid", "ut", "lt","emode"))]
return(edges)
}
.merge_arrowtypes_dir <- function(edges, arrow1, arrow2) {
## 0 = "---", 1 = "-->", 2 = "<--", 3 = "<->", 4 = "|->",
## -1 = "--|", -2 = "|--", -3 = "|-|", -4 = "<-|",
atypes <- c(0, 1, 2, 3, 4, -1, -2, -3, -4)
names(atypes) <- c("00","01","10","11","-11","0-1","-10","-1-1","1-1")
arrowType <- paste0(format(arrow1, digits = 1, trim = TRUE),
format(arrow2, digits = 1, trim = TRUE))
edges$arrowType <- as.numeric(atypes[arrowType])
return(edges)
}
.extract_directed_att <- function(g) {
# e <- igraph::as_adjacency_matrix(g, sparse = FALSE)
e <- .adjacency(g)
atts <- arrayInd(seq_len(prod(dim(e))), dim(e), useNames = TRUE)
atts <- as.data.frame(atts)
colnames(atts) <- c("vertex1", "vertex2")
atts$e <- as.numeric(e)
# a_names <- names(.get.default.eatt())
a_names <- igraph::edge_attr_names(g)
ne <- e == 0
for (at in a_names) {
x <- .adjacency(g, attr = at)
x[ne] <- NA
if (is.data.frame(x)){
atts[[at]] <- I(unlist(x, recursive=FALSE))
} else {
if (is.numeric(x)) {
atts[[at]] <- as.numeric(x)
} else if (is.character(x)) {
atts[[at]] <- as.character(x)
}
}
}
rownames(atts) <- NULL
atts <- atts[, c("vertex1", "vertex2", a_names)]
return(atts)
}
# ..this is a fix for 'as_adjacency_matrix', when 'attr' is character
.adjacency <- function(g, attr = NULL) {
if(is.null(attr)){
exattr <- rep(1, ecount(g))
x <- matrix(0, nrow = vcount(g), ncol = vcount(g))
} else {
exattr <- edge_attr(g, as.character(attr))
x <- matrix(NA, nrow = vcount(g), ncol = vcount(g))
if(is.list(exattr)) x <- as.data.frame(x)
}
e <- igraph::ends(g, seq_len(ecount(g)), names = FALSE)
x[e] <- exattr
if (!is_directed(g)) x[e[,c(2,1)]] <- exattr
colnames(x) <- rownames(x) <- V(g)$name
return(x)
}
################################################################################
### Other functions
################################################################################
.gs_edges <- function(gs){
nodes <- gs@nodes
edges <- gs@edges
coord <- data.frame(
x = nodes[edges$vertex1, "x"],
y = nodes[edges$vertex1, "y"],
xend = nodes[edges$vertex2, "x"],
yend = nodes[edges$vertex2, "y"]
)
n_offsets <- nodes[["nodeSize"]]
#emode <- .get_emode(edges[["arrowType"]])
#coord$offset_start <- ifelse(emode %in% c(0,1), 0, n_offsets[edges[["vertex1"]]])
#coord$offset_end <- ifelse(emode %in% c(0,2), 0, n_offsets[edges[["vertex2"]]])
coord$offset_start <- n_offsets[edges[["vertex1"]]]
coord$offset_end <- n_offsets[edges[["vertex2"]]]
gs_id <- attr(edges, "gs_id")
edges <- cbind(coord, edges)
attr(edges, "gs_id") <- gs_id
return(edges)
}
.get_emode <- function(arrow_type){
emode <- abs(arrow_type)
emode[emode>3] <- 3
return(emode)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.