CMS 3D CMS Logo

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