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