ATLAS Offline Software
MuonValidation_CreateSlides.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
2 
3 #author: Dan Mori < dmori@cern.ch >
4 #including code by Felix Socher <Felix.Socher@cern.ch>
5 import ROOT
6 import math
7 import sys
8 import os
9 import argparse
10 from commands import getstatusoutput
11 from MuonValidation_CreateSlides_config import *
12 
13 
14 
15 def CreateEmptyPlot( filename ):
16  can = ROOT.TCanvas("","",860,900)
17  can.SaveAs( filename )
18 
19 
20 
21 def SetBounds( refHist, testHist ):
22  maximum = max(refHist.GetMaximum(), testHist.GetMaximum())
23  maximum = maximum + 0.1*abs(maximum)
24  minimum = min(refHist.GetMinimum(), testHist.GetMinimum())
25  minimum = minimum - 0.1*abs(minimum)
26  refHist.SetMinimum(minimum)
27  refHist.SetMaximum(maximum)
28  return refHist
29 
30 
31 
32 def MakeComparisonPlot( refHist, testHist, plotName, path, doNorm = False, doRatio = True ):
33  labelsize = 0.14
34  titlesize = 0.18
35 
36  #check that test histogram exist
37  if not refHist:
38  print('WARNING Ref Histogram not found: '+plotName)
39 
40  if not testHist:
41  print('WARNING Test histogram not found: '+plotName)
42  print(' Creating empty plot')
43  CreateEmptyPlot( path+'/'+plotName+'.png' )
44  return
45 
46  #if doNorm set, scale hists to area = 1
47  if refHist:
48  refint = refHist.Integral()
49  else:
50  refint = 0
51  testint = testHist.Integral()
52 
53  if doNorm:
54  if refint != 0:
55  refHist.Scale( 1./refint )
56  elif refHist:
57  print( 'WARNING empty ref plot ' + plotName )
58 
59  if testint != 0:
60  testHist.Scale( 1./testint )
61  else:
62  print( 'WARNING empty test plot ' + plotName )
63 
64  canvas = ROOT.TCanvas( "", "", 860, 900 )
65  canvas.SetLeftMargin( 0 )
66  padMain = ROOT.TPad( 'padMain', 'padMain', 0, 0.3, 1, 1 )
67  padMain.SetBottomMargin( 0 )
68  padMain.Draw()
69 
70  if doRatio:
71  padRatio = ROOT.TPad( 'padRatio', 'padRatio', 0, 0, 1, 0.3 )
72  padRatio.SetTopMargin( 0 )
73  padRatio.SetBottomMargin( 0.4 )
74  padRatio.Draw()
75  ROOT.TLine()
76  padMain.cd()
77  if 'cone' in plotName:
78  padMain.SetLogy()
79 
80  leg = ROOT.TLegend( 0.82, 0.77, 0.96, .96 )
81  leg.SetFillColor( ROOT.kWhite )
82  leg.SetTextSizePixels(20)
83 
84  testHist.SetMarkerColor(ROOT.kRed)
85  testHist.SetLineColor(ROOT.kRed)
86  leg.AddEntry(testHist, "test",'P')
87 
88  testHist.GetYaxis().SetTitleOffset( 1.4 )
89  testHist.GetYaxis().SetTitleSize( labelsize*0.4 )
90  testHist.SetLabelSize( labelsize*0.4, 'Y' )
91 
92  for i in testHist.GetListOfFunctions():
93  testHist.GetFunction(i.GetName()).SetBit(ROOT.TF1.kNotDraw)
94  testHist.Draw("PE")
95  if refint > 0:
96  for i in refHist.GetListOfFunctions():
97  refHist.GetFunction(i.GetName()).SetBit(ROOT.TF1.kNotDraw)
98 
99  refHist.SetMarkerColor(ROOT.kBlack)
100  refHist.SetLineColor(ROOT.kBlack)
101  leg.AddEntry(refHist, "ref", 'P')
102  if 'cone' not in plotName:
103  refHist = SetBounds(refHist, testHist)
104 
105  refHist.Draw("PESAME")
106  testHist.Draw("PESAME")
107  leg.Draw()
108 
109  # #ks & chi^2 values
110  # if refint > 0 and testint > 0:
111  # ks = testHist.KolmogorovTest( refHist, 'WW' )
112  # kstext = ROOT.TLatex( 0.18, .955, 'KS = %0.3f'%(ks))
113  # kstext.SetNDC(ROOT.kTRUE)
114  # kstext.SetTextSize(0.055)
115  # kstext.Draw()
116  # chi = testHist.Chi2Test( refHist, 'WW' )
117  # #print(chi)
118  # chitext = ROOT.TLatex( 0.4, .955, 'p(#chi^{2}) = %0.3f'%(chi))
119  # chitext.SetNDC(ROOT.kTRUE)
120  # chitext.SetTextSize(0.055)
121  # chitext.Draw()
122 
123  if refint == 0 or testint == 0:
124  print( 'WARNING No ratio plot available: '+ plotName )
125  elif not doRatio:
126  print( 'INFO skipping ratio plot for '+ plotName )
127  else:
128  padRatio.cd()
129  ratioHist = testHist.Clone()
130  ratioHist.Divide( refHist )
131  ratioHist.SetMarkerColor( ROOT.kBlack )
132  ratioHist.SetMaximum(1.2)
133  ratioHist.SetMinimum(0.8)
134  ratioHist.SetLineColor( ROOT.kBlack )
135  ratioHist.GetYaxis().SetTitle( "test / ref" )
136  xtitle = ratioHist.GetXaxis().GetTitle()
137  if 'Transverse Momentum' in xtitle:
138  ratioHist.GetXaxis().SetTitle(xtitle.replace('Transverse Momentum', 'pT'))
139 
140  ratioHist.GetXaxis().SetTitleSize( titlesize )
141  ratioHist.GetYaxis().SetTitleSize( labelsize )
142  ratioHist.SetLabelSize( labelsize, 'XY' )
143  ratioHist.GetXaxis().SetTitleOffset( 1.0 )
144  ratioHist.GetYaxis().SetTitleOffset( .4 )
145  ratioHist.Draw("PE")
146 
147  lineRatio = ROOT.TLine( ratioHist.GetXaxis().GetXmin(), 1,
148  ratioHist.GetXaxis().GetXmax(), 1 )
149  lineRatio.SetLineColor( ROOT.kRed )
150  lineRatio.SetLineWidth( 2 )
151  lineRatio.Draw("same")
152 
153  canvas.cd()
154  canvas.SaveAs( path + '/' + plotName + '.png' )
155  del canvas, padRatio, padMain
156 
157 
158 
159 def main():
160  #parse options
161  parser = argparse.ArgumentParser( description = 'Create Muon Validation Slides in LaTeX Beamer' )
162  parser.add_argument( '-r', '--reference', help = 'reference sample ROOT file' )
163  parser.add_argument( '-t', '--test', required=True, help = 'test sample ROOT file' )
164  parser.add_argument( '-d', '--directory', default = 'beamer', help = 'directory to put new files' )
165  parser.add_argument( '-n', '--notitlepage', action = 'store_true', help = 'set to remove title page' )
166  parser.add_argument( '-c', '--compile', action= 'store_true', help = 'compile beamer file' )
167  args = parser.parse_args()
168  args.directory = os.path.dirname( args.directory + '/' )
169  outdir = args.directory + '/plots'
170  if not os.path.isdir( outdir ):
171  os.makedirs( outdir )
172 
173  #read files
174  testfile = ROOT.TFile.Open( args.test, 'read' )
175  reffile = ROOT.TFile.Open( args.reference, 'read' )
176 
177 
178 
179  specialTypes = [ 'RecoFrac', 'PtRes', 'Res_pT_vs', 'PtScale', 'Eff' ]
180  for PlotList in PlotPages.values():
181  for PlotPath in PlotList:
182  HistDir, HistName = os.path.split( PlotPath )
183  if testfile.GetDirectory( HistDir ):
184  testhist = testfile.GetDirectory( HistDir ).Get( HistName )
185  else:
186  testhist = False
187  if reffile.GetDirectory( HistDir ):
188  refhist = reffile.GetDirectory( HistDir ).Get( HistName )
189  else:
190  refhist = False
191 
192  doNorm = not sum([ HistName.__contains__(i) for i in specialTypes ])
193  #doRatio = not (plot.__contains__('PtRes') or plot.__contains__('PtScale'))
194  MakeComparisonPlot( refhist, testhist, HistName, outdir, doNorm = doNorm, doRatio = True )
195 
196  testfile.Close()
197  reffile.Close()
198 
199 
200  endl = '\n'
201  output = r'\documentclass{beamer}' + endl
202  output += r'\definecolor{links}{HTML}{0000FF}' + endl
203  output += r'\hypersetup{colorlinks=true,urlcolor=links}' + endl
204  output += r'\usepackage[latin1]{inputenc}' + endl
205  output += r'\usetheme{Warsaw}' + endl*2
206  output += r'\definecolor{LightBlue}{cmyk}{0.248,0.0609,0,0.098}' + endl
207  output += r'\setbeamercolor{author in head/foot}{fg=white, bg=blue}'+endl
208  output += r'\setbeamercolor{title in head/foot}{fg=white, bg=LightBlue}'+endl
209  output += r'\makeatother' + endl
210  output += r'\setbeamertemplate{footline}{' + endl
211  output += r'\leavevmode' + endl
212  output += r'\hbox{%' + endl
213 
214  ht = 2.4
215  dp = 1.1
216  output += r'\begin{beamercolorbox}[wd=0.4\paperwidth,ht=%0.3fex,dp=%0.3fex,center]{author in head/foot}'%( ht, dp ) + r'%' + endl
217  output += r' \usebeamerfont{author in head/foot}\insertshortauthor' + endl
218 
219  output += r'\end{beamercolorbox}%' + endl
220  output += r'\begin{beamercolorbox}[wd=0.5\paperwidth,ht=%0.3fex,dp=%0.3fex,center]{title in head/foot}'%( ht, dp ) + r'%' + endl
221  output += r' \usebeamerfont{author in head/foot}\insertshorttitle' + endl
222  output += r'\end{beamercolorbox}%' + endl
223  output += r'\begin{beamercolorbox}[wd=0.1\paperwidth,ht=%0.3fex,dp=%0.3fex,center]{author in head/foot}'%( ht, dp ) + r'%' + endl
224  output += r' \insertframenumber{}/\inserttotalframenumber' + endl
225  output += r'\end{beamercolorbox}}%' + endl
226  output += r'\vskip0pt}' + endl*2
227 
228  output += r'\makeatletter' + endl
229  output += r'\setbeamertemplate{navigation symbols}{}' + endl*2
230  output += r'\setbeamerfont{footline}{size=\fontsize{10}{11}\selectfont}' + endl
231 
232  output += r'\setbeamersize{text margin left=0.5cm}' + endl
233  output += r'\setbeamersize{text margin right=0.5cm}' + endl
234 
235  output += r'\title[%s]{%s}'%(ShortTitle, Title) + endl
236  output += r'\subtitle{%s}'%(Subtitle) + endl
237  output += r'\author[%s]{%s}'%(ShortAuthor, Author) + endl
238  output += r'\institute[%s]{%s}'%(ShortInstitute, Institute) + endl
239  output += r'\date{%s}'%(Date) + endl
240  output += r'\begin{document}' + endl*2
241  output += r'%%%%%%%%%%%%%%%%%%%% BEGIN DOCUMENT %%%%%%%%%%%%%%%%%%%%' + endl*2
242  if not args.notitlepage:
243  output += r'{\setbeamertemplate{footline}{}' + endl
244  output += r'\begin{frame} \titlepage \end{frame} }' + endl
245  output += r'\addtocounter{framenumber}{-1}' + endl*2
246 
247  #intro slide
248  output += r'\begin{frame}' + endl
249  output += r'\frametitle{Introduction}' + endl
250  output += 'Reference:' + endl*2
251  output += '{0}: {1}'.format(RefVersion, RefDescription) + endl*2
252  output += RefDataset + endl*2
253  output += r'\vspace{12pt}' + endl
254  output += 'Test:' + endl*2
255  output += '{0}: {1}'.format(TestVersion, TestDescription) + endl*2
256  output += TestDataset + endl*2
257  output += r'\vspace{12pt}' + Intro + endl
258  output += r'\end{frame}' + endl*2
259 
260  for page in PlotPages:
261  plotlist = PlotPages[page]
262  output += r'\begin{frame}' + endl
263  output += r'\frametitle{%s}'%(page) + endl
264  output += r'\hspace*{-4pt}\makebox[\linewidth][c]{' + endl
265  output += r'\begin{tabular}{c%s}'%(r'@{\hspace{1pt}}c'*(len(plotlist)-1)) + endl
266  for n, plotpath in enumerate(plotlist):
267  output += r'\includegraphics[width=%0.2f\textwidth]{%s/%s.png}'%( 0.35, outdir.replace( args.directory+'/', '' ), os.path.split(plotpath)[1] )
268  if n+1 < len(plotlist):
269  output += ' &'
270  output += endl
271  output += r'\end{tabular} }' + endl
272  if page in PlotComments:
273  output += PlotComments[page] + endl
274  output += r'\end{frame}' + endl*2
275 
276  #summary slide
277  if len(Summary) > 0:
278  output += r'\begin{frame}' + endl
279  output += 'Summary' + endl
280  output += r'\begin{itemize}' + endl
281 
282  for item in Summary:
283  output += r'\item %s'%(item) + endl
284 
285  output += r'\end{itemize}' + endl
286  output += r'\end{frame}' + endl
287  output += r'\end{document}'
288 
289  with open( args.directory + '/' + texfile, 'w' ) as f:
290  f.write( output )
291 
292  badEnvVars = [ 'TEXMFCNF', 'TEXINPUTS', 'TEXMFHOME' ] #Athena sets these vars but LaTeX doesn't like them
293  for i in badEnvVars:
294  os.unsetenv(i)
295  if args.compile:
296  stat, out = getstatusoutput( 'cd %s; pdflatex -halt-on-error %s; pdflatex -halt-on-error %s'%( args.directory, texfile, texfile ) )
297  if stat != 0:
298  print out
299 
300 
301 
302 
303 if __name__ == "__main__":
304  if sys.version_info < (2,7):
305  print( 'INFO This program requires Python version 2.7 or greater' )
306  exit(1)
307 
308  #ROOT.gROOT.Macro("rootlogon.C")
309  ROOT.gROOT.SetBatch()
310  main()
max
#define max(a, b)
Definition: cfImp.cxx:41
vtune_athena.format
format
Definition: vtune_athena.py:14
MuonValidation_CreateSlides.main
def main()
Definition: MuonValidation_CreateSlides.py:159
MuonValidation_CreateSlides.SetBounds
def SetBounds(refHist, testHist)
Definition: MuonValidation_CreateSlides.py:21
Get
T * Get(TFile &f, const std::string &n, const std::string &dir="", const chainmap_t *chainmap=0, std::vector< std::string > *saved=0)
get a histogram given a path, and an optional initial directory if histogram is not found,...
Definition: comparitor.cxx:178
convertTimingResiduals.sum
sum
Definition: convertTimingResiduals.py:55
MuonValidation_CreateSlides.MakeComparisonPlot
def MakeComparisonPlot(refHist, testHist, plotName, path, doNorm=False, doRatio=True)
Definition: MuonValidation_CreateSlides.py:32
calibdata.exit
exit
Definition: calibdata.py:236
min
#define min(a, b)
Definition: cfImp.cxx:40
Trk::open
@ open
Definition: BinningType.h:40
Muon::print
std::string print(const MuPatSegment &)
Definition: MuonTrackSteering.cxx:28
MuonValidation_CreateSlides.CreateEmptyPlot
def CreateEmptyPlot(filename)
Definition: MuonValidation_CreateSlides.py:15