Clusters are not showing - pygraphviz

I am using the below code to generate a graph with two clusters with four nodes each
For some reasons when I print the graph the clusters do not show up.
What am I doing wrong?
import pygraphviz as pgv
A=pgv.AGraph(bgcolor="#cccccc",layout='neato')
A.add_edge('R1','R2')
A.add_edge('R2','R3')
A.add_edge('R3','R4')
A.add_edge('R4','R5')
A.add_edge('R5','R6')
A.add_subgraph(['R1','R2','R3','R4'], 'pbd01')
A.add_subgraph(['R5','R6','R7','R8'], 'pbd02')
A.write('cluster.dot')
A.draw('Topology.png', prog='neato')

I believe there are two problems:
The 'neato' rendering engine does not support clustering
By convention, rendering engines that do support clustering require that the subgraph name starts with 'cluster'
The following code / image was produced with the 'dot' engine and correctly clusters the nodes:
import pygraphviz as pgv
A=pgv.AGraph(bgcolor="#cccccc",layout='dot')
A.add_edge('R1','R2')
A.add_edge('R2','R3')
A.add_edge('R3','R4')
A.add_edge('R4','R5')
A.add_edge('R5','R6')
A.add_subgraph(['R1','R2','R3','R4'], name='cluster_pbd01')
A.add_subgraph(['R5','R6','R7','R8'], name='cluster_pbd02')
A.write('cluster.dot')
A.draw('Topology.png', prog='dot')
Topology.png

Related

How to get plot as svg string in sympy plotting backends library?

I use sympy plotting backends library to create plots directly from sympy expressions. I chose this library because it gives more options for plots fine tunning compared to standart sympy plotting module.
As backend in choosen library i use matplotlib.
My aim is to get resulting plot as svg string in order to insert it in the web page later. I need to do it programmatically. I use the code below:
from spb import plot, MB
import io
from sympy import symbols, sin, cos
x = symbols("x")
# create plot
p1 = plot(
(sin(x), "a", dict(color="k", linestyle=":")),
(cos(x), "b"),
backend=MB, show=False)
# buffer:
f = io.StringIO()
# save plot in buffer as svg string:
p1._fig.savefig(f, format = "svg")
# return result as svg string to insert it in web page later:
return f.getvalue()
The problem is that i get an exception:
'NoneType' object has no attribute 'savefig'
p1._fig.savefig(f, format = "svg")
But if i slightly modify the code:
...
# buffer:
f = io.StringIO()
# show plot:
p1.show()
# save plot in buffer as svg string:
p1._fig.savefig(f, format = "svg")
...
Everything works just fine. But the problem is that i do not want to show the plot, i need to save it as svg string. Anyone knows how to solve this task?
Here I am, the developer of that module.
That error is caused by the fact that when you create a plot with MatplotlibBackend and show=False, the figure is not created (too long to explain why); this behavior is specific to MatplotlibBackend, the other backends should not be affected by it. So, p1.fig is None.
However, the plotting function exposes the save method, which is nothing more than a wrapper to a specific plotting library "save" functionality. If you look at the source code, you'll see that MatplotlibBackend.save calls matplotlib's savefig, but first it checks if the figure has been created. If not, it forces the creation.
So, all you have to do is:
p1.save(f, format = "svg")
One final note. If possible, do not use attributes or methods starting with _ (underscore). They represent private attributes and the names might change from version to version. If you really need to retrieve the matplotlib figure, use p1.fig.
EDIT to answer the question in the comment about performance:
For back-compatibility reasons, the new module uses an adaptive algorithm for line plots by default, which is different from the one used on SymPy. On the one hand it can be easily applied to a wider set of applications, on the other hand it is slower.
You have two options: either way you might want to change the configuration file of the module.
Option 1: the adaptive algorithm minimizes some loss function (loss_fn) and stops when a threshold (adaptive_goal) has been reached. We can increase this threshold (which by default is set to 0.01), thus improving performance but sacrificing the smooth quality of lines.
from spb.defaults import cfg, set_defaults
# it requires a few tries to find an appropriate value
cfg["adaptive"]["goal"] = 0.02
set_defaults(cfg)
# restart the kernel to load the new configuration
Option 2: don't use the adaptive algorithm and switch to the uniform meshing algorithm which uses Numpy and vectorization (usually done with adaptive=False and possibly setting an appropriate number of discretization points n=something)! This is very very fast in comparison to the adaptive algorithm.
Think about it: generally, our plots are relatively small in comparison to the screen size. 1000 points per line (or whatever number you decide to use) should create smooth-enough lines.
So, you can deactivate the adaptive algorithm on a plot-by-plot basis (with adaptive=False), or you can set the module to always use the uniform meshing algorithm (this is the setup that I use on my machine).
from spb.defaults import cfg, set_defaults
# disable adaptive algorithm
cfg["adaptive"]["used_by_default"] = False
set_defaults(cfg)
# restart the kernel to load the new configuration
Then, when you create a plot and you feel like it should be smoother, simply increase the number of discretization points by setting n=something (default value is 1000).
You can find more customization options on this documentation page.

Networkx attributes of imported graph

I import a .graphml file with
G = nx.read_graphml(file.graphml).
It's a graph that shows fuzzing status. There are some attributes like FuncSize, Coverage etc.
How can I visualize my graph? For example, FuncSize should affect node size. Coverage should affect
node color etc?

Can we get the list of followed edges of the current edge?

In SUMO, can we get the list of next edges (if there exits) given the current edge? Also, can we get the four incoming approaches to an normal intersection?
It depends if you want to use TraCI and need the following edge on the route of a specific vehicle or if you just want a static network analysis. For the latter you can use sumolib (at least if you can use python):
# import the library
import sumolib
# parse the net
net = sumolib.net.readNet('myNet.net.xml')
# retrieve the successor edges of an edge
nextEdges = net.getEdge('myEdgeID').getOutgoing()
# retrieve the incoming edges of the destination of an edge
nextEdges = net.getEdge('myEdgeID').getToNode().getIncoming()
see https://sumo.dlr.de/docs/Tools/Sumolib.html

Tensorflow: what's the SplitByWorker exactly done in distributed version?

In Tensorflow, there's a placement algorithm (which named as placer.cc in master branch) used for mapping node (op) to devices.
Supposed that in distributed TF, there's
1 client graph and 2 workers(or maybe more)
Without specifying node operations to specified workers or devices on workers such as with tf.device("/job:worker/task:7"):
Without using tf.train.replica_device_setter() for model replication on workers.
Question:
What's the SplitByWorker actually done?
I've read the SplitByDevice and it seems to retrive by node->device_name() if user explicitly specified a device and placement algo places the whole worker0 subgraph to /job:worker0/gpu:0
Is there any API or tf source code that actually make partition of client graph to different subgraphs, and send to different workers?
I know that tf.train.replica_device_setter() is used to create replicas on workers and for place parameters to ps. But without using this, can tensorflow partition model for me if there's more than 1 workers? (Obviously 1 worker get the whole client graph as its "subgraph")
What's the default option for tensorflow if the client doesn't partition the graph all all?
If the ans of 2 is NO, then I must partition by myself through explicit specifying. But how would tf do to if the client doesn't partition the graph all? Like placement algorithms default option is put all nodes on GPU:0, would it place the whole client graph to worker0 without partition and let worker1 be idle?
Please give me some insight for this, any answers or source code references are appriciated (:

Selective patterns with Matplotlib imshow without using patches

Is there a way to place patterns into selected areas on an imshow graph? To be precise, I need to make it so that, in addition to the numerical-data-carrying colored squares, I also have different patterns in other squares indicate different failure modes for the experiment (and also generate a key explaining the meaning of these different patterns). An example of a pattern that would be useful would be various types of crosshatches. I need to be able to do this without disrupting the main color-numerical data relationship on the graph.
Due to the back-end I am working within for the GUI containing the graph, I cannot utilize patches (they fail to pickle and make it from the back-end to the front-end via the multiprocessing package). I was wondering if anyone knew of another way to do this.
grid = np.ma.array(grid, mask=np.isnan(grid))
ax.imshow(grid, interpolation='nearest', aspect='equal', vmax = private.vmax, vmin = private.vmin)
# Up to here works fine and draws the graph showing only the data with white spaces for any point that failed
if show_fail and faildat != []:
faildat = faildat[np.lexsort((faildat[:,yind],faildat[:,xind]))]
fails = []
for i in range(len(faildat)): #gives coordinates with failures as (x,y)
fails.append((faildat[i,1],faildat[i,0]))
for F in fails:
ax.FUNCTION NEEDED HERE
ax.minorticks_off()
ax.set_xticks(range(len(placex)))
ax.set_yticks(range(len(placey)))
ax.set_xticklabels(placex)
ax.set_yticklabels(placey, rotation = 0)
ax.colorbar()
ax.show()