COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
networkxpython.py
Go to the documentation of this file.
1 # Copyright (C) 2010-2013 von Karman Institute for Fluid Dynamics, Belgium
2 #
3 # This software is distributed under the terms of the
4 # GNU Lesser General Public License version 3 (LGPLv3).
5 # See doc/lgpl.txt and doc/gpl.txt for the license text.
6 
7 #########################################################################################
8 # import needed stuff
9 #########################################################################################
10 from cStringIO import StringIO
11 from copy import deepcopy
12 import numpy
13 import Image
14 import base64
15 import sys
16 import math
17 import matplotlib.pyplot as plt
18 import networkx as nx
19 import coolfluid as cf
20 
21 #########################################################################################
22 # color settings
23 #########################################################################################
24 titlecolor='white'
25 bgcolor='black'
26 navicolor='yellow'
27 componentcolor='#aaaaaa'
28 optioncolor='#2a83bd'
29 fieldcolor='#3a773a'
30 signalcolor='#aa6d00'
31 tagcolor='#5a5ab7'
32 linkcolor='#aaaaaa'
33 propertycolor='#cc4444'
34 
35 #########################################################################################
36 # base64 coded png image for root component
37 #########################################################################################
38 cf3_b64="""iVBORw0KGgoAAAANSUhEUgAAADIAAAAgCAYAAABQISshAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wBFRM6KYr0o9UAA
39 AAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAJpUlEQVRYw61YT4hdVxn/fd93zr33vTeTTCZJmzY2kCGlmPQfWqQtKCIupJtCF9qFQsFVtFCycJVFyMZlSEFQcOGmxCLdqt2JqC2V0
40 mqxVlBM2iammdZmZvJm3rv3/PlcnHPvu7ex7cQ6cDn3ngyT73d/f77vXDpz5syYmVZ3dpbvWV+/7VlmPlGWghhjvgJCSPdpDZ+475zv/U6Eqg7+FgBYW6Asy5cPHJBvHTq0feX8+R/GJ598Es8//zz+1
41 x/DzPtV5cT6+h2/Xlvbh/vvPwznPJrGd2vTBDjn8r1H0/TvG9R12qtrh7pusLGxDVUdgFCNUAWstTDGgtk8PJ3aX50/f/q+J5544jOBaIHcOZ1Ovr68XODEiTswn7sBEOcCmsZ1awvEOY+6Ts9pdd0zo
42 B0bfUAiBsZYGGNgrSERe+9TT507fvTojbdeeeWVXRUcQkBd13ry5ElcunQJFy5cSEAA/Zxz/ODx47er94FS8QlAujy8Dz1gLbj+2oJPgEJYSCoxEcHMmQ2BMRYiiZkQ8Ijq1j+feeaZuBsgRIQYI4goH
43 j9+PJ46dUqfe+45NUQ4AOh+IiLnArwPcC7C+2HR3rcSG8qrL7m6buC9B6CqquR9RAjJF0VRADAgsiCyYLYwpsCIpnvu+/uF8cEqhNJYWGtQFBbWWhTWoLAWhc37eU+0Vuy94fHt383xwmNkJ98jA9AE0
44 CoB8B0LfUZS8UMQzgXUtYP3Hjs7Neq6aZnQGCMdO2b+evTo6O2iINd/o6o+An5GNH1X/M6brx377smf8TfPOefRuPxinEeTWXbOofEebrbYb5yHdw7h99+HZX71G8v/+poBYAFwCAHOCYbS6oNwnYRal
45 uraYTqdwXuPGCMAharSaIQrd99d/CJG3QwBXlWViFpxAEBUBRDtCpqdJS9FUoD38C6x317OD5998AjeI4QAFgGEH/rN/K5nDQBWjdRnZHGfQCRZDT2xszPH1tYMqhExDhPqgQfKH4UQ/gjQhqqGxIT2W
46 FHDzHcA9KC6+V6H0BXswqJ45z18SP/mfP4dF+BDADFDmFFZgwj6jgGgAHLxlIsdymwYxR43bsywvT2HagQwTCdVxZ13mt9ubvq3gbjNzLEPIjGHMYAJiCbqXeUpFep9yGsC4UIYMOJc2iciiDCqwmBcG
47 NQRxgAgVYVzESIxp1RfWq5jomk8trZ2MJvVvcKRWen6hVqL92IMH+7Zs6dZWlpS5xY2uX79OmazGcbjsQdgQgjisGDAOZfffoBvZe4DmiwrAB0TlRWMrEFwESZRjVw8/isD7XMLoo3V5ImPMhJhTJyFE
48 Ny5c+fi1atXB/H59NNPYzwexxijkhCFGMhpC2IhpQTMpefcAlQBEUGZQVSFQVkazGMAZ9Xio6nVT6emSck0ZKI/eiz6BRHBWo6rq/uxsrJyUx9IMdxrcD4siu2Kbv2xUEiMEcKMQhIbo8JmVgyMcGIEA
49 JwLefU9Vtqu7rC1tdMrWDuD90EBgIgFM2kXUp/Y3QAfA1xoi+/5w6ek9L2EImZUpUVVJDZGhWBUCMw8tEASI0TaAehLbGNjp0udVj6tL9p7VXRduwX16TgIIUT42AMRkukXcZtACDMKKxgXglGRpZUlJ
50 iKtRzRrMA684ZzDfN501LZM9NlI9xHMCYS1uwfSzk6p+F7sukX0EhGECMyE5cqiKkxiJMuqMgZG/NDsIfTN7tA0AdPpvMdGHLDRNkEihjEmz1ACVXcLQOJNIHxI/QKUEoqFMS4tJqXFyNpsdEFpGWUhE
51 OHW7OhGkv78VNfN4Ezx0X6Rplztptp27feNXTHSNr7c7JwPUCiYBcwEZsbKuEBlBWWWVNmTlhGGIUBbj6jGQdzO583AF8OESiBaJtJq8kS7S48Q4MNikvDB5YNZSihhArPg4HKFUWFQWoORlc4fpRWUR
52 mBYYBQgQOGcR2qMvpujFizc3CtUFSKcWWjBJFZSj9md3WOMvb4REGLITHDHxKQ0OXJbJvJlJJudFx5Jb0K7uPU+dL4Y9gtF8jJBxMBaM2DDWnsLQLCYpTIzRC0TjElpsDIuO0mV1mRvJBAdI8IwREnSL
53 aWttBbFDz3RdvSWgeGVAN1KavkQu3GEiCCZjXFpcHB51HXwxAKjNElWRQcuxS+rIjJraBqv7RG23ysW/WIRvSKS2bCD46sxJkvr483u09BHIsIEsA+BgvcAEYQJIoSlyuC25VF684Xpii9NAlSaBKg0j
54 NJmBlXRjEY6reuGnAsDJlo2+tHLTBCx3UeEBYjFcyutpmluMsXa2hpVVWVUtRCK9srcLkVVMCVjr05KrE4qlEUeDHP3rgrpZNX6pDSCUgQmN8TN5eV4TVUGLCzY0G4FMPCDiHQGT2fwtO+cynS6aR9//
55 HFm5i75jhw5gvfff99YaycA7Xtte+9dG84YI0BhDFaXCozKIidTbn4meSOx0TIhKAxneTEMM4yqvsfMFx9+OLz6+ut63+amlouDknbfqFSTLwCbz90GzAWYLZgLiKTLmIK+uPUHfH62aQ/MLoutSqAqg
56 bIEcIjeXT1S/iUe2veTD459+cWNA49ZIV2qLE1y1x4NPLEwdmUZhUmpVVhBZTiBMZxSS4HLqvrnoiB69FF6JwQaqxpJ56128tP+MRVABDDPV7exDeBSVPztBys/vepdrU0eNZrGwTUezeX8tcV5qp1HZ
57 UTHlaFxaTHK8VoVgjID6Te/tvjSMCrJbEhiR4RhKIaryvInVd2MEQeJqAKUaTC+fvIoq8lIEYAT0qXeaS99XgqLY2p7ZC0NY1wa6gbAwvTmJ0FlWllxx0qRfVFYQSGMwjIqI5h7wATFFqtejDFeF5GJq
58 tp8aqRb/NhnAdzOiPeXbmtr5mXPcIYK3XkcQDcvJS+0hyXTm6MEZZEBtcbup5URVMJ4c32mMx9rM51O3fLy8haAnaZpTFmWrKp0K/NS/mA2YmZWFnzVvfbmC+ELjyQQ7QyVQLQTgVeCFYExDGGBkdQEk
59 xIICoIqEAD4CIgCEgGnAAWF14iXLs/08g1Pe+P05+aNN97Qw4cPu8lk4kejEa2trd0SCABYX1+H976JMf5bla6tYHrlK3jr4i/d0aONC2h8gGsCYlSQCMCMAMYHswBpAOEIIwwWn5IwT7xGsv45N71uT
60 yBCEBY64D546aFrL/6Y8H/6OX36tLHW7mfmewF8SZjuiUr7GuWC6ONMRt3weJMf6WOdqVAEELYJesmG+mWn/Lo5c+YMzp49+5mBhBBCURRbqvoPIvIh6jtE2FNyNJ/qN93lXu+/06jbAK558EXV+OF/A
61 OQy9FESRGTLAAAAAElFTkSuQmCC"""
62 
63 #########################################################################################
64 # setting up the matplotlib layout
65 #########################################################################################
66 
67 # coolfluid head component
68 root = cf.Core.root()
69 
70 #figures and axes
71 fig=plt.figure(figsize=(10,10))
72 mainax=plt.axes([0,0,1,1],axisbg=bgcolor,label='main')
73 naviax=plt.axes([0.65,0.01,0.34,0.34],axisbg=bgcolor,label='navi')
74 plt.sca(mainax)
75 
76 # turning off ticks, labels and frame both for the main plot and the little navigation plot
77 mainax.xaxis.set_visible(False)
78 mainax.yaxis.set_visible(False)
79 for i in mainax.spines: mainax.spines[i].set_visible(False)
80 naviax.xaxis.set_visible(False)
81 naviax.yaxis.set_visible(False)
82 for i in naviax.spines: naviax.spines[i].set_color(titlecolor)
83 naviax.set_visible(False)
84 
85 # setting up the text object of the title and decode+load the cf logo image
86 titletxt=plt.text(0.02,0.98,'',transform=mainax.transAxes, size=16, weight='bold',color=titlecolor, ha='left', va='top',zorder=50)
87 cf3_png=StringIO(base64.decodestring(cf3_b64))
88 cf3_img=Image.open(cf3_png)
89 plt.imshow(cf3_img,aspect='auto',zorder=41)
90 plt.gca().add_patch(plt.Rectangle([20,5],12,22,facecolor=bgcolor,lw=0,fill=True,zorder=40))
91 
92 
93 #########################################################################################
94 # custom-made layouts
95 # traditional_left2right_tree_layout(G,key,pos)
96 # traditional_left2right_tree_layout_in_polar(G,key)
97 #########################################################################################
99  for i in G.successors(key):
100  if G.node[i]['tag']=='link':
101  if not ((G.edge[key][i]['tag']=='link') and (G.node[i]['tag']!='link')) :
102  pos[i]=[G.node[i]['depth'],y]
103  y+=1
104  y=traverse_successors_recursive(G,i,pos,y)
105  for i in G.successors(key):
106  if G.node[i]['tag']=='option':
107  if not ((G.edge[key][i]['tag']=='link') and (G.node[i]['tag']!='link')) :
108  pos[i]=[G.node[i]['depth'],y]
109  y+=1
110  y=traverse_successors_recursive(G,i,pos,y)
111  for i in G.successors(key):
112  if G.node[i]['tag']=='tag':
113  if not ((G.edge[key][i]['tag']=='link') and (G.node[i]['tag']!='link')) :
114  pos[i]=[G.node[i]['depth'],y]
115  y+=1
116  y=traverse_successors_recursive(G,i,pos,y)
117  for i in G.successors(key):
118  if G.node[i]['tag']=='field':
119  if not ((G.edge[key][i]['tag']=='link') and (G.node[i]['tag']!='link')) :
120  pos[i]=[G.node[i]['depth'],y]
121  y+=1
122  y=traverse_successors_recursive(G,i,pos,y)
123  for i in G.successors(key):
124  if G.node[i]['tag']=='property':
125  if not ((G.edge[key][i]['tag']=='link') and (G.node[i]['tag']!='link')) :
126  pos[i]=[G.node[i]['depth'],y]
127  y+=1
128  y=traverse_successors_recursive(G,i,pos,y)
129  for i in G.successors(key):
130  if G.node[i]['tag']=='signal':
131  if not ((G.edge[key][i]['tag']=='link') and (G.node[i]['tag']!='link')) :
132  pos[i]=[G.node[i]['depth'],y]
133  y+=1
134  y=traverse_successors_recursive(G,i,pos,y)
135  for i in G.successors(key):
136  if G.node[i]['tag']=='component':
137  if not ((G.edge[key][i]['tag']=='link') and (G.node[i]['tag']!='link')) :
138  pos[i]=[G.node[i]['depth'],y]
139  y+=1
140  y=traverse_successors_recursive(G,i,pos,y)
141  return y
142 
144  pos=dict(zip(G,numpy.tile(-999,(G.number_of_nodes(),2))))
145  pos['c:'+key]=[G.node['c:'+key]['depth'],0]
146  y=traverse_successors_recursive(G,'c:'+key,pos,1)
147  for i in G.pred['c:'+key]:
148  pos[i]=[G.node[i]['depth'],G.node[i]['depth']]
149  ctr=0
150  for i in pos:
151  if pos[i][0]==-999:
152  print "traditional_left2right_tree_layout: unplugged key: ", i, G.node[i]
153  pos[i][1]=ctr
154  ctr+=1
155  return pos
156 
159  ymax=-1.
160  for i in pos: ymax=max(float(pos[i][1]),float(ymax))
161  for i in pos:
162  x=float(pos[i][0])
163  y=float(pos[i][1])
164  r=x
165  fi=2*math.pi*y/ymax
166  pos[i][0]=r*math.cos(fi)
167  pos[i][1]=r*math.sin(fi)
168  return pos
169 
170 #########################################################################################
171 # compute angle in degree for each node at which the edge from parent node arrives
172 #########################################################################################
174  angle=dict.fromkeys(pos,float(0.))
175  for i in G:
176  for j in G.successors(i):
177  if not ((G.node[j]['tag']!='link') and (G.edge[i][j]['tag']=='link')):
178  dx=float(pos[j][0]-pos[i][0])
179  dy=float(pos[j][1]-pos[i][1])
180  if not (dx==0. and dy==0.):
181  angle[j] = -180./math.pi*math.atan2(dy,dx)
182  return angle
183 
184 #########################################################################################
185 # renormalizing positions in the range of zoomfact & root position in zoomfact
186 # it gets normalized in a way that cf3_img's pixels are 1m away frm each other
187 # and size is 1/zoomfact compared t axes dimensions
188 # also computing angles, based on the angle of the edge leading to parent node
189 #########################################################################################
190 def normalize_coordinates(key_,pos_,img_):
191  zoomfact=40.
192  imx=float(img_.size[0])
193  imy=float(img_.size[1])
194  rootx,rooty=pos_['c:'+key_]
195  xmin=float(min([i[0] for i in pos_.values()]))
196  ymin=float(min([i[1] for i in pos_.values()]))
197  xmax=float(max([i[0] for i in pos_.values()]))
198  ymax=float(max([i[1] for i in pos_.values()]))
199  if xmin==xmax:
200  xmin-=0.5
201  xmax+=0.5
202  if ymin==ymax:
203  ymin-=0.5
204  ymax+=0.5
205  for i in pos_:
206  pos_[i]=[(pos_[i][0]-rootx)/(xmax-xmin)*zoomfact*imx+imx/2,
207  (pos_[i][1]-rooty)/(ymax-ymin)*zoomfact*imy+imy/2]
208  return pos_;
209 
210 #########################################################################################
211 # need to put things into a class to be reachable by the event callbacks
212 #########################################################################################
214 
215  # main members
216  #######################################################################################
217  name=None
218  G=None
219  pos=None
220  nodecaption=None
221  cn=None
222  ce=None
223  ccapt=None
224  on=None
225  oe=None
226  ocapt=None
227  pn=None
228  pe=None
229  pcapt=None
230  sn=None
231  se=None
232  scapt=None
233  fn=None
234  fe=None
235  fcapt=None
236  ln=None
237  le=None
238  lcapt=None
239  tn=None
240  te=None
241  tcapt=None
242  printdestination=None
243  hidden=None
244  navi=None
245 
246  # constructor
247  #######################################################################################
248  def __init__(self,name_):
249  self.name=name_ # name for identifying between main and navi
250  self.G=nx.DiGraph() # the graph itself
251  self.pos=dict() # positions of the nodes
252  #self.navi=nx_event_connector("navi") # secondary graph for navigating, only initialized on pick
253  self.nodecaption=dict() # node labels to show
254  self.cn=list() # list of nodes to display for components
255  self.ce=list() # list of edges to display for components
256  self.ccapt=dict( ) # text to display for nodes of components
257  self.on=list() # list of nodes to display for options
258  self.oe=list() # list of edges to display for options
259  self.ocapt=dict() # text to display for nodes of options
260  self.pn=list() # list of nodes to display for properties
261  self.pe=list() # list of edges to display for properties
262  self.pcapt=dict() # text to display for nodes of properties
263  self.sn=list() # list of nodes to display for signal
264  self.se=list() # list of edges to display for signal
265  self.scapt=dict() # text to display for nodes of signal
266  self.fn=list() # list of nodes to display for field
267  self.fe=list() # list of edges to display for field
268  self.fcapt=dict() # text to display for nodes of field
269  self.ln=list() # list of nodes to display for links
270  self.le=list() # list of edges to display for links
271  self.lcapt=dict() # text to display for nodes of links
272  self.tn=list() # list of nodes to display for tags
273  self.te=list() # list of edges to display for tags
274  self.tcapt=dict() # text to display for nodes of tags
275  self.printdestination='sc' # where to print component info: 's' screen and/or 'c' console terminal
276  self.hidden='cfospl' # mask for which nodes marked as hidden not to display
277 
278  # helper members
279  #######################################################################################
280  infotxt=plt.text(0.02,0.92,"",
281  transform=mainax.transAxes, family='monospace',size=10, weight='bold',
282  color=navicolor, ha='left', va='top',zorder=51)
283  seltxt=plt.text(0.,0.,"",
284  family='monospace',size=10, weight='bold',
285  color=navicolor, ha='left', va='center',zorder=51)
286 
287  # helper func for plotting the secondary navigator
288  #######################################################################################
290  plt.sca(naviax)
291  nxp=root.get_child('NetworkXPython')
292  naviax.clear()
293  self.navi=nx_event_connector("navi")
294  self.navi=build_graph_with_lists(cf.URI(key[2:]),self.navi,nxp,1,'cspoflt',depthlimit_sofplt=False,add_parent=True,hidden=self.hidden)
295  self.navi.pos=traditional_left2right_tree_layout_in_polar(self.navi.G,key[2:])
296  self.navi.pos=normalize_coordinates(key[2:],self.navi.pos,cf3_img)
297  self.navi.rot=compute_edge_angles_for_target_nodes(self.navi.G,self.navi.pos)
298  for i in self.navi.G:
299  if self.navi.G.node[i]['depth']==-1:
300  self.navi.pos[i]=(-1.3,1.3)
301  else:
302  if self.navi.G.node[i]['depth']==0:
303  self.navi.pos[i]=(0.,0.)
304  else:
305  coord=self.navi.pos[i]
306  magnitude=math.sqrt(coord[0]*coord[0]+coord[1]*coord[1])
307  if magnitude!=0:
308  coord[0]/=magnitude
309  coord[1]/=magnitude
310  self.navi.pos[i]=coord
311  draw_edges_nodes(self.navi.G,self.navi.pos,self.navi.se,'se',self.navi.sn,'sn','solid',signalcolor,10)
312  draw_edges_nodes(self.navi.G,self.navi.pos,self.navi.pe,'pe',self.navi.pn,'pn','solid',propertycolor,11)
313  draw_edges_nodes(self.navi.G,self.navi.pos,self.navi.fe,'fe',self.navi.fn,'fn','solid',fieldcolor,12)
314  draw_edges_nodes(self.navi.G,self.navi.pos,self.navi.te,'te',self.navi.tn,'tn','solid',tagcolor,13)
315  draw_edges_nodes(self.navi.G,self.navi.pos,self.navi.oe,'oe',self.navi.on,'on','solid',optioncolor,14)
316  draw_edges_nodes(self.navi.G,self.navi.pos,self.navi.le,'le',self.navi.ln,'ln','dashed',linkcolor,15)
317  draw_edges_nodes(self.navi.G,self.navi.pos,self.navi.ce,'ce',self.navi.cn,'cn','solid',componentcolor,16)
318  draw_captions(self.navi.G,self.navi.pos,self.navi.scapt,'sc',signalcolor,40,rotation=self.navi.rot,onlyalign=True)
319  draw_captions(self.navi.G,self.navi.pos,self.navi.pcapt,'pc',propertycolor,41,rotation=self.navi.rot,onlyalign=True)
320  draw_captions(self.navi.G,self.navi.pos,self.navi.fcapt,'fc',fieldcolor,42,rotation=self.navi.rot,onlyalign=True)
321  draw_captions(self.navi.G,self.navi.pos,self.navi.tcapt,'tc',tagcolor,43,rotation=self.navi.rot,onlyalign=True)
322  draw_captions(self.navi.G,self.navi.pos,self.navi.ocapt,'oc',optioncolor,44,rotation=self.navi.rot,onlyalign=True)
323  draw_captions(self.navi.G,self.navi.pos,self.navi.lcapt,'lc',linkcolor,45,rotation=self.navi.rot,onlyalign=True)
324  draw_captions(self.navi.G,self.navi.pos,self.navi.ccapt,'cc',componentcolor,46,rotation=self.navi.rot,onlyalign=True)
325  naviax.set_xbound((-3,3))
326  naviax.set_ybound((-1.2,1.5))
327  naviax.set_visible(True)
328  plt.sca(mainax)
329 
330  # event on picking a node
331  #######################################################################################
332  def on_pick(self, event):
333 
334  # get the key from the label of the artist node_info=(main|navi,label_passed_to_draw_functions)
335  exec event.artist.get_label() # this gives node_info
336  if node_info[0]=="main": # this gives the key was picked
337  exec "key_orig=self." + node_info[1] + "[" + str(event.ind[0]) + "]"
338  tG=self.G
339  else:
340  exec "key_orig=self.navi." + node_info[1] + "[" + str(event.ind[0]) + "]"
341  tG=self.navi.G
342  key=deepcopy(key_orig)
343 
344  # marionetting out the owner if its not a component, first trying main and then navi
345  if ((tG.node[key]['tag']=='tag') or (tG.node[key]['tag']=='signal') or (tG.node[key]['tag']=='option') or (tG.node[key]['tag']=='field') or (tG.node[key]['tag']=='property')):
346  key=tG.pred[key].keys()[0]
347  comp=root.access_component(key[2:])
348 
349  if node_info[0]=="navi":
350  key_orig=key
351 
352  # set string to display
353  self.seltxt.set_text("")
354  self.seltxt.set_position(self.pos[key_orig])
355  if (tG.node[key_orig]['tag']=='component'):
356  self.seltxt.set_text(key[2:])
357  if (tG.node[key_orig]['tag']=='option'):
358  self.seltxt.set_text("option of " + key[2:])
359  if (tG.node[key_orig]['tag']=='tag'):
360  self.seltxt.set_text("tag of " + key[2:])
361  if (tG.node[key_orig]['tag']=='property'):
362  self.seltxt.set_text("property of " + key[2:])
363  if (tG.node[key_orig]['tag']=='signal'):
364  self.seltxt.set_text("signal of " + key[2:])
365  if (tG.node[key_orig]['tag']=='field'):
366  self.seltxt.set_text("field of " + key[2:])
367  if (tG.node[key_orig]['tag']=='link'):
368  self.seltxt.set_text("link to " + key[2:])
369 
370  # and finally get and display detailed info of the actual component
371  nxp=root.get_child('NetworkXPython')
372  infostr=nxp.get_detailed_info(cf.URI(key[2:]))
373  self.infotxt.set_text("")
374  if 's' in self.printdestination: self.infotxt.set_text(infostr)
375  if 'c' in self.printdestination: print infostr
376  self.plot_secondary_navigation(key)
377 
378  plt.draw()
379 
380 #########################################################################################
381 # draw text
382 #########################################################################################
383 def draw_captions(G,pos,capt,label,color,zord,rotation=None,onlyalign=False):
384  curraxes=fig.gca()
385  for i in capt:
386  capt[i]= " " + capt[i] + " "
387  txt=nx.draw_networkx_labels(G,pos,labels=capt,font_color=color)
388  if txt is not None:
389  for i in txt:
390  if txt[i] is not None:
391  txt[i].set_family('sans-serif')
392  txt[i].set_size(11)
393  txt[i].set_weight('bold')
394  txt[i].set_zorder(zord)
395  txt[i].set_label( "caption_info=('" + curraxes.get_label() + "','" + label + "')" )
396  txt[i].set_rotation_mode('anchor')
397  if rotation is not None:
398  if (abs(rotation[i])<=90):
399  txt[i].set_verticalalignment('center')
400  txt[i].set_horizontalalignment('left')
401  if not onlyalign: txt[i].set_rotation(rotation[i])
402  else:
403  txt[i].set_verticalalignment('center')
404  txt[i].set_horizontalalignment('right')
405  if not onlyalign: txt[i].set_rotation(rotation[i]+180.)
406 
407 #########################################################################################
408 # draw edges and nodes
409 #########################################################################################
410 def draw_edges_nodes(G,pos,elist,elabel,nlist,nlabel,edgestyle,color,zord):
411  curraxes=fig.gca()
412  edge=nx.draw_networkx_edges(G,pos,edgelist=elist,edge_color=color,arrows=False)
413  node=nx.draw_networkx_nodes(G,pos,nodelist=nlist,node_color=color,node_shape='o',node_size=50)
414  if edge is not None:
415  edge.set_label("edge_info=('" + curraxes.get_label() + "','" + elabel + "')")
416  edge.set_zorder(zord)
417  edge.set_linewidths(1.5)
418  edge.set_linestyle(edgestyle)
419  if node is not None:
420  node.set_picker(5)
421  node.set_edgecolor(bgcolor)
422  node.set_label("node_info=('" + curraxes.get_label() + "','" + nlabel + "')")
423  node.set_zorder(zord+10)
424  node.set_linewidths(1.5)
425 
426 #########################################################################################
427 # query data from coolfluid and build graph and lists
428 #########################################################################################
429 def append_with_successors_recursive(G,key,to_append) :
430  to_append[key]=1
431  for i in G.successors(key):
432  append_with_successors_recursive(G,i,to_append)
433 
434 def build_graph_with_lists(starturi_,nec_,nxp_,depth_,tree_,depthlimit_sofplt=True,add_parent=False,hidden='cofpslt'):
435 
436  # getting the strings which holds the script to setup the graph
437  components=nxp_.get_component_graph( uri = starturi_, depth = depth_ )
438  if depthlimit_sofplt==True:
439  options=nxp_.get_option_graph( uri = starturi_, depth = depth_ )
440  tags=nxp_.get_tag_graph( uri = starturi_, depth = depth_ )
441  signals=nxp_.get_signal_graph( uri = starturi_, depth = depth_ )
442  fields=nxp_.get_field_graph( uri = starturi_, depth = depth_ )
443  links=nxp_.get_link_graph( uri = starturi_, depth = depth_ )
444  properties=nxp_.get_property_graph( uri = starturi_, depth = depth_ )
445  else:
446  options=nxp_.get_option_graph( uri = starturi_, depth = depth_-1 )
447  tags=nxp_.get_tag_graph( uri = starturi_, depth = depth_-1 )
448  signals=nxp_.get_signal_graph( uri = starturi_, depth = depth_-1 )
449  fields=nxp_.get_field_graph( uri = starturi_, depth = depth_-1 )
450  links=nxp_.get_link_graph( uri = starturi_, depth = depth_-1 )
451  properties=nxp_.get_property_graph( uri = starturi_, depth = depth_-1 )
452 
453  #print components
454  #print options
455  #print tags
456  #print signals
457  #print fields
458  #print links
459  #print properties
460 
461  # executing the submission into the graph
462  if 'c' in tree_:
463  for line in StringIO(components): exec 'nec_.' + line
464  if 'o' in tree_:
465  for line in StringIO(options ): exec 'nec_.' + line
466  if 'p' in tree_:
467  for line in StringIO(properties): exec 'nec_.' + line
468  if 's' in tree_:
469  for line in StringIO(signals ): exec 'nec_.' + line
470  if 'f' in tree_:
471  for line in StringIO(fields ): exec 'nec_.' + line
472  if 'l' in tree_:
473  for line in StringIO(links ): exec 'nec_.' + line
474  if 't' in tree_:
475  for line in StringIO(tags ): exec 'nec_.' + line
476 
477  # if there is a parent node and add_parent is true, the make it mimic a regular component
478  if add_parent==True:
479  parn=[(u) for (u,d) in nec_.G.nodes(data=True) if d['tag']=='parent']
480  for i in parn:
481  nec_.G.node[i]['tag']='component'
482  pare=[(u,v) for (u,v,d) in nec_.G.edges(data=True) if d['tag']=='parent']
483  for i in pare:
484  nec_.G.edge[i[0]][i[1]]['tag']='component'
485 
486  # getting out hidden from the graph if required, using dict becuase some elements could end up in a list multiple times
487  dellist=dict()
488  for i in nec_.G:
489  if nec_.G.node[i]['hidden']==True:
490  if nec_.G.node[i]['tag'][0] in hidden:
491  append_with_successors_recursive(nec_.G,i,dellist)
492  nec_.G.remove_nodes_from(dellist.keys())
493  for i in dellist.keys():
494  nec_.nodecaption.pop(i)
495 
496  # separating lists
497  nec_.cn=[(u) for (u,d) in nec_.G.nodes(data=True) if d['tag']=='component']
498  nec_.ce=[(u,v) for (u,v,d) in nec_.G.edges(data=True) if d['tag']=='component']
499  nec_.ccapt=dict.fromkeys(nec_.nodecaption,'')
500  for key in nec_.cn : nec_.ccapt[key]=nec_.nodecaption[key]
501  nec_.on=[(u) for (u,d) in nec_.G.nodes(data=True) if d['tag']=='option']
502  nec_.oe=[(u,v) for (u,v,d) in nec_.G.edges(data=True) if d['tag']=='option']
503  nec_.ocapt=dict.fromkeys(nec_.nodecaption,'')
504  for key in nec_.on : nec_.ocapt[key]=nec_.nodecaption[key]
505  nec_.pn=[(u) for (u,d) in nec_.G.nodes(data=True) if d['tag']=='property']
506  nec_.pe=[(u,v) for (u,v,d) in nec_.G.edges(data=True) if d['tag']=='property']
507  nec_.pcapt=dict.fromkeys(nec_.nodecaption,'')
508  for key in nec_.pn : nec_.pcapt[key]=nec_.nodecaption[key]
509  nec_.sn=[(u) for (u,d) in nec_.G.nodes(data=True) if d['tag']=='signal']
510  nec_.se=[(u,v) for (u,v,d) in nec_.G.edges(data=True) if d['tag']=='signal']
511  nec_.scapt=dict.fromkeys(nec_.nodecaption,'')
512  for key in nec_.sn : nec_.scapt[key]=nec_.nodecaption[key]
513  nec_.fn=[(u) for (u,d) in nec_.G.nodes(data=True) if d['tag']=='field']
514  nec_.fe=[(u,v) for (u,v,d) in nec_.G.edges(data=True) if d['tag']=='field']
515  nec_.fcapt=dict.fromkeys(nec_.nodecaption,'')
516  for key in nec_.fn : nec_.fcapt[key]=nec_.nodecaption[key]
517  nec_.ln=[(u) for (u,d) in nec_.G.nodes(data=True) if d['tag']=='link']
518  nec_.le=[(u,v) for (u,v,d) in nec_.G.edges(data=True) if d['tag']=='link']
519  nec_.lcapt=dict.fromkeys(nec_.nodecaption,'')
520  for key in nec_.ln : nec_.lcapt[key]=nec_.nodecaption[key]
521  nec_.tn=[(u) for (u,d) in nec_.G.nodes(data=True) if d['tag']=='tag']
522  nec_.te=[(u,v) for (u,v,d) in nec_.G.edges(data=True) if d['tag']=='tag']
523  nec_.tcapt=dict.fromkeys(nec_.nodecaption,'')
524  for key in nec_.tn : nec_.tcapt[key]=nec_.nodecaption[key]
525 
526  return nec_
527 
528 
529 #########################################################################################
530 # starturi: from where the recursive listing starts
531 # depth: how many levels to list down deep in starturi's subtree
532 # tree: what to plot in the tree. Combination of chars 'cosfl'
533 # caption: what to label in the tree. Combination of chars 'cosfl'
534 # 'c': component
535 # 'o': option
536 # 't': tag
537 # 'p': property
538 # 's': signal
539 # 'f': field
540 # 'l': link
541 # printdestination: 'sc' if user clicks on a node, the component information is printed
542 # 's': to screen (matplotlib window)
543 # 'c': console (terminal)
544 # depthlimit_sofpl: bool option to include or exclude printing signals, options, fields,
545 # properties and links at depthlimit level
546 # hidden: wether to display or not cospfl element which has tag 'hidden' set to true
547 #
548 # zorder numbers:
549 # 1x: edges
550 # 2x: nodes, hardcoded to edges +10
551 # 3x: captions
552 # 40: cf logo middle backdrop rectangle
553 # 41: cf logo image
554 # 50: title
555 # 51: component info
556 #########################################################################################
557 def show_graph(starturi,depth=1000,tree='cofl',caption='',printdestination='c',hidden='cospflt'):
558 
559  # create the collector component on coolfluid side
560  nxp = root.create_component('NetworkXPython','cf3.python.NetworkXPython')
561 
562  # create and configure handler class in python side
563  nec=nx_event_connector("main")
564  nec.printdestination=printdestination
565  nec.hidden=hidden
566  cid=fig.canvas.mpl_connect('pick_event', nec.on_pick)
567 
568  # get a string with a nice name of the component and show it in title
569  start_key=root.access_component(str(starturi)).uri().path()
570  titletxt.set_text("COOLFluiD3 component graph starting from '" + start_key + "'")
571  fig.canvas.set_window_title(start_key)
572 
573  # build the graph
574  nec=build_graph_with_lists(starturi,nec,nxp,depth,tree,hidden=hidden)
575 
576  # computing the positions of the nodes via layouts
577  #nec.pos=nx.graphviz_layout(nec.G,prog='twopi')
578  #nec.pos=nx.graphviz_layout(nec.G,prog='circo',root=start_key)
579  #nec.pos=nx.spring_layout(nec.G,iterations=50)
580  #nec.pos=traditional_left2right_tree_layout(nec.G,start_key)
581  nec.pos=traditional_left2right_tree_layout_in_polar(nec.G,start_key)
582  #pos2=traditional_left2right_tree_layout_in_polar(nec.G,start_key)
583  #nec.pos=nx.spring_layout(nec.G,pos=pos2,iterations=50)
584 
585  # renormalizing positions in the range of zoomfact & root position in zoomfact
586  # also computing angles, just in case
587  nec.pos=normalize_coordinates(start_key,nec.pos,cf3_img)
588  rot=compute_edge_angles_for_target_nodes(nec.G,nec.pos)
589 
590  # print statistics
591  print "Statistics for: ", start_key
592  print "Number of nodes & edges"
593  print "--------------------------------"
594  print "Components: %10d%10d" % ( len(nec.cn), len(nec.ce) )
595  print "Options: %10d%10d" % ( len(nec.on), len(nec.oe) )
596  print "Tags: %10d%10d" % ( len(nec.tn), len(nec.te) )
597  print "Properties: %10d%10d" % ( len(nec.pn), len(nec.pe) )
598  print "Signals: %10d%10d" % ( len(nec.sn), len(nec.se) )
599  print "Fields: %10d%10d" % ( len(nec.fn), len(nec.fe) )
600  print "Links: %10d%10d" % ( len(nec.ln), len(nec.le) )
601  print "TOTAL: %10d%10d" % ( len(nec.G.nodes()), len(nec.G.edges()) )
602 
603  # draw the nodes and edges
604  if 's' in tree: draw_edges_nodes(nec.G,nec.pos,nec.se,'se',nec.sn,'sn','solid',signalcolor,10)
605  if 'p' in tree: draw_edges_nodes(nec.G,nec.pos,nec.pe,'pe',nec.pn,'pn','solid',propertycolor,11)
606  if 'f' in tree: draw_edges_nodes(nec.G,nec.pos,nec.fe,'fe',nec.fn,'fn','solid',fieldcolor,12)
607  if 't' in tree: draw_edges_nodes(nec.G,nec.pos,nec.te,'te',nec.tn,'tn','solid',tagcolor,13)
608  if 'o' in tree: draw_edges_nodes(nec.G,nec.pos,nec.oe,'oe',nec.on,'on','solid',optioncolor,14)
609  if 'l' in tree: draw_edges_nodes(nec.G,nec.pos,nec.le,'le',nec.ln,'ln','dashed',linkcolor,15)
610  if 'c' in tree: draw_edges_nodes(nec.G,nec.pos,nec.ce,'ce',nec.cn,'cn','solid',componentcolor,16)
611 
612  # draw the
613  if 's' in caption: draw_captions(nec.G,nec.pos,nec.scapt,'sc',signalcolor,40,rotation=rot)
614  if 'p' in caption: draw_captions(nec.G,nec.pos,nec.pcapt,'pc',propertycolor,41,rotation=rot)
615  if 'f' in caption: draw_captions(nec.G,nec.pos,nec.fcapt,'fc',fieldcolor,42,rotation=rot)
616  if 't' in caption: draw_captions(nec.G,nec.pos,nec.tcapt,'tc',tagcolor,43,rotation=rot)
617  if 'o' in caption: draw_captions(nec.G,nec.pos,nec.ocapt,'oc',optioncolor,44,rotation=rot)
618  if 'l' in caption: draw_captions(nec.G,nec.pos,nec.lcapt,'lc',linkcolor,45,rotation=rot)
619  if 'c' in caption: draw_captions(nec.G,nec.pos,nec.ccapt,'cc',componentcolor,46,rotation=rot)
620 
621  # showing the plot
622  print "---------- SHOW ----------"
623  plt.show()
624 
625  # delete the collector component
626 
need to put things into a class to be reachable by the event callbacks
def show_graph
starturi: from where the recursive listing starts depth: how many levels to list down deep in startur...
def traditional_left2right_tree_layout_in_polar(G, key)
common::URI uri(ComponentWrapper &self)
Real max(const Real a, const Real b)
Maximum between two scalars.
Definition: Terminals.hpp:228
def append_with_successors_recursive(G, key, to_append)
query data from coolfluid and build graph and lists
def traverse_successors_recursive(G, key, pos, y)
custom-made layouts traditional_left2right_tree_layout(G,key,pos) traditional_left2right_tree_layout_...
def draw_edges_nodes(G, pos, elist, elabel, nlist, nlabel, edgestyle, color, zord)
draw edges and nodes
def normalize_coordinates(key_, pos_, img_)
renormalizing positions in the range of zoomfact & root position in zoomfact it gets normalized in a way ...
Real min(const Real a, const Real b)
Minimum between two scalars.
Definition: Terminals.hpp:234
def compute_edge_angles_for_target_nodes(G, pos)
compute angle in degree for each node at which the edge from parent node arrives
def traditional_left2right_tree_layout(G, key)
Send comments to:
COOLFluiD Web Admin