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 = []
class Data:
pass
def read(f,regex='.*'):
def read(f,regex='.*',skipevents=0):
data = []
regex = re.compile(regex)
for l in open(f,'r'):
if l.startswith('#'): # e.g. #start end algorithm thread slot event
names = l.lstrip('#').split()
names = l.lstrip('#').split()
continue
d = Data()
for i,f in enumerate(l.split()):
setattr(d, names[i], int(f) if f.isdigit() else f)
data.append(d)
if d.event >= skipevents:
data.append(d)
return data
def findEvents(data):
"""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:
if d.start<t[d.event][0]: t[d.event][0] = d.start
if d.end>t[d.event][1]: t[d.event][1] = d.end
return t
if d.start<t[d.event][0]:
t[d.event][0] = d.start
t[d.event][2] = d.slot
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
from ROOT import TColor
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):
def plot(data, showThreads=True, batch=False, nevtcolors=10, width=1200, height=500):
import ROOT
tmin = min(f.start for f in data)
tmax = max(f.end for f in data)
slots = 1+max(f.slot 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
c = ROOT.TCanvas('timeline','Timeline',1200,500)
c = ROOT.TCanvas('timeline','Timeline',width,height)
c.SetLeftMargin(0.05)
c.SetRightMargin(0.2)
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().SetTitleOffset(0.6)
c.coord.GetYaxis().SetTitleOffset(0.5)
c.coord.GetYaxis().CenterTitle()
c.coord.SetStats(False)
c.coord.GetYaxis().SetNdivisions(ymax)
c.coord.GetXaxis().CenterTitle()
c.Draw()
c.coord.Draw()
c.lines = []
colors = {}
setPalette(ymax)
mycolors = algcolors
setPalette(ymax, nevtcolors)
mycolors = algcolors
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
if alg not in colors and len(mycolors)>0:
if alg not in colors and len(mycolors)>0:
colors[alg] = mycolors.pop(0)
if len(mycolors)==0:
print "Too many algorithm to show"
......@@ -88,35 +95,28 @@ def plot(data, showThreads=True, batch=False):
t0 = d.start - tmin
t1 = d.end - tmin
# Skip lines with 0 pixels (sometimes leads to artifacts)
if c.XtoPixel(t1)-c.XtoPixel(t0)==0:
continue
# Alg
l = ROOT.TLine(t0, y, t1, y)
l.SetLineColor(colors[alg])
l.SetLineWidth(30)
l = ROOT.TBox(t0, y+.1, t1, y+.8)
l.SetFillColor(colors[alg])
# Event
l2 = ROOT.TLine(t0, y+0.3, t1, y+0.3)
l2.SetLineColor(evtcolors[d.event % ymax])
l2.SetLineWidth(10)
l2 = ROOT.TBox(t0, y+.8, t1, y+.9)
l2.SetFillColor(evtcolors[d.event % nevtcolors])
c.lines += [l,l2]
l2.Draw()
l.Draw()
# Global event timeline
tevt = findEvents(data)
tevt, nbslots = findEvents(data)
bheight = 0.1
for k,v in tevt.iteritems():
m = k % ymax # event modulo
y = ymax+0.06*m+0.05
l = ROOT.TLine(v[0]-tmin,y,v[1]-tmin,y)
l.SetLineColor(evtcolors[m])
l.SetLineWidth(5)
y = ymax+bheight*v[2]
l = ROOT.TBox(v[0]-tmin,y+0.2*bheight,v[1]-tmin,y+bheight)
l.SetFillColor(evtcolors[k % nevtcolors])
c.lines += [l]
l.Draw()
# Alg legend
c.leg = ROOT.TLegend(0.8,0.4,0.98,0.9)
for alg,cl in sorted(colors.iteritems(),key=operator.itemgetter(1)):
......@@ -126,12 +126,13 @@ def plot(data, showThreads=True, batch=False):
e.SetFillStyle(1001)
# Event legend
for cl in range(ymax):
bwidth = 0.18 / nevtcolors
for cl in range(nevtcolors):
l = ROOT.TLine()
c.lines.append(l)
l.SetLineWidth(10)
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.SetNDC()
......@@ -139,6 +140,19 @@ def plot(data, showThreads=True, batch=False):
c.t1.SetTextSize(0.04)
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.Update()
if not batch: raw_input()
......@@ -160,17 +174,29 @@ def main():
parser.add_argument('--slots', action='store_true', default=False,
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',
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()
data = read(args.timeline[0], args.select)
c = plot(data, not args.slots, args.batch)
data = read(args.timeline[0], args.select, args.skipevents)
c = plot(data, not args.slots, args.batch, args.nevtcolors, args.width, args.height)
if args.outfile:
c.SaveAs(args.outfile)
return 0
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