chiark / gitweb /
faff with graphs and searching
[familyTree.git] / cgiFiles / make_dot.py
1 #!/usr/bin/python
2
3 import cgi
4 import cgitb
5 import gv
6 import re
7
8 cgitb.enable()
9 def add_quotes(s):
10         return '\"'+str(s)+'\"'
11
12 def add_node(node,node_attr):
13         global dot
14         global nodes
15         node_attr = attr_string(node_attr)
16         if node not in nodes:
17                 dot = dot + add_quotes(node) + node_attr + ";\n"
18                 nodes.append(node)
19
20 def has_node(node):
21         if node in nodes:
22                 return 1
23         else:
24                 return 0
25 def has_edge(edge):
26         edge[0] = add_quotes(edge[0])
27         edge[1] = add_quotes(edge[1])
28         if edge in edges:
29                 return 1
30         else:
31                 return 0
32
33 def add_edge(n1,n2,edge_attr):
34         global dot
35         global edges
36         edge = (add_quotes(n1),add_quotes(n2))
37         edge_attr = attr_string(edge_attr)
38         if edge not in edges:
39                 dot = dot + edge[0] + ' -> ' + edge[1] + edge_attr + ";"
40                 edges.append(edge)
41
42 def add_arrow(n1,n2):
43         add_edge(n1,n2,edge_attr)
44
45 def add_no_arrow(n1,n2):
46         add_edge(n1,n2,nodir_attr)
47
48 def add_marriage(n1,n2,children,joinChildren):
49         global cNodes
50         
51         jN = n1+n2
52         jNRev = n2+n1
53         if has_node(jNRev):
54                 jN = jNRev
55         add_spot(jN)
56         add_person(n1)
57         add_person(n2)
58
59         
60
61         if len(children)>0 and joinChildren==1:
62                 cNode = jN + 'c'
63                 tcNode = cNode + children[0]
64                 
65                 if cNodes.has_key(cNode):
66                         if not has_node(tcNode):
67                                 if len(cNodes[cNode])>0:
68                                         last = cNodes[cNode][-1]
69                                 add_spot(tcNode)
70                                 cNodes[cNode].append(tcNode)
71                                 add_no_arrow(last,tcNode)
72                                 add_subgraph([tcNode,last])
73                 else:
74                         add_spot(tcNode)
75                         cNodes[cNode] = [tcNode]
76                         add_no_arrow(jN,tcNode)
77
78
79         elif len(children)>0:
80                 tcNode = jN
81
82         for c in children:
83                 add_person(c)
84                 add_arrow(tcNode,c)
85         for n in [n1, n2]:
86                 add_edge(n,jN,marriage_attr)
87         add_subgraph([n1,n2])
88
89
90 def add_subgraph(myG):
91         global subgraphs
92         subgraphs.append(myG)
93         
94 def add_subgraphs():
95         global dot
96         for sg in subgraphs:
97                 line = "\n{rank=same "
98
99                 for n in sg:
100                         line = line +add_quotes(n) + ' '
101
102                 line = line +"}"
103
104                 dot = dot + line
105
106 def end_dot():
107         global dot
108         dot = dot + "}"
109
110 def start_dot(fs):
111         global dot
112         global nodes
113         global edges
114         global subgraphs
115         global cNodes
116         nodes=[]
117         edges=[]
118         cNodes={}
119         dot = "digraph G{\n"
120         dot = dot + "ranksep = 0.5 nodesep = 0\n"
121         subgraphs=[]
122         set_attr(fs)
123
124 def add_highlight(name):
125         add_node(name,highlight_attr)
126
127 def add_person(name):
128         add_node(name,person_attr)
129
130 def add_spot(name):
131         add_node(name,spot_attr)
132
133
134 def set_attr(fs):
135         global person_attr
136         global highlight_attr
137         global spot_attr
138         global edge_attr
139         global invis_attr
140         global ignored_attr
141         global nodir_attr
142         global marriage_attr
143         global debug_attr
144         global debug_edge_attr
145         zero_size = [('width','0'),('height','0')]
146         person_attr = [('fontsize',str(fs)),('shape','plaintext')] + zero_size
147         highlight_attr = person_attr + \
148                 [('fontcolor','red'),('shape','box'),('color','red')]
149         debug_attr = person_attr + [('fontcolor','green')]
150         spot_attr = [('shape','point')] + zero_size
151         edge_attr = [('len','0'),('arrowsize','0.5')]
152         debug_edge_attr = edge_attr + [('color','green')]
153         invis_attr = edge_attr + [('style','invis')]
154         nodir_attr = edge_attr + [('dir','none')]
155         marriage_attr = nodir_attr + [('weight','10'),('color','red')]
156         ignored_attr =edge_attr + [('constraint','false')] + nodir_attr
157
158 def attr_string(attr):
159         
160         attr_str = '['
161         for a in attr:
162                 attr_str = attr_str + a[0] + '=' + a[1]
163                 if a != attr[-1]:
164                         attr_str = attr_str +','
165
166         attr_str = attr_str + ']'
167         return attr_str
168
169 def render_dot():
170         gvv = gv.readstring(dot)
171         gv.layout(gvv,'dot')
172
173         format = 'png'
174
175         print "Content-type: image/" + format + "\n"
176         print gv.render(gvv,format)