chiark / gitweb /
I'm sure I've done something since I remembered to commit...
[familyTree.git] / cgiFiles / make_dot.py
1 #!/usr/bin/python
2
3 import cgi
4 #import cgitb
5 import gv
6 import re
7 import sys
8 sys.path.append('/home/naath/familyTreeProject/familyTree')
9 import askQuestion as aQ
10 import englishUtils as eU
11
12 #cgitb.enable()
13 def add_quotes(s):
14         return '\"'+str(s)+'\"'
15
16 def add_node(node,node_attr):
17         na = attr_string(node_attr)
18         if not has_node(node):
19                 nodes[node] = na
20         elif node_attr[-2][1]==highlight_attr[0][1]:    
21                 nodes[node] = na
22
23 def has_node(node):
24         if node in nodes.keys():
25                 return 1
26         else:
27                 return 0
28 def has_edge(edge):
29         edge[0] = add_quotes(edge[0])
30         edge[1] = add_quotes(edge[1])
31         if edge in edges.keys():
32                 return 1
33         else:
34                 return 0
35
36 def add_edge(n1,n2,edge_attr):
37         edge = (add_quotes(n1),add_quotes(n2))
38         edge_attr = attr_string(edge_attr)
39         if edge not in edges.keys():
40                 edges[edge] = edge_attr
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         if len(children)>0 and joinChildren==1:
61                 cNode = jN + 'c'
62                 tcNode = cNode + children[0]
63                 
64                 if cNodes.has_key(cNode):
65                         if not has_node(tcNode):
66                                 if len(cNodes[cNode])>0:
67                                         last = cNodes[cNode][-1]
68                                 add_spot(tcNode)
69                                 cNodes[cNode].append(tcNode)
70                                 add_no_arrow(last,tcNode)
71                                 add_subgraph([tcNode,last])
72                 else:
73                         add_spot(tcNode)
74                         cNodes[cNode] = [tcNode]
75                         add_no_arrow(jN,tcNode)
76
77
78         elif len(children)>0:
79                 tcNode = jN
80
81         for c in children:
82                 add_person(c)
83                 add_arrow(tcNode,c)
84
85         m = 1
86         good = 1
87         try:
88                 id1 = int(n1.split(',')[-1])
89                 id2 = int(n2.split(',')[-1])
90
91                 m = aQ.is_married(id1,id2)
92         except:
93                 m = 1
94
95         for n in [n1, n2]:
96                 if m==1:
97                         add_edge(n,jN,marriage_attr)
98                 else:
99                         add_edge(n,jN,not_marriage_attr)
100         add_subgraph([n1,n2])
101
102
103 def add_subgraph(myG):
104         global subgraphs
105         if myG not in subgraphs:
106                 subgraphs.append(myG)
107         
108
109 def start_dot(fs):
110         global nodes
111         global edges
112         global cNodes
113         global dot
114         global subgraphs
115
116         nodes = dict()
117         edges=dict()
118         cNodes={}
119         dot = "digraph G{\n"
120         dot = dot + "ranksep = 0.2 nodesep = 0.1\n"
121         subgraphs=[]
122         set_attr(fs)
123
124 def create_dot():
125         global dot
126
127         for node in nodes.keys():
128                 dot +=add_quotes(node) + nodes[node] + ";\n"
129
130         for edge in edges.keys():
131                 dot += edge[0] + ' -> ' + edge[1] + edges[edge] + ";\n"
132
133 def add_subgraphs():
134         global dot
135         for sg in subgraphs:
136                 line = "\n{rank=same "
137
138                 for n in sg:
139                         line  +=add_quotes(n) + ' '
140
141                 line += "}"
142
143                 dot+=line
144
145 def end_dot():
146         global dot
147         dot = dot + "}"
148
149
150 def arrange_name(name):
151
152         ln = name.replace('  ',' ')
153         ln = ln.replace(', ','\\n')
154         ln = ln.replace(',','\\n')
155         ln = ln.replace(' ','\\n')
156
157         return str(ln)
158
159 def add_highlight(name):
160         try:    
161                 k=eU.isKing(name)
162         except: 
163                 k=0
164
165         myLabel =str(arrange_name(name))
166
167         if k==1:
168                 add_node(name,king_attr+[('label',myLabel)]+highlight_attr)
169         else:
170                 add_node(name,person_attr+[('label',myLabel)]+highlight_attr)   
171
172 def add_person(name):
173         try:
174                 k=eU.isKing(name)
175         except:
176                 k=0
177         myLabel = str(arrange_name(name))
178
179         if k==1:
180                 add_node(name,king_attr+[('label',myLabel)])
181         else:
182                 add_node(name,person_attr+[('label',myLabel)])
183
184 def add_spot(name):
185         add_node(name,spot_attr)
186
187
188 def set_attr(fs):
189         global person_attr
190         global highlight_attr
191         global king_attr
192         global spot_attr
193         global edge_attr
194         global invis_attr
195         global ignored_attr
196         global nodir_attr
197         global marriage_attr
198         global not_marriage_attr
199         global debug_attr
200         global debug_edge_attr
201         zero_size = [('width','0'),('height','0'),('fontsize',str(fs))]
202         person_attr = [('shape','plaintext'),('margin','0')] +\
203                 zero_size
204         highlight_attr =  [('fillcolor','yellow'),('style','filled,bold')]
205         king_attr = person_attr +\
206                 [('fontcolor','purple4'),('shape','house'),('color','purple4')]
207         debug_attr = person_attr + [('fontcolor','green')]
208         spot_attr = [('shape','point')] + zero_size
209         edge_attr = [('len','0'),('arrowsize','0.5')]
210         debug_edge_attr = edge_attr + [('color','green')]
211         invis_attr = edge_attr + [('style','invis')]
212         nodir_attr = edge_attr + [('dir','none')]
213         marriage_attr = nodir_attr + [('weight','10'),('color','red')]
214         not_marriage_attr = nodir_attr+[('weight','10'),('color','blue')]
215         ignored_attr =edge_attr + [('constraint','false')] + nodir_attr
216
217 def attr_string(attr):
218         
219         attr_str = '['
220         for a in attr:
221                 attr_str = attr_str + a[0] + '="' + a[1]+'"'
222                 if a != attr[-1]:
223                         attr_str = attr_str +','
224
225         attr_str = attr_str + ']'
226         return attr_str
227
228 def render_dot():
229
230         f = open('tempfile','w')
231         f.write(dot)
232         f.close
233
234         gvv = gv.readstring(dot)
235         gv.layout(gvv,'dot')
236
237         format = 'png'
238
239         print "Content-type: image/" + format + "\n"
240         print gv.render(gvv,format)
241
242
243 def render_to_file(file):
244         f = open('/home/naath/familyTreeProject/cgiFiles/biggraphfile','w')
245         f.write(dot)
246         f.close
247         gvv = gv.readstring(dot)
248         gv.layout(gvv,'dot')
249         format = 'png'
250         gv.render(gvv,format,file)
251
252
253 global dot
254 global nodes
255 global edges
256 global subgraphs
257 global cNodes