CMS 3D CMS Logo

cmsTiming_parser.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 
3 from __future__ import print_function
4 import sys, os
5 import time
6 import optparse
7 from math import sqrt, log10, floor
8 
9 import ROOT
10 
11 def manipulate_log(outdir, logfile_name, secsperbin):
12  """ Parses logfile_name and create an html report
13  with information and plots, at the outdir path.
14  Graphs' production is also done here.
15  """
16  ################################
17  #### Parse of the log file. ####
18  ################################
19  logfile = open(logfile_name,'r')
20  logfile_lines = iter(logfile.readlines())
21  logfile.close()
22  data = {}
23  report = ''
24  for line in logfile_lines:
25  # Retrieve cpu time of every event.
26  if 'TimeEvent>' in line:
27  line = line[:-1] #no \n!
28  content = line.split(' ')
29  event = int(content[1])
30  seconds = float(content[3])
31  data[event] = seconds
32  # Fill the time report.
33  elif 'TimeReport' in line:
34  if '[sec]' in line:
35  report += line.replace('TimeReport', '\n')
36  elif 'headings' in line:
37  continue
38  elif 'complete' in line:
39  report += line.replace('TimeReport', '\n')
40  for count in range(12):
41  line = next(logfile_lines)
42  report += line
43  break
44  else:
45  report += line.replace('TimeReport', '')
46 
47  ##############################
48  #### Graph and Histogram ####
49  ##############################
50  __argv = sys.argv # trick for a strange behaviour of the TApp..
51  sys.argv = sys.argv[:1]
52  ROOT.gROOT.SetStyle("Plain") # style paranoia
53  sys.argv = __argv
54  #Cannot use this option when the logfile includes
55  #a large number of events... PyRoot seg-faults.
56  #Set ROOT in batch mode to avoid canvases popping up!
57  ROOT.gROOT.SetBatch(1)
58 
59  # Save in file
60  rootfilename = '%s/graphs.root' %outdir
61  myfile = ROOT.TFile(rootfilename,'RECREATE')
62 
63  # Set limits
64  min_val = data[min(data, key=data.get)]
65  max_val = data[max(data, key=data.get)]
66  interval = max_val-min_val
67  min_val = min_val - (interval*0.2)
68  max_val = max_val + (interval*0.2)
69  interval = max_val - min_val
70  nbins = int(interval/secsperbin)
71 
72  # Initialize Histogram
73  histo = ROOT.TH1F('Seconds per event','Seconds per event', nbins, min_val, max_val)
74  histo.GetXaxis().SetTitle("s")
75  # Initialize Graph
76  npoints = len(data)
77  graph = ROOT.TGraph(npoints)
78  graph.SetMarkerStyle(8)
79  graph.SetMarkerSize(.7)
80  graph.SetMarkerColor(1)
81  graph.SetLineWidth(3)
82  graph.SetLineColor(2)
83  graph.SetTitle('Seconds per event')
84  graph.SetName('SecondsPerEvent')
85  graph.GetXaxis().SetTitle("Event")
86  last_event = max(data)
87  graph.GetXaxis().SetLimits(0, last_event)
88  graph.GetYaxis().SetTitleOffset(1.3)
89  graph.GetYaxis().SetTitle("s")
90  graph.GetYaxis().SetRangeUser(0, max_val)
91  # Fill them
92  total_time = 0
93  for event_num in data.keys():
94  seconds = data[event_num]
95  graph.SetPoint(event_num-1, event_num, seconds)
96  histo.Fill(seconds)
97  total_time += seconds
98  # A line which represents the average is drawn in the TGraph
99  avg = histo.GetMean()
100  avg_line = ROOT.TLine(1,avg,last_event, avg)
101  avg_line.SetLineColor(4)
102  avg_line.SetLineWidth(2)
103  # Draw and save!
104  graph_canvas = ROOT.TCanvas('graph_canvas')
105  graph_canvas.cd()
106  graph.Draw("ALP")
107  avg_line.Draw("Same")
108 
109 
110  # Write graph to file
111  graph_canvas.Print("%s/graph.png" %outdir,"png")
112  graph.Write()
113  graph_canvas.Write()
114  histo_canvas = ROOT.TCanvas('histo_canvas')
115  histo_canvas.cd()
116  histo.Draw('')
117 
118  # Write histogram to file
119  histo_canvas.Print("%s/histo.png" %outdir,"png")
120  histo.Write()
121  histo_canvas.Write()
122 
123  myfile.Close()
124 
125  ########################
126  #### The html page! ####
127  ########################
128  titlestring = '<b>Report executed with release %s on %s.</b>\n<br>\n<hr>\n'\
129  %(os.environ['CMSSW_VERSION'], time.asctime())
130  html_file_name = '%s/%s_TimingReport.html' %(outdir, logfile_name[:-4])
131  html_file = open(html_file_name,'w')
132  html_file.write('<html>\n<body>\n'+\
133  titlestring)
134  html_file.write('<table>\n'+\
135  '<tr>\n<td><img src=graph.png></img></td>\n'+\
136  '<td><img src=histo.png></img></td>\n</tr>\n'+\
137  '</table>\n')
138  html_file.write('<hr>\n<h2>Time Report</h2>\n<pre>\n' + report + '</pre>\n')
139  html_file.write('</body>\n</html>')
140  html_file.close()
141 
142  ##########################
143  #### Print statistics ####
144  ##########################
145  total_events = max(data)
146  average_time = total_time / total_events
147  sum = 0.
148  for i in range(1, max(data)+1):
149  sum += (data[i]-average_time)**2
150  denominator = total_events**2 - total_events
151  uncertainty = sqrt(sum/denominator)
152  # Comment out next 2 line to round uncertainty to the most significant digit
153  #rounded_uncertainty=round(uncertainty, -int(floor(log10(uncertainty))))
154  #print 'Rounded uncertainty=' , rounded_uncertainty
155  print('------ Statistics ------')
156  print('last event = {}'.format(last_event))
157  print('Minval = {} maxval = {} interval = {}'.format(min_val, max_val, interval))
158  print('Total Time = {}'.format(total_time))
159  print('Average Time = {}'.format(average_time))
160  print('Uncertainty of Average Time = {} +/- {}'.format(average_time, uncertainty))
161 
162 #################################################################################################
163 
164 if __name__ == '__main__':
165 
166  # Here we define an option parser to handle commandline options..
167  usage = 'timing_parser.py <options>'
168  parser = optparse.OptionParser(usage)
169  parser.add_option('-i', '--in_ profile',
170  help='The profile to manipulate' ,
171  default='',
172  dest='profile')
173 
174  parser.add_option('-o', '--outdir',
175  help='The directory of the output' ,
176  default='',
177  dest='outdir')
178 
179  parser.add_option('-n',
180  help='Number of secs per bin. Default is 1.' ,
181  default='1',
182  dest='startevt')
183  (options,args) = parser.parse_args()
184 
185  # Now some fault control..If an error is found we raise an exception
186  if options.profile == '' or\
187  options.outdir == '':
188  raise Exception('Please select a profile and an output dir!')
189 
190  if not os.path.exists(options.profile) or\
191  not os.path.exists(options.outdir):
192  raise Exception('Outdir or input profile not present!')
193 
194  try:
195  startevt = float(options.startevt)
196  except ValueError:
197  print('Problems in convertng starting event value!')
198 
199  # launch the function!
200  manipulate_log(options.outdir,options.profile,startevt)
S & print(S &os, JobReport::InputFile const &f)
Definition: JobReport.cc:65
T sqrt(T t)
Definition: SSEVec.h:18
T min(T a, T b)
Definition: MathUtil.h:58
def manipulate_log(outdir, logfile_name, secsperbin)