Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v31r0 (aeb156f0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
hivetimeline.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 """Plot timeline from TimelineSvc"""
3 
4 __author__ = "Frank Winklmeier"
5 
6 import sys
7 import re
8 import argparse
9 import operator
10 from collections import defaultdict
11 
12 algcolors = []
13 evtcolors = []
14 
15 # Attributes will be added in read()
16 
17 
18 class Data:
19  pass
20 
21 
22 def read(f, regex='.*', skipevents=0):
23  data = []
24  regex = re.compile(regex)
25  for l in open(f, 'r'):
26  if l.startswith('#'): # e.g. #start end algorithm thread slot event
27  names = l.lstrip('#').split()
28  continue
29  d = Data()
30  for i, f in enumerate(l.split()):
31  setattr(d, names[i], int(f) if f.isdigit() else f)
32  if d.event >= skipevents:
33  data.append(d)
34  return data
35 
36 
37 def findEvents(data):
38  """Find event start/stop times"""
39 
40  t = defaultdict(lambda: [sys.maxint, 0, -1]) # start,stop,slot
41  nbslots = 0
42  for d in data:
43  if d.start < t[d.event][0]:
44  t[d.event][0] = d.start
45  t[d.event][2] = d.slot
46  if d.end > t[d.event][1]:
47  t[d.event][1] = d.end
48  if d.slot > nbslots:
49  nbslots = d.slot
50 
51  return t, nbslots
52 
53 
54 def setPalette(nevts, nevtcolors):
55  global algcolors, evtcolors
56 
57  from ROOT import TColor
58  algcolors = range(2, 10) + [20, 28, 29, 30, 33, 38, 40] + range(41, 50)
59  evtcolors = [
60  TColor.GetColor(0, 255 - g, g)
61  for g in range(20, 255, (255 - 20) / nevtcolors)
62  ]
63 
64 
65 def plot(data,
66  showThreads=True,
67  batch=False,
68  nevtcolors=10,
69  width=1200,
70  height=500):
71  import ROOT
72 
73  tmin = min(f.start for f in data)
74  tmax = max(f.end for f in data)
75  slots = 1 + max(f.slot for f in data)
76  threads = sorted(list(set(f.thread for f in data)))
77  threadid = dict((k, v) for v, k in enumerate(threads)) # map thread : id
78  ymax = len(threads) if showThreads else slots
79 
80  c = ROOT.TCanvas('timeline', 'Timeline', width, height)
81  c.SetLeftMargin(0.05)
82  c.SetRightMargin(0.2)
83  c.SetTopMargin(0.1)
84  c.SetBottomMargin(0.1)
85  c.coord = ROOT.TH2I('coord', ';Time (ns)', 100, 0, tmax - tmin, ymax, 0,
86  ymax)
87  c.coord.GetYaxis().SetTitle(('Thread' if showThreads else 'Slot'))
88  c.coord.GetYaxis().SetTitleOffset(0.5)
89  c.coord.GetYaxis().CenterTitle()
90  c.coord.SetStats(False)
91  c.coord.GetYaxis().SetNdivisions(ymax)
92  c.coord.GetXaxis().CenterTitle()
93 
94  c.Draw()
95  c.coord.Draw()
96 
97  c.lines = []
98  colors = {}
99  setPalette(ymax, nevtcolors)
100  mycolors = algcolors
101  for d in data:
102  y = (threadid[d.thread] if showThreads else d.slot)
103  alg = d.algorithm
104  if alg not in colors and len(mycolors) > 0:
105  colors[alg] = mycolors.pop(0)
106  if len(mycolors) == 0:
107  print "Too many algorithm to show"
108 
109  if alg in colors:
110  t0 = d.start - tmin
111  t1 = d.end - tmin
112 
113  # Alg
114  l = ROOT.TBox(t0, y + .1, t1, y + .8)
115  l.SetFillColor(colors[alg])
116 
117  # Event
118  l2 = ROOT.TBox(t0, y + .8, t1, y + .9)
119  l2.SetFillColor(evtcolors[d.event % nevtcolors])
120  c.lines += [l, l2]
121 
122  l2.Draw()
123  l.Draw()
124 
125  # Global event timeline
126  tevt, nbslots = findEvents(data)
127  bheight = 0.1
128  for k, v in tevt.iteritems():
129  y = ymax + bheight * v[2]
130  l = ROOT.TBox(v[0] - tmin, y + 0.2 * bheight, v[1] - tmin, y + bheight)
131  l.SetFillColor(evtcolors[k % nevtcolors])
132  c.lines += [l]
133  l.Draw()
134 
135  # Alg legend
136  c.leg = ROOT.TLegend(0.8, 0.4, 0.98, 0.9)
137  for alg, cl in sorted(colors.iteritems(), key=operator.itemgetter(1)):
138  e = c.leg.AddEntry('', alg, 'F')
139  e.SetLineColor(cl)
140  e.SetFillColor(cl)
141  e.SetFillStyle(1001)
142 
143  # Event legend
144  bwidth = 0.18 / nevtcolors
145  for cl in range(nevtcolors):
146  l = ROOT.TLine()
147  c.lines.append(l)
148  l.SetLineWidth(10)
149  l.SetLineColor(evtcolors[cl])
150  l.DrawLineNDC(0.807 + bwidth * cl, 0.37, 0.807 + bwidth * (cl + 1),
151  0.37)
152 
153  c.t1 = ROOT.TText(0.807, 0.314, 'Events')
154  c.t1.SetNDC()
155  c.t1.SetTextFont(42)
156  c.t1.SetTextSize(0.04)
157  c.t1.Draw()
158 
159  c.t2 = ROOT.TText(0.02, 0.92, 'Event')
160  c.t2.SetNDC()
161  c.t2.SetTextFont(42)
162  c.t2.SetTextSize(0.03)
163  c.t2.SetTextAngle(90)
164  c.t2.Draw()
165  c.t3 = ROOT.TText(0.03, 0.922, 'Slots')
166  c.t3.SetNDC()
167  c.t3.SetTextFont(42)
168  c.t3.SetTextSize(0.03)
169  c.t3.SetTextAngle(90)
170  c.t3.Draw()
171 
172  c.leg.Draw()
173  c.Update()
174  if not batch:
175  raw_input()
176  return c
177 
178 
179 def main():
180  parser = argparse.ArgumentParser(description=__doc__)
181 
182  parser.add_argument('timeline', nargs=1, help='timeline file')
183 
184  parser.add_argument(
185  '-s',
186  '--select',
187  default='.*',
188  help='Regular expression to filter algorithms')
189 
190  parser.add_argument(
191  '-b',
192  '--batch',
193  action='store_true',
194  default=False,
195  help='Do not wait for user input')
196 
197  parser.add_argument(
198  '--slots',
199  action='store_true',
200  default=False,
201  help='Show slots instead of threads (leads to overlaps!)')
202 
203  parser.add_argument(
204  '-p',
205  '--print',
206  dest='outfile',
207  nargs='?',
208  const='timeline.png',
209  help='Save to FILE [%(const)s]')
210 
211  parser.add_argument(
212  '-n',
213  '--nevtcolors',
214  default=10,
215  type=int,
216  help='Number of colors used for events (10 is default)')
217 
218  parser.add_argument(
219  '-e',
220  '--skipevents',
221  default=0,
222  type=int,
223  help='Number of events to skip at the start')
224 
225  parser.add_argument(
226  '-x',
227  '--width',
228  default=1200,
229  type=int,
230  help='width of the output picture')
231 
232  parser.add_argument(
233  '-y',
234  '--height',
235  default=500,
236  type=int,
237  help='height of the output picture')
238 
239  args = parser.parse_args()
240 
241  data = read(args.timeline[0], args.select, args.skipevents)
242  c = plot(data, not args.slots, args.batch, args.nevtcolors, args.width,
243  args.height)
244  if args.outfile:
245  c.SaveAs(args.outfile)
246 
247  return 0
248 
249 
250 if __name__ == '__main__':
251  sys.exit(main())
EventIDBase min(const EventIDBase &lhs, const EventIDBase &rhs)
Definition: EventIDBase.h:202
def read(f, regex='.*', skipevents=0)
Definition: hivetimeline.py:22
EventIDBase max(const EventIDBase &lhs, const EventIDBase &rhs)
Definition: EventIDBase.h:215
def plot(data, showThreads=True, batch=False, nevtcolors=10, width=1200, height=500)
Definition: hivetimeline.py:70
decltype(auto) range(Args &&...args)
Zips multiple containers together to form a single range.
def setPalette(nevts, nevtcolors)
Definition: hivetimeline.py:54
def findEvents(data)
Definition: hivetimeline.py:37