Skip to content
Snippets Groups Projects
Commit 102daf40 authored by Benedikt Hegner's avatar Benedikt Hegner
Browse files

Improvements on Hivetimeline script

In particular : 
  - proper display of slots for the events bars at the top
  - scalable display, with command line options to change size
  - option to skip first events (useful for first one where cache are not warm)
  - worked around ROOT bug of TLines not working properly
  - allow to change on command line number of colors for the events

See merge request !243
parents 291ba412 1a252a89
No related branches found
No related tags found
1 merge request!243Improvements on Hivetimeline script
Pipeline #
...@@ -16,70 +16,77 @@ evtcolors = [] ...@@ -16,70 +16,77 @@ evtcolors = []
class Data: class Data:
pass pass
def read(f,regex='.*'): def read(f,regex='.*',skipevents=0):
data = [] data = []
regex = re.compile(regex) regex = re.compile(regex)
for l in open(f,'r'): for l in open(f,'r'):
if l.startswith('#'): # e.g. #start end algorithm thread slot event if l.startswith('#'): # e.g. #start end algorithm thread slot event
names = l.lstrip('#').split() names = l.lstrip('#').split()
continue continue
d = Data() d = Data()
for i,f in enumerate(l.split()): for i,f in enumerate(l.split()):
setattr(d, names[i], int(f) if f.isdigit() else f) setattr(d, names[i], int(f) if f.isdigit() else f)
data.append(d) if d.event >= skipevents:
data.append(d)
return data return data
def findEvents(data): def findEvents(data):
"""Find event start/stop times""" """Find event start/stop times"""
t = defaultdict(lambda : [sys.maxint, 0]) # start,stop t = defaultdict(lambda : [sys.maxint, 0, -1]) # start,stop,slot
nbslots = 0
for d in data: for d in data:
if d.start<t[d.event][0]: t[d.event][0] = d.start if d.start<t[d.event][0]:
if d.end>t[d.event][1]: t[d.event][1] = d.end t[d.event][0] = d.start
t[d.event][2] = d.slot
return t if d.end>t[d.event][1]:
t[d.event][1] = d.end
if d.slot > nbslots:
nbslots = d.slot
return t, nbslots
def setPalette(nevts): def setPalette(nevts, nevtcolors):
global algcolors, evtcolors global algcolors, evtcolors
from ROOT import TColor from ROOT import TColor
algcolors = range(2,10)+[20,28,29,30,33,38,40]+range(41,50) algcolors = range(2,10)+[20,28,29,30,33,38,40]+range(41,50)
evtcolors = [TColor.GetColor(g,g,g) for g in range(20,255,(255-20)/nevts)] evtcolors = [TColor.GetColor(0,255-g,g) for g in range(20,255,(255-20)/nevtcolors)]
def plot(data, showThreads=True, batch=False, nevtcolors=10, width=1200, height=500):
def plot(data, showThreads=True, batch=False):
import ROOT import ROOT
tmin = min(f.start for f in data) tmin = min(f.start for f in data)
tmax = max(f.end for f in data) tmax = max(f.end for f in data)
slots = 1+max(f.slot for f in data) slots = 1+max(f.slot for f in data)
threads = sorted(list(set(f.thread for f in data))) threads = sorted(list(set(f.thread for f in data)))
threadid = dict((k,v) for v,k in enumerate(threads)) # map thread : id threadid = dict((k,v) for v,k in enumerate(threads)) # map thread : id
ymax = len(threads) if showThreads else slots ymax = len(threads) if showThreads else slots
c = ROOT.TCanvas('timeline','Timeline',1200,500) c = ROOT.TCanvas('timeline','Timeline',width,height)
c.SetLeftMargin(0.05) c.SetLeftMargin(0.05)
c.SetRightMargin(0.2) c.SetRightMargin(0.2)
c.SetTopMargin(0.1) c.SetTopMargin(0.1)
c.coord = ROOT.TH2I('coord',';Time',100,0,tmax-tmin,ymax,0,ymax) c.SetBottomMargin(0.1)
c.coord = ROOT.TH2I('coord',';Time (ns)',100,0,tmax-tmin,ymax,0,ymax)
c.coord.GetYaxis().SetTitle(('Thread' if showThreads else 'Slot')) c.coord.GetYaxis().SetTitle(('Thread' if showThreads else 'Slot'))
c.coord.GetYaxis().SetTitleOffset(0.6) c.coord.GetYaxis().SetTitleOffset(0.5)
c.coord.GetYaxis().CenterTitle()
c.coord.SetStats(False) c.coord.SetStats(False)
c.coord.GetYaxis().SetNdivisions(ymax) c.coord.GetYaxis().SetNdivisions(ymax)
c.coord.GetXaxis().CenterTitle()
c.Draw() c.Draw()
c.coord.Draw() c.coord.Draw()
c.lines = [] c.lines = []
colors = {} colors = {}
setPalette(ymax) setPalette(ymax, nevtcolors)
mycolors = algcolors mycolors = algcolors
for d in data: for d in data:
y = (threadid[d.thread] if showThreads else d.slot) + 0.4 y = (threadid[d.thread] if showThreads else d.slot)
alg = d.algorithm alg = d.algorithm
if alg not in colors and len(mycolors)>0: if alg not in colors and len(mycolors)>0:
colors[alg] = mycolors.pop(0) colors[alg] = mycolors.pop(0)
if len(mycolors)==0: if len(mycolors)==0:
print "Too many algorithm to show" print "Too many algorithm to show"
...@@ -88,35 +95,28 @@ def plot(data, showThreads=True, batch=False): ...@@ -88,35 +95,28 @@ def plot(data, showThreads=True, batch=False):
t0 = d.start - tmin t0 = d.start - tmin
t1 = d.end - tmin t1 = d.end - tmin
# Skip lines with 0 pixels (sometimes leads to artifacts)
if c.XtoPixel(t1)-c.XtoPixel(t0)==0:
continue
# Alg # Alg
l = ROOT.TLine(t0, y, t1, y) l = ROOT.TBox(t0, y+.1, t1, y+.8)
l.SetLineColor(colors[alg]) l.SetFillColor(colors[alg])
l.SetLineWidth(30)
# Event # Event
l2 = ROOT.TLine(t0, y+0.3, t1, y+0.3) l2 = ROOT.TBox(t0, y+.8, t1, y+.9)
l2.SetLineColor(evtcolors[d.event % ymax]) l2.SetFillColor(evtcolors[d.event % nevtcolors])
l2.SetLineWidth(10)
c.lines += [l,l2] c.lines += [l,l2]
l2.Draw() l2.Draw()
l.Draw() l.Draw()
# Global event timeline # Global event timeline
tevt = findEvents(data) tevt, nbslots = findEvents(data)
bheight = 0.1
for k,v in tevt.iteritems(): for k,v in tevt.iteritems():
m = k % ymax # event modulo y = ymax+bheight*v[2]
y = ymax+0.06*m+0.05 l = ROOT.TBox(v[0]-tmin,y+0.2*bheight,v[1]-tmin,y+bheight)
l = ROOT.TLine(v[0]-tmin,y,v[1]-tmin,y) l.SetFillColor(evtcolors[k % nevtcolors])
l.SetLineColor(evtcolors[m])
l.SetLineWidth(5)
c.lines += [l] c.lines += [l]
l.Draw() l.Draw()
# Alg legend # Alg legend
c.leg = ROOT.TLegend(0.8,0.4,0.98,0.9) c.leg = ROOT.TLegend(0.8,0.4,0.98,0.9)
for alg,cl in sorted(colors.iteritems(),key=operator.itemgetter(1)): for alg,cl in sorted(colors.iteritems(),key=operator.itemgetter(1)):
...@@ -126,12 +126,13 @@ def plot(data, showThreads=True, batch=False): ...@@ -126,12 +126,13 @@ def plot(data, showThreads=True, batch=False):
e.SetFillStyle(1001) e.SetFillStyle(1001)
# Event legend # Event legend
for cl in range(ymax): bwidth = 0.18 / nevtcolors
for cl in range(nevtcolors):
l = ROOT.TLine() l = ROOT.TLine()
c.lines.append(l) c.lines.append(l)
l.SetLineWidth(10) l.SetLineWidth(10)
l.SetLineColor(evtcolors[cl]) l.SetLineColor(evtcolors[cl])
l.DrawLineNDC(0.807+0.02*cl,0.37,0.807+0.02*(cl+1),0.37) l.DrawLineNDC(0.807+bwidth*cl,0.37,0.807+bwidth*(cl+1),0.37)
c.t1 = ROOT.TText(0.807,0.314,'Events') c.t1 = ROOT.TText(0.807,0.314,'Events')
c.t1.SetNDC() c.t1.SetNDC()
...@@ -139,6 +140,19 @@ def plot(data, showThreads=True, batch=False): ...@@ -139,6 +140,19 @@ def plot(data, showThreads=True, batch=False):
c.t1.SetTextSize(0.04) c.t1.SetTextSize(0.04)
c.t1.Draw() c.t1.Draw()
c.t2 = ROOT.TText(0.02,0.92,'Event')
c.t2.SetNDC()
c.t2.SetTextFont(42)
c.t2.SetTextSize(0.03)
c.t2.SetTextAngle(90)
c.t2.Draw()
c.t3 = ROOT.TText(0.03,0.922,'Slots')
c.t3.SetNDC()
c.t3.SetTextFont(42)
c.t3.SetTextSize(0.03)
c.t3.SetTextAngle(90)
c.t3.Draw()
c.leg.Draw() c.leg.Draw()
c.Update() c.Update()
if not batch: raw_input() if not batch: raw_input()
...@@ -160,17 +174,29 @@ def main(): ...@@ -160,17 +174,29 @@ def main():
parser.add_argument('--slots', action='store_true', default=False, parser.add_argument('--slots', action='store_true', default=False,
help='Show slots instead of threads (leads to overlaps!)') help='Show slots instead of threads (leads to overlaps!)')
parser.add_argument('-p', '--print', dest='outfile' , nargs='?', parser.add_argument('-p', '--print', dest='outfile' , nargs='?',
const='timeline.png', const='timeline.png',
help='Save to FILE [%(const)s]') help='Save to FILE [%(const)s]')
parser.add_argument('-n', '--nevtcolors', default=10, type=int,
help='Number of colors used for events (10 is default)')
parser.add_argument('-e', '--skipevents', default=0, type=int,
help='Number of events to skip at the start')
parser.add_argument('-x', '--width', default=1200, type=int,
help='width of the output picture')
parser.add_argument('-y', '--height', default=500, type=int,
help='height of the output picture')
args = parser.parse_args() args = parser.parse_args()
data = read(args.timeline[0], args.select) data = read(args.timeline[0], args.select, args.skipevents)
c = plot(data, not args.slots, args.batch) c = plot(data, not args.slots, args.batch, args.nevtcolors, args.width, args.height)
if args.outfile: if args.outfile:
c.SaveAs(args.outfile) c.SaveAs(args.outfile)
return 0 return 0
if __name__ == '__main__': if __name__ == '__main__':
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment