CMS 3D CMS Logo

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