1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
"""
Knuth Miles
===========
An example that shows how to add your own positions to nodes
and have graphviz "neato" position the edges.
miles_graph() returns an undirected graph over the 128 US cities from
the datafile miles_dat.txt.
This example is described in Section 1.1 in Knuth's book [1]_ [2]_.
The data used in this example is copied from [2]_. The filename and
header have been modified to adhere to the request of the author to
not corrupt the original source file content and name.
References.
-----------
.. [1] Donald E. Knuth,
"The Stanford GraphBase: A Platform for Combinatorial Computing",
ACM Press, New York, 1993.
.. [2] http://www-cs-faculty.stanford.edu/~knuth/sgb.html
"""
__author__ = """Aric Hagberg (aric.hagberg@gmail.com)"""
def miles_graph():
"""Return a graph from the data in miles_dat.txt.
Edges are made between cities that are less then 300 miles apart.
"""
import math
import re
import gzip
G = pgv.AGraph(name="miles_dat")
G.node_attr["shape"] = "circle"
G.node_attr["fixedsize"] = "true"
G.node_attr["fontsize"] = "8"
G.node_attr["style"] = "filled"
G.graph_attr["outputorder"] = "edgesfirst"
G.graph_attr["label"] = "miles_dat"
G.graph_attr["ratio"] = "1.0"
G.edge_attr["color"] = "#1100FF"
G.edge_attr["style"] = "setlinewidth(2)"
cities = []
for line in gzip.open("miles_dat.txt.gz", "rt"):
if line.startswith("*"): # skip comments
continue
numfind = re.compile(r"^\d+")
if numfind.match(line): # this line is distances
dist = line.split()
for d in dist:
if float(d) < 300: # connect if closer then 300 miles
G.add_edge(city, cities[i])
i = i + 1
else: # this line is a city, position, population
i = 1
(city, coordpop) = line.split("[")
cities.insert(0, city)
(coord, pop) = coordpop.split("]")
(y, x) = coord.split(",")
G.add_node(city)
n = G.get_node(city)
# assign positions, scale to be something reasonable in points
n.attr["pos"] = (
f"{-(float(x) - 7000) / 10.0:f},{(float(y) - 2000) / 10.0:f}"
)
# assign node size, in sqrt of 1,000,000's of people
d = math.sqrt(float(pop) / 1000000.0)
n.attr["height"] = f"{d / 2}"
n.attr["width"] = f"{d / 2}"
# assign node color
n.attr["fillcolor"] = f"#0000{int(d * 256):2x}"
# empty labels
n.attr["label"] = " "
return G
if __name__ == "__main__":
import warnings
import pygraphviz as pgv
# ignore Graphviz warning messages
warnings.simplefilter("ignore", RuntimeWarning)
G = miles_graph()
print("Loaded miles_dat.txt containing 128 cities.")
G.write("miles.dot")
print("Wrote miles.dot")
G.draw("miles.png", prog="neato", args="-n2")
print("Wrote miles.png")
|