I am trying to build a dependecy scheme of a program as a digraph in dot. Therefore I used the following code:
digraph LINK {
rankdir=LR;
ranksep=0.65;
nodesep=0.40;
splines=false;
overlap=false;
concentrate=false;
node[shape=box];
subgraph clusterAPP {
label="Application";
style=dashed;
nodeA[label="d = func(...);"];
};
subgraph clusterFB{
color=red;
label="Wrapper";
style=dashed;
rank=same;
wrapper[label="wrapper"];
real[label="pointer to\nreal func"];
wrapper -> real [constraint=false,label="dlopen\ndlsym"];
}
subgraph clusterBACKEND {
label="Backend"
style=dashed;
func[label="float func(...)"];
};
nodeA -> wrapper;
real -> func[weight=10];
func->real[color=blue];
}
This results in
The problems are now:
The egdes between real and func overlap. How can I separate them that they are easy to recognize.
Why has the edge from wrapper to real the wrong direction?
The answer to your first question has already been given elsewhere here on Stackoverflow, what it boils down to is you can either use ports postions or use the trick mentioned by the infamous marapet to add an extra edge in the same direction, remove it's constraint and reverse the edge's direction and hide the edge pointing back.
Or to put it in code:
real -> func [weight=10] // Remains unaltered
real -> func [constraint=false, dir=back] // Remove the constraint and reverse the edge
func -> real [style=invis] // Hide the edge pointing pack
As to why the other edge is pointing in the wrong direction, this has to do with a bug in relation to constraint and should be fixed in version 2.27. You may be working with an older version. (I know I am, as a lot of *NIX package managers still have 2.26.X by default).
To fix this you will either need to manually update your Graphviz to a newer version or (if you already have a newer version or can't/don't want to update) add dir=back to that nodes attribute.
Putting everything together the result is this:
Using the following DOT code:
digraph LINK {
rankdir=LR;
ranksep=0.65;
nodesep=0.40;
splines=false;
overlap=false;
concentrate=false;
node[shape=box];
subgraph clusterAPP {
label="Application";
style=dashed;
nodeA[label="d = func(...);"];
};
subgraph clusterFB{
color=red;
label="Wrapper";
style=dashed;
rank=same;
wrapper[label="wrapper"];
real[label="pointer to\nreal func"];
}
subgraph clusterBACKEND {
label="Backend"
style=dashed;
func[label="float func(...)"];
};
nodeA -> wrapper;
wrapper -> real [constraint=false, dir=back, label="dlopen\ndlsym"]; // Added reverse direction
real -> func [weight=10] // Remains unaltered
real -> func [constraint=false, dir=back] // Remove the constraint and reverse the edge
func -> real [style=invis] // Hide the edge pointing pack
}
Related
I have a code that allows me to perform a cluster. i want to move the label to the border of the cluster in the output. I have tried labelloc=l and other options but i am unable to make it work. attached is the one i got from graphviz while the other one is what i was expecting. is there a way to modify the code, add plugin or gvpr to get the desired output?
digraph AlignmentMap {
/*
/*
Author: Lars Barkman
Created: 2015-08-25
Changelog: See version control system
This is an example of an Alignment Map visualized with the help of Graphviz.
This solution depends on either generation or maintaining a .dot file and from that generating a image or document.
Personally, I think that editing the file by hand should be fine if the naming conventions used are intuitive.
Alignment maps first came to my attention on Martin Fowlers blog (http://martinfowler.com/bliki/AlignmentMap.html).
*/
// General layout of the graph
rankdir=LR; // Direction of the graph Left to Right
node [style="rounded,filled",color=black,shape=box,fillcolor=white]; // Defines the default layout of the nodes
graph [style=filled, splines=line]; // Fills the subgraphs and defines the layout of the connections
rank = same; // Makes sure that nodes are properly aligned even without a connection
// Column for Business Outcomes
subgraph cluster_business_outcome {
label="Business Outcomes"
graph [color=pink];
business_outcome_Customer_Acquisition [label="Customer\nAcquisition"];
business_outcome_Customer_Retention [label="Customer\nRetention"];
business_outcome_Cost_of_Operations [label="Cost of\nOperations"];
}
// Column for IT Outcomes
subgraph cluster_IT_outcome {
label=< <table>
<tr><td fixedsize="true" width="50" height="50"><img src="./Azure-PlantUML-master/dist/Identity/AzureActiveDirectory.svg" /></td></tr>
<tr><td>Active Directory</td></tr>
</table>
>
graph [color=mistyrose2];
IT_outcome_Platform_Unbundling [label="Platform\nUnbundling"];
IT_outcome_Site_Ux [label="Site Ux"];
IT_outcome_Site_Performance [label="Site\nPerformance"];
IT_outcome_Site_Scalability [label="Site\nScalability"];
}
// Column for IT Initiatives
subgraph cluster_IT_initiatives {
label="IT Initiatives"
graph [color=papayawhip];
IT_initiatives_API [label="API"];
IT_initiatives_Pluginize [label="Pluginize"];
IT_initiatives_Responsive_Rewrite [label="Responsive\nRewrite"];
IT_initiatives_Catalog_Performance [label="Catalog\nPerformance"];
IT_initiatives_Sharding [label="Sharding"];
}
// Column for Action Items
subgraph cluster_action_items {
label="Action Items"
graph [color=darkseagreen1];
action_items_0 [label="..."];
action_items_1 [label="..."];
action_items_App_X [label="App X"];
action_items_Search_In_One [label="Search-\nIn-One"];
action_items_4 [label="..."];
}
// Connections between nodes in the different columns
// business_outcome_* -> IT_outcome_Platform_*
business_outcome_Customer_Acquisition -> IT_outcome_Platform_Unbundling;
business_outcome_Customer_Acquisition -> IT_outcome_Site_Ux;
business_outcome_Customer_Retention -> IT_outcome_Site_Ux;
business_outcome_Customer_Retention -> IT_outcome_Site_Performance;
business_outcome_Cost_of_Operations -> IT_outcome_Site_Performance;
business_outcome_Cost_of_Operations -> IT_outcome_Site_Scalability;
// IT_outcome_* -> IT_initiatives_*
IT_outcome_Platform_Unbundling -> IT_initiatives_API;
IT_outcome_Platform_Unbundling -> IT_initiatives_Pluginize;
IT_outcome_Site_Ux -> IT_initiatives_Responsive_Rewrite;
IT_outcome_Site_Performance -> IT_initiatives_Catalog_Performance;
IT_outcome_Site_Scalability -> IT_initiatives_Sharding;
// IT_initiatives_* -> action_items_*
IT_initiatives_API -> action_items_0;
IT_initiatives_Pluginize -> action_items_1;
IT_initiatives_Responsive_Rewrite -> action_items_App_X;
IT_initiatives_Catalog_Performance -> action_items_Search_In_One;
IT_initiatives_Sharding -> action_items_4;
}
The one on right is graphviz and left is what i expect
(sorry, I misunderstood the request)
Here is a gvpr "fix".
run dot -Tdot to position the nodes, edges, clusters
run that result through gvpr (program below) to remove the label and replace it with a (new) node
run that (modified) result through neato -n2 -Tsvg (see https://graphviz.org/faq/#FaqDottyWithCoords)
[note that I had to tweak the html to remove borders:]
label=< <table BGCOLOR="transparent" BORDER="0" CELLBORDER="0" CELLSPACING="0">
<tr><td fixedsize="true" width="50" height="50"><img src="image_dir/Face-smile.svg" /></td></tr>
<tr><td>Active Directory</td></tr>
</table>
>
commandline:
dot -Tdot myfile.gv|gvpr -c -f moveLabel.gvpr | neato -n2 -Tsvg >myfile.svg
moveLable.gvpr:
BEGIN{
string saveLbl, saveX, saveY, workS;
graph_t theG;
node_t newNode;
}
BEG_G{
print("// ONE");
theG=subg($G, "cluster_IT_outcome");
saveLbl=theG.label;
// next 3 steps get the left X coordinate of the cluster
workS=llOf(theG.bb);
workS=xOf(workS);
saveX=(float)workS;
// now get Y coordinate of label
workS=yOf(theG.lp);
saveY=(float)workS;
theG.label=""; // remove label from cluster
}
END_G{
// create new node to replace cluster label
newNode=node($G, "__myNewNode");
newNode.pos=sprintf("%.2f,%.2f", saveX, saveY);
newNode.shape="plain";
newNode.fillcolor="none";
newNode.label=html($G, saveLbl);
}
In flowcharts, one of the "standard" node shapes is that of a terminal:
But this shape does not seem to be directly supported by Graphviz, according to the documentation here. This seems a bit strange to me...
Is there some way to get graphviz to draw this shape, that I'm missing?
Try shape=Mrecord, like so:
digraph D {
A [shape=Mrecord label="Tip Top"];
A -> B
}
Giving:
You can use "rounded style" on your node shapes, e.g.:
digraph G {
node [style="rounded", shape=box]; a;
node [style="" shape=box]; b;
a -> b;
}
produces this:
I need to print a large number of graphs using Graphviz DOT. To distinguish which input each graph corresponds to, I want to also have a caption for each graph. Is there anyway to embed this into the DOT representation of the graphs.
You can use label to add a caption to the graph.
Example:
digraph {
A -> B;
label="Graph";
labelloc=top;
labeljust=left;
}
labelloc and labeljust can be used to determine top/bottom and left/right position of the graph label.
All the details and other attributes that can be used to modify the label (font etc) in the graphviz attribute reference.
Tip: Define the graph label end of your dot file, otherwise subgraphs will inherit those properties.
Graph's can have attributes just like nodes and edges do:
digraph {
graph [label="The Tale of Two Cities", labelloc=t, fontsize=30];
node [color=blue];
rankdir = LR;
London -> Paris;
Paris -> London;
}
That dot file produces this graph.
If you are looking for a way to add a caption to a Graph object of graphviz in python. Then the following code can help:
from graphviz import Graph
dot = Graph()
dot.node('1','1')
dot.node('2','2')
dot.edge('1','2', label="link")
dot.attr(label="My caption")
dot.attr(fontsize='25')
dot.render(view=True)
Output:
I am trying to draw a graph using Graphviz, but I need to add labels on the edges. There does not seem to be any way to that in Graphviz.
Are there a way out?
You use the label property attached to the edge.
digraph G {
a -> b [ label="a to b" ];
b -> c [ label="another label"];
}
The above generates a graph that looks something like this.
#Andrew Walker has given a great answer!
It's also worth being aware of the labeltooltip attribute. This allows an additional string to be attached to the label of an edge. This is easier for a user than the tooltip attribute, as it can be fiddly to hover directly on an edge. The syntax is as follows:
digraph G {
a -> b [label=" a to b" labeltooltip="this is a tooltip"];
b -> c [label=" another label" ];
}
Which gives the following result:
Landed here by googling whether labels could be on arrow's ends, for UML's composition/aggregation. The answer is yes:
"Person" -> "Hand" [headlabel="*", taillabel="1"]
You can use label="\E" It will generate bye default label.
For Example:
digraph G {
a -> b [ label="\E" ];
b -> c [ label="\E"];
}
When I changed the rankdir of my graph from LR to TD, my record nodes also changed their layout direction so they no longer look like a 'record'. I tried applying a separate rankdir to the nodes, but this had no effect.
How does one keep the record nodes with the correct layout?
digraph sample {
graph [rankdir=TD];
node [shape=record];
A [label="ShouldBeTop | ShouldBeBottom"];
B [label="Top | Bottom"];
A -> B;
}
Taking into account that rankdir effectively replaces the notion of "top" and "bottom" for the given graph, that's not surprising.
I am afraid that there is no easy remedy for this, save hacking the source (and that would not be easy at all). You can surround your labels in "{}" with some kind of mass search-replace solution to get the requested effect:
digraph sample { graph [rankdir=TD]; node [shape=record];
A [label="{ShouldBeTop | ShouldBeBottom}"];
B [label="{Top | Bottom}"]; A -> B;
}
You can use html table like labels instead of records. IIRC the table based labels do not rotate with the rank direction. See http://www.graphviz.org/doc/info/shapes.html#html