I am using a combination of networkx, pygraphviz and graphviz to create and visualise graphs in python,
However I keep encountering utf-8 encoding errors when writing my dot file from my networkx graph that has greek letters as nodes.
I would like to be able to create dot graphs with nodes such as these: Κύριος, Θεός, Πᾶσα, Μέγας, Νέμεσις but am unable to do so.
Are there any encoding tricks I need to know about?
The example you posted works fine for me (using ipython with python 3.7) when using the correct dot file path.
import networkx as nx
from networkx.drawing.nx_pydot import write_dot
import graphviz as grv
n = "Νέμεσις"
G = nx.Graph()
G.add_node(n)
write_dot(G, 'test.dot')
grv.render('neato', 'svg', 'test.dot')
Related
I'm currently trying to build a block model using the python package networkx. I found that the function networkx.quotient_graph can be used for this job:
g_block = nx.quotient_graph(G=g, partition=node_list, relabel=True)
In the next step, I want to export the generated block graph "g_block" to a file to import it afterwards in a visualization tool that supports for example graphml-files.
nx.write_graphml(g_block, 'test_block.graphml')
However, this leads to the error:
{KeyError}class 'networkx.classes.graphviews.SubDiGraph'
Can someone help?
Currently networkx (version 2.2) doesn't support nested graphs in a way you can easily export and visualize. Consider using graphviz for handling your nested graph and export it to a dot format.
For working with a networkx version of the graph, you can transform the pygraphviz to a networkx graph and vise versa by keeping a 'graph' property for nodes (which is semantically a subgraph), similarly to the result of quotient_graph.
Here is an example of transforming a small networkx graph to pygraphviz with subgraphs, and exporting it as a dot file:
import networkx as nx
import pygraphviz as pgv
G = nx.erdos_renyi_graph(6, 0.5, directed=False)
node_list = [set([0, 1, 2, 3]), set([4, 5])]
pgv_G = pgv.AGraph(directed=True)
pgv_G.add_edges_from(G.edges())
for i, sub_graph in enumerate(node_list):
pgv_G.add_subgraph(sub_graph, name=str(i))
print(pgv_G)
pgv_G.write("test_pgv.dot")
Note that netwrokx also allows writing and reading 'dot' format (see example), however since there is no built-in support for nested graphs it's not too helpful for this purpose.
The reason you can't write the quotient_graph is twofold:
In a quotient_graph each node has a 'graph' property, which is a SubDiGraph (or a SubGraph, if the original graph is undirected). A SubDiGraph is a ReadOnlyGraph which means it is not possible to write it using the standard networkx.readwrite utils.
Even if we convert the SubDiGraph to a DiGraph, not every graph file format allows to encode a 'graph' property. For example, graphml format supports primitive properties such as booleans, integers etc. Read more here.
One solution that works is to solve the first issue by overriding the 'graph' property with a DiGraph copy of the original SubDiGraph. The second issue can be simply solved by using another file format (e.g., pickle format can work). Read about all supported formats here.
Following is a working example:
g_block = nx.quotient_graph(G=G, partition=node_list, relabel=True)
def subdigraph_to_digraph(subdigraph):
G = nx.DiGraph()
G.add_nodes_from(subdigraph.nodes())
G.add_edges_from(subdigraph.edges())
return G
for node in g_block:
g_block.nodes[node]['graph'] = subdigraph_to_digraph(g_block.nodes[node]['graph'])
nx.write_gpickle(g_block, "test_block.pickle")
This allows to write and load the nested graph for using with netwrokx, however for the purpose of using the exported file in a visualization tool this is not too helpful.
I want to make a graph with random node positions but it seems that the "pos" attribute for nodes does nothing. Here is a minimal example:
import graphviz
import pylab
from graphviz import Digraph
g = Digraph('G', filename='ex.gv',format='pdf')
g.attr(size='7')
g.node('1',pos='1,2')
g.node('2',pos='2,3')
g.node('3',pos='0,0')
g.edge('1','2')
g.edge('1','3')
graphviz.Source(g)
Any ideas of how achieve that?
Thanks in advance.
Although not 100% clear in the docs, I think pos is not supported in the dot engine on input. The fdp or neato engines do support pos on input for setting the initial position, and if you end the coordinate specification with '!', the coordinates will not change and thus become the final node position.
Play with a live example at https://beta.observablehq.com/#magjac/placing-graphviz-nodes-in-fixed-positions
This standalone python script generates a pdf with the expected node positions:
#!/usr/bin/python
import graphviz
from graphviz import Digraph
g = Digraph('G', engine="neato", filename='ex.gv',format='pdf')
g.attr(size='7')
g.node('1',pos='1,2!')
g.node('2',pos='2,3!')
g.node('3',pos='0,0!')
g.edge('1','2')
g.edge('1','3')
g.render()
Since SO does not support pdf uploading, here's a png image generated with the same code except format='png':
Without the exclamation marks you get:
Without any pos attributes at all you get a similar (but not exactly the same) result:
This is a followup question to this question. Since it addresses a more general issue I make it a new question.
I have a network for which the labels of the nodes are in Farsi language (Arabic alphabet). When I try to use networkx to display my network it shows blank squares instead of Arabic letters. Below I copy a good example provided in the answers in here.
from bidi.algorithm import get_display
import matplotlib.pyplot as plt
import arabic_reshaper
import networkx as nx
# Arabic text preprocessing
reshaped_text = arabic_reshaper.reshape(u'زبان فارسی')
artext = get_display(reshaped_text)
# constructing the sample graph
G=nx.Graph()
G.add_edge('a', artext ,weight=0.6)
pos=nx.spring_layout(G)
nx.draw_networkx_nodes(G,pos,node_size=700)
nx.draw_networkx_edges(G,pos,edgelist=G.edges(data=True),width=6)
# Drawing Arabic text
# Just Make sure your version of the font 'Times New Roman' has Arabic in it.
# You can use any Arabic font here.
nx.draw_networkx_labels(G,pos,font_size=20, font_family='Times New Roman')
# showing the graph
plt.axis('off')
plt.show()
which generates the following image:
I tried to install the needed fonts by following command lines in python, but I get the same thing.
>>> import matplotlib.pyplot
>>> matplotlib.rcParams.update({font.family' : 'TraditionalArabic'})
Here is the ERROR message, to be more specific:
/usr/local/anaconda3/lib/python3.5/site-packages/matplotlib/font_manager.py:1288: UserWarning: findfont: Font family ['TraditionalArabic'] not found. Falling back to Bitstream Vera Sans
(prop.get_family(), self.defaultFamily[fontext])
I am also investigating ways to install the needed fonts from ubuntu cli, if possible, and put it in my docker file as it gets installed every time I spin my runs.
Best regards, s.
My task is to generate a graph from a dot file (using pydot) and then convert the same as networkx graph. The problem that I faced was that the attributes of Graph (as I have given in the .dot file) is not present in the networkx graph.
I also used read_dot() function which is again an error. My code is successfully working to visualize graphs but not its attribs.
My code is:
import pydot
import networkx as nx
(graph,) = pydot.graph_from_dot_file('1.dot')
G = nx.nx_pydot.from_pydot(graph)
nx.get_node_attributes(G,'1')
My output is {}
Pls help me to fix the problem
Thanks from Mathan :)
I am using networkx to plot graph in python. However, my output is too dense. Is there any ways to sparse the graph? Below is my command in python.Thanks
pos=nx.spring_layout(self.G)
nx.draw_networkx_nodes(self.G,pos)
edge_labels=dict([((u,v,),d['weight'])
for u,v,d in self.G.edges(data=True)])
nx.draw_networkx_labels(self.G,pos, font_size=20,font_family='sans-serif')
nx.draw_networkx_edges(self.G,pos)
plt.axis('off')
#nx.draw_networkx_labels(self.G,pos, font_size=20,font_family='sans-serif')
nx.draw_networkx_edge_labels(self.G,pos,edge_labels=edge_labels)
nx.draw(self.G,pos, edge_cmap=plt.cm.Reds)
plt.show()
You can also try Graphviz via PyDot (I prefer this one) or PyGraphviz.
In case you are interested in a publication-ready result, you can use the toolchain networkx -> pydot + dot -> dot2tex + dot -> dot2texi.sty -> TikZ. Instead of this fragile toolchain, you can alternatively export directly to TikZ with nx2tikz (I've written it, so I'm biased) and use the graph layout algorithms that have been relatively recently added to TikZ.
After I check some information from the documentation here: http://networkx.github.io/documentation/latest/reference/drawing.html#module-networkx.drawing.layout
I changed the format of layout to
pos=nx.circular_layout(self.G, scale=5)
and it works!