Networkx; move edges in nx.MultiDiGraph plot - jupyter-notebook

The question is very simple. However, neither official documentation or searching has helped much. I am looking to create something that (in a simple case) looks like this:
I am looking to plot a very simple directed graph, with one node, and two self-loops. This is what I got so far.
import networkx as nx
from nxpd import draw
G = nx.MultiDiGraph()
G.graph['dpi'] = 120
{'state': 'Low'}
G.add_nodes_from(range(1,2))
G.add_edges_from([(1,1),(1,1)])
pos=nx.get_node_attributes(G,'pos')
draw(G, show='ipynb')
Which produces
But, I would very much like that the other edge was on the left, and of equal size to the first one.

You are using Graphviz to draw the graph with the draw() command there. The attribute settings for Graphviz are documented at http://www.graphviz.org/content/attrs
In your case you want to use "headport" and "tailport" to set where the edges meet the node.
Try
import networkx as nx
G = nx.MultiDiGraph()
G.add_edge(1,1,headport='sw',tailport='nw')
G.add_edge(1,1,headport='se',tailport='ne')
nx.write_dot(G,'sl.dot')
# run dot -Tpng sl.dot >sl.png
The documentation

Related

How to draw a large-scale network graph using networkx(Occlusion issue)

There is a social network graph with more than 6000 vertices and tens of thousands of edges. It is drawn directly by Python networkx as shown in the figure. How to make her look better and clearer, and make interactive information more obvious?
The disorganized graph
And what I have done is try to decrease all those transparencies or make the line thinner. But it looks like the result is still disorganized. Because my screen is fixed, no matter what I do, the lines are very dense just like the pic before.
My little thinking is I don't try to make all lines clear but to make some lines clear. It may be like, increasing the opacity of some lines which are more important or more prominent structures, decreasing the opacity of other lines, like to calculate the edge_betweenness value for every edge and using this to set the transparency of each line. The code is below:
G = nx.read_gml('data\\lesmis.gml')
cent = edge_betweenness_centrality(G)
#node_pos = nx.spring_layout(G)
node_pos = nx.kamada_kawai_layout(G)
#node_pos = nx.circular_layout(G)
nx.draw_networkx_nodes(G,node_pos,**options)#draw nodes
[nx.draw_networkx_edges(G,node_pos,edgelist=[key],alpha=np.amin([1,value*100]),width=2) for key,value in cent.items()] #loop through edges and draw them
plt.show()
But the result is just so so. Is there anyone who can give me some methods, or just a little advice or possible ideas?

How to draw social network graph with R more clearly?

i'm now using lesmis.gml to do network analysis homework.
I can't adjust graph node's distance: there's more than 70 nodes and the nodes are too close.
graph is variable g and g2.
graph looks weird like this.(image)
here's my code using R.
I tried to use Gephi, but my laptop doesn't run it well. It shuts off.
install.packages('igraph')
install.packages('statnet')
library('igraph')
library('statnet')
g<-read.graph("lesmis.gml", format=c("gml"))
g
graph.density(g)
igraph::degree(g,mode="out")
plot(g)
vcount(g)
centralization.degree(g)
V(g)$size<-igraph::degree(g)*5
plot(g)
clo<-igraph::closeness(g)
clo
clo.score<-round((clo-min(clo))*length(clo)/max(clo))+1
clo.colors<-rev(heat.colors(max(clo.score)))
V(g)$color<-clo.colors[clo.score]
plot(g)
btw<-igraph::betweenness(g)
btw
btw.score<-round(btw)+1
btw.score
btw.colors<-rev(heat.colors(max(btw.score)))
V(g)$color<-btw.colors[btw.score]
plot(g)
clusters(g)
clusters(g)$csize
cliques(g)
sapply(cliques(g), length)
largest_cliques(g)
cliques(g)
sapply(cliques(g),length)
a<-largest_cliques(g)
a
clique1<-a[[1]]
g2<-induced.subgraph(graph=g,vids=clique1)
plot(g2)
vcol<-rep("grey80",vcount(g))
vcol[unlist(largest_cliques(g))]<-"gold"
plot(as.undirected(g),vertex.lavel=V(g)$name, vertex.color=vcol)
windows()
I have two suggestions. Before presenting them, I will set up the basics so that what I do is (mostly) repeatable. This is just a streamlined version of what you had in your code, with a change to the vertex size as you had it.
library(igraph)
g<-read.graph("temp/lesmis.gml", format=c("gml"))
V(g)$size<-igraph::degree(g)/2
btw<-igraph::betweenness(g)
btw.score<-round(btw)+1
btw.colors<-rev(heat.colors(max(btw.score)))
V(g)$color<-btw.colors[btw.score]
I think that this is what #nhl was suggesting. There are quite a few layout functions in igraph. Just try a bunch of them and see what looks good. I kind of liked the large graph layout.
set.seed(1234)
LO_LGL = layout_with_lgl(g)
plot(as.undirected(g), layout=LO_LGL, margin=c(-0.25,-0.25))
Once you get something that is pretty close, you might try using tkplot which will allow you to select nodes and move them around to make the graph more readable.
tkplot(as.undirected(g), layout=LO_LGL)
I used the previous layout as a starting place and adjusted the vertices by hand to make the graph clearer. It is not perfect, but you can see some of the communities.

Custom art in NetworkX graph

Is anyone aware of a way to put in an image (vector or raster) in place of a text label for a node or edge in a NetworkX graph visualization?
I prefer a solution that uses the matplotlib plot engine rather than the graphviz, but will take either solution.
In principle, the below should work. I transform the points into pixel coordinates, and then use figimage to put the image at that point.
import networkx as nx
import matplotlib.pyplot as plt
import matplotlib.image as image
im = image.imread('Lower_case_a.png')
G=nx.fast_gnp_random_graph(2,1)
pos = nx.spring_layout(G)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.patch.set_alpha(0)
ax.axis(xmin=-1,xmax=2,ymin=-1,ymax=2)
for node in G.nodes():
x,y = pos[node]
trans_x, trans_y = ax.transData.transform((x,y))
fig.figimage(im,trans_x,trans_y) #could use custom image for each node
nx.draw_networkx_edges(G,pos)
plt.savefig('tmp.png')
It almost works for me. I get:
I think that's because of some weird issue on my computer. When I run the code provided at matplotlib.org to explain transData.transform, it should give me, but instead I get
So I feel like the offset I'm seeing may be a problem on my machine and I'd like to try another computer. At any rate, let me know if this works for you and hopefully it at least points you in the right direction.

Weighted graph drawing using Sage

I was trying to draw a weight graph using Sage for a 10x10 matrix, A. I used the following code:
G = DiGraph(A, format='weighted_adjacency_matrix')
H = G.plot(edge_labels=False, graph_border=True)
H.show()
I was wondering if someone could help me change the starting node from 0 to 1. Currently the node labes are 0,1,...9 but I would prefer them to be 1,...,10.
It took me a lot longer to find this than it should have.
G.relabel([1..10],inplace=True)
This function actually has quite a few nice features.

Which layout should I use to get non-overlapping edges in igraph?

I am trying to build graphs using tree-like data, where nodes typically split into >2 edges. I have tried various layouts, and I see that the layout.reingold.tilford parameter will generate tree-like graphs with non-bifurcating data. However the outputs are not particularly attractive. I would rather use something like the layout.lgl or layout.kamada.kawai since these produce more radial structures. I cannot see how to change the parameters in R such that these trees have no overlapping edges though. Is this possible?
I imported a simple data file in Pajek format, with 355 nodes and 354 edges. I'm currently printing it using:
plot.igraph(g,vertex.size=3,vertex.label=NA,layout=layout.lgl)
This gives me an output like this, which is nice, but still has overlapping edges. I have read that you can manually fix this using tkplot, or another program like cytoscape, however I have quite a few of these to build, and the size of them makes manual correction a hassle.
Many thanks.
Just want to add a comment but my rep is too low. The method that #bdemarest posted does not work on igraph version > 0.7. The newer version does not support the area parameter, so I cannot get the same effect. And getting the old version to build took me a while, so I though I'd share some insights. You can manually install igraph 0.7 from source if you download it from igraph nightly builds. On my machine (Mac OS 10.10), I encountered some problems building it, due to gfortran, so I found this link that solved the problem. Hope that helps anyone who wants to create similar graphs in R.
You may want to try layout.fruchterman.reingold(). It seems to do a good job keeping the edges from crossing. I've tested it with a 355 node version of the barabasi graph suggested by #Tamás.
library(igraph)
g = barabasi.game(355, directed=FALSE)
png("plot1.png", height=6, width=12, units="in", res=200)
par(mfrow=c(1, 2))
plot.igraph(g,vertex.size=3,vertex.label=NA,
layout=layout.fruchterman.reingold(g, niter=10000))
mtext("layout.fruchterman.reingold, area = vcount^2", side=1)
plot.igraph(g,vertex.size=3,vertex.label=NA,
layout=layout.fruchterman.reingold(g, niter=10000, area=30*vcount(g)^2))
mtext("layout.fruchterman.reingold, area = 30 * vcount^2", side=1)
dev.off()
layout.reingold.tilford has a parameter called circular. Setting this to TRUE will convert the final layout into a radial one by treating the X coordinate as the angle (after appropriate rescaling) and the Y coordinate as the radius. Ironically enough, this does not guarantee that there will be no edge crossings in the end, but it works nicely if your subtrees are not exceedingly wide compared to the rest of the graph:
> g <- barabasi.game(100, directed=F)
> layout <- layout.reingold.tilford(g, circular=T)
> plot(g, layout=layout)

Resources