ATLAS Offline Software
navigation2dot.py
Go to the documentation of this file.
1 #! /usr/bin/python
2 # Q? Send mail to Tomasz dot Bold at cern dot ch
3 
4 import string
5 from string import rstrip,atoi,replace
6 import sys
7 import commands
8 import os
9 import re
10 
11 teIdtoName = {'0':'0'}
12 featureCLIDtoName = {}
13 
14 
15 
16 
17 
18 if 'CMTROOT' not in os.environ.keys():
19  print 'Can not find out graphviz binaries: ',GraphivizBinPath
20  print 'Have you setup CMT environmet? CMTROOT not set'
21  raise SystemExit
22 
23 else:
24  # setup lib
25  GraphivizPath = os.environ['CMTROOT']+'/../Grafviz/2.2'
26  GraphivizBinPath = GraphivizPath+'/bin/'
27  GraphivizLibPath = GraphivizPath+'/lib/graphviz'
28 
29  if 'LD_LIBRARY_PATH' not in os.environ.keys():
30  os.environ['LD_LIBRARY_PATH'] = ''
31  os.environ['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']+':'+GraphivizLibPath
32 
33  print "Graphviz programs from there: ", GraphivizBinPath
34 
35 
36 # global options driving grph drawing (switched by command line parser)
37 options = {'drawFeatures': False,
38  'clid': True,
39  'convert': False,
40  'program': 'dot',
41  'event': None,
42  'raw': False,
43  'regex': re.compile('.*')}
44 
45 
46 def featureClassName(clid):
47  """ converts the CLID to ClassName in C++. If falied then CLID instead.
48  The CLIDS to name is taken from CLID Svc dump."""
49  if clid in featureCLIDtoName.keys():
50  return featureCLIDtoName[clid]
51  else:
52  if options['clid'] is False:
53  return str(clid)
54  else: # use CLID DB clid command to get it)
55  name = commands.getoutput( 'clid '+clid).split(' ')[1]
56  featureCLIDtoName[clid] = name
57  return name
58 
59 def teName(teid):
60  if teid in teIdtoName.keys():
61  return teIdtoName[teid]
62  else:
63  print "TE id: ", teid, " unknown"
64  return teid
65 
66 class TE:
67  def __init__(self, s):
68  # print s
69  # this si typical line it has to deal with: id:0;active:1;error:0;ptr:0x9606b98;#seeds:4,0x9606ce0 0x9607338 0x96075b0 0x96077e8 #seededBy:0;#RoI:0;#features:1 CLID:242645981 idx:0:0:1 label:"OPI_L2";
70  tok = s.split(';')
71  #print tok
72  self.tename = teName(tok[0].split(':')[1])
73  self.active = bool(int(tok[1].split(':')[1]))
74  self.error = bool(int(tok[2].split(':')[1]))
75  self.ptr = tok[3].split(':')[1]
76  self.roi = tok[5].split(':')[1]
77  # find out relations
78  self.relations = []
79  self.terminal = False
80  seeds = tok[4].split(',')[0].split(':')[1]
81  if seeds is '0':
82  self.terminal = True
83  else:
84  self.relations = tok[4].split(',')[1].split(' ')[0:-1]
85 
86  # find out features attached
87  #print tok
88  self.features = []
89  global options
90  passed=False
91  if options['drawFeatures']:
92  for part in tok:
93  if 'keyprints' in part:
94  passed=True
95  clid = 0
96  label = ''
97  idx=''
98  for field in part.split(" "):
99  if field.find("CLID") is not -1:
100  clid = field.split(":")[1].lstrip(' ').lstrip(' ')
101  elif field.find("label") is not -1:
102  label = field.split(":")[1].rstrip("\"").lstrip("\"")
103  elif field.find("idx") is not -1:
104  idx=field
105  if clid is not 0:
106  #print (featureClassName(clid), label, idx, passed)
107  self.features.append( (featureClassName(clid), label, idx, ('','*')[passed]) )
108 
109  # print self.features
110 
111  # print self.tename, self.active, self.ptr, self.relations
112 
113  def node(self):
114  """ Draws node of the graph. """
115  global options
116 
117  if options['regex'].search(self.tename) == None and self.tename != '0':
118  # print "rejecting TE which of name ", self.tename, ' due to regex'
119  return None
120 
121  nodename = 'X'+ str(self.ptr)
122  line = nodename +' [ label="{TE: ' + self.tename
123 
124  line += reduce(lambda x,y: x + "|"+y[0]+ "(" +y[1] + ' '+ y[2]+str(y[3])+")", self.features, "")
125  line += '}", style=filled, '
126 
127  # special nodes
128  if self.tename is '0':
129  line += 'fillcolor=pink, '
130  else:
131  if self.active:
132  line += 'color=green, '
133  else:
134  line += 'color=plum, '
135 
136  # error color scheme
137  if self.error:
138  line += 'fillcolor=red, '
139  else:
140  line += 'fillcolor=palegreen, '
141 
142 
143 
144 
145  line += 'shape=record'
146  line += ']\n'
147  return line
148 
149  def edges (self):
150  """ Draws node and edges. """
151  line = ''
152  for rel in self.relations:
153  line += 'X'+self.ptr + ' -> X' + rel + '\n'
154  return line
155 
156  def __str__(self):
157  r = self.node()
158  if r:
159  return r + self.edges()
160  else:
161  return ""
162 
163 
164 def nav2dot(nav, eventId, level):
165  """ converts"""
166  global options
167  inputTEs = nav.split('\n')
168  stringTEs = []
169  for te in inputTEs:
170  if te is not '':
171  stringTEs.append(te.lstrip(' |\_'))
172 
173  # unique
174  uniqueTEs = []
175  for ste in stringTEs:
176  if ste not in uniqueTEs:
177  uniqueTEs.append(ste)
178  # print "LEN :" + str(len(stringTEs)) + "-->" + str(len(uniqueTEs))
179 
180  objectTEs = map( lambda x: TE(x), uniqueTEs)
181  dot = 'digraph Menu {\n'\
182  +'\n'\
183  +'graph [ rankdir = "TR"];'\
184  +'node [ shape=polygon, fontname=Helvetica ]\n'\
185  +'edge [ fontname=Helvetica ]\n'
186  dot += reduce(lambda x,y: x+str(y), objectTEs, '')
187  dot += '\n}'
188 
189  fname = 'navigationEvent-'+level+'-'+str(eventId)
190  if options['event'] is None or str(options['event']) == str(eventId):
191  print 'writing file: '+fname+'.dot'
192  f = file('temp.dot','w')
193  f.write(dot)
194  f.close()
195  #print commands.getoutput(GraphivizBinPath+'unflatten -l4 -f -c2 -o '+ fname+ '.dot temp.dot')
196  print commands.getoutput('mv -f temp.dot '+fname+'.dot')
197  print commands.getoutput('/bin/rm -f temp.dot')
198  if options['convert']:
199  print 'converting file: '+fname+'.dot to graphics'
200  global GraphivizBinPath
201  print commands.getoutput(GraphivizBinPath+options['program']+' ' + fname +'.dot -Tpng -o '+fname+'.png')
202  # delete dot file
203  print commands.getoutput('rm -f '+fname+'.dot')
204 # nav2dot(navex)
205 
206 def parseLog(file):
207  eventNumber = -1
208  navigationStarted=False
209  nav = ""
210  step = 0
211  stepToLevel = ["L2", "EFunpacking", "EF"]
212 
213  for line in file:
214  if line.find("- --") is not -1:
215  # print line
216  if line.find("inputTEs") is not -1: # we spoted input TE in sequence printout
217  try:
218  teId = line.split(" ")[5]
219  teId = string.strip(teId, "(), \"\n")
220  teId = rstrip(teId, ",")
221  teName = line.split(" ")[4]
222  teName = string.strip(teName, "(), \"\n")
223  teIdtoName[teId] = teName
224  except:
225  pass
226  if line.find(" outputTE : (") is not -1:
227  teId = line.split(" ")[7]
228  teId = string.strip(teId, "() \n")
229  teName = line.split(" ")[6]
230  teName = string.strip(teName, "()\",\n")
231  teIdtoName[teId] = teName
232 
233  # catch the navigation printout
234  if line.find("start processing event #") is not -1:
235  eventId = line.split("#")[1].split(",")[0]
236  step=0
237  print "scanning event: ",eventId
238 
239 
240  if line.find("Start of HLT Processing in L2") is not -1:
241  step = 0
242 
243  if line.find("Start of HLT Processing in EF") is not -1:
244  step = 1
245 
246  if line.find("TrigSteer_EF.ResultBuilder") is not -1:
247  step = 2
248 
249  # catch navigation block
250  if line.find("\\_") is not -1:
251  if navigationStarted is False:
252  navigationStarted=True
253  nav += line
254  else:
255  if navigationStarted is True:
256  navigationStarted=False
257  nav2dot(nav, eventId, stepToLevel[step] )
258 
259  nav = ""
260 
261 
263 
264  if options['clid'] is False:
265  clids = file("CLIDDBout.txt")
266  for line in clids:
267  clid = line.split(" ")[0]
268  name = line.split(" ")[1].rstrip("\n")
269  featureCLIDtoName[clid] = name
270  # print featureCLIDtoName
271 
272 
273 
274 def parseOpt():
275  global options
276  stat = True
277 
278  if '-f' in sys.argv:
279  options['drawFeatures'] = True
280  print "OPTION: will draw features"
281 
282  if '-d' in sys.argv:
283  options['clid'] = True
284  print "OPTION: will use clid command to get class names (slower)"
285  if '-x' in sys.argv:
286  options['regex'] = re.compile(sys.argv[sys.argv.index('-x')+1])
287  print "OPTION: will use only TEs accepted by regex", sys.argv[sys.argv.index('-x')+1]
288  if '-e' in sys.argv:
289  import string
290  options['event'] = string.atoi(sys.argv[sys.argv.index('-e')+1])
291  print "OPTION: will only draw event: ", options["event"]
292 
293  if '-c' in sys.argv:
294  options['convert'] = True;
295  print "OPTION: will convert to graphics on the fly"
296 
297  if '-p' in sys.argv:
298  options['program'] = sys.argv[sys.argv.index('-p')+1]
299  print "OPTION: will convert to graphics on the fly using ", options['program']
300 
301  if '-r' in sys.argv:
302  options['raw'] = True
303  options['configdump'] = sys.argv[sys.argv.index('-r')+2]
304  options['navigationdump'] = sys.argv[sys.argv.index('-r')+1]
305 
306 
307  if '-h' in sys.argv:
308  print "OPTION: Help needed? Here it is:"
309  print """
310  Files generated by this utility can be viewed by programs like 'dotty'.
311  Thay can be converted to graphics using probram 'dot':
312  dot nav_event_123.dot -o nav123.png -Tpng
313 
314  -h -- this help
315  -f -- draw freatures atteched to TE (with lables)
316  -d -- use clid command instead of CLIDDBout.txt to get human class names rather than CLIDs
317  -e X -- writeout only event (X)
318  -x regex -- use the regex to select only wanted TEs
319  -c -- convert graphs to png on the fly using dot program
320  -p prog -- use other program(neato, twopi, circo, fdp)
321  -r navigationfile configfile -- take files with the navigation dump and the configuration dump (rather than plain log)
322  """
323  stat = False
324  return stat
325 # main script
326 
327 if parseOpt():
328  if not options['raw']:
329  logname = sys.argv[-1]
330  log = file(logname)
331  parseCLIDs()
332  parseLog(log)
333  else:
334  conflog = file(options['configdump'])
335  parseLog(conflog)
336  navlog = file(options['navigationdump'])
337  parseLog(navlog)
338 
339  #print teIdtoName
navigation2dot.TE.__str__
def __str__(self)
Definition: navigation2dot.py:156
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
navigation2dot.TE.terminal
terminal
Definition: navigation2dot.py:79
navigation2dot.TE
Definition: navigation2dot.py:66
navigation2dot.TE.__init__
def __init__(self, s)
Definition: navigation2dot.py:67
navigation2dot.parseOpt
def parseOpt()
Definition: navigation2dot.py:274
navigation2dot.teName
def teName(teid)
Definition: navigation2dot.py:59
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
navigation2dot.TE.ptr
ptr
Definition: navigation2dot.py:75
search
void search(TDirectory *td, const std::string &s, std::string cwd, node *n)
recursive directory search for TH1 and TH2 and TProfiles
Definition: hcg.cxx:738
reduce
void reduce(HepMC::GenEvent *ge, std::vector< HepMC::GenParticlePtr > toremove)
Remove unwanted particles from the event, collapsing the graph structure consistently.
Definition: FixHepMC.cxx:82
navigation2dot.parseCLIDs
def parseCLIDs()
Definition: navigation2dot.py:262
navigation2dot.TE.roi
roi
Definition: navigation2dot.py:76
file
TFile * file
Definition: tile_monitor.h:29
navigation2dot.TE.node
def node(self)
Definition: navigation2dot.py:113
navigation2dot.TE.relations
relations
Definition: navigation2dot.py:78
navigation2dot.TE.tename
tename
Definition: navigation2dot.py:72
navigation2dot.TE.active
active
Definition: navigation2dot.py:73
navigation2dot.parseLog
def parseLog(file)
Definition: navigation2dot.py:206
navigation2dot.featureClassName
def featureClassName(clid)
Definition: navigation2dot.py:46
navigation2dot.nav2dot
def nav2dot(nav, eventId, level)
Definition: navigation2dot.py:164
navigation2dot.TE.edges
def edges(self)
Definition: navigation2dot.py:149
navigation2dot.TE.error
error
Definition: navigation2dot.py:74
str
Definition: BTagTrackIpAccessor.cxx:11
xAOD::bool
setBGCode setTAP setLVL2ErrorBits bool
Definition: TrigDecision_v1.cxx:60
navigation2dot.TE.features
features
Definition: navigation2dot.py:88
Trk::split
@ split
Definition: LayerMaterialProperties.h:38