ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/VHbb/python/scaleFactorPlot.py
Revision: 1.1
Committed: Thu Mar 14 16:39:57 2013 UTC (12 years, 2 months ago) by bortigno
Content type: text/x-python
Branch: MAIN
Log Message:
beta version. Script to make the SF plot from the mlfit.root. Option to be used: --sf.

File Contents

# User Rev Content
1 bortigno 1.1 #!/usr/bin/env python
2     import re
3     from sys import argv, stdout, stderr, exit
4     from optparse import OptionParser
5    
6     # import ROOT with a fix to get batch mode (http://root.cern.ch/phpBB3/viewtopic.php?t=3198)
7     hasHelp = False
8     for X in ("-h", "-?", "--help"):
9     if X in argv:
10     hasHelp = True
11     argv.remove(X)
12     argv.append( '-b-' )
13     import ROOT
14     ROOT.gROOT.SetBatch(True)
15     ROOT.gSystem.Load("libHiggsAnalysisCombinedLimit.so")
16     argv.remove( '-b-' )
17     if hasHelp: argv.append("-h")
18    
19     parser = OptionParser(usage="usage: %prog [options] in.root \nrun with --help to get list of options")
20     parser.add_option("--vtol", "--val-tolerance", dest="vtol", default=0.30, type="float", help="Report nuisances whose value changes by more than this amount of sigmas")
21     parser.add_option("--stol", "--sig-tolerance", dest="stol", default=0.10, type="float", help="Report nuisances whose sigma changes by more than this amount")
22     parser.add_option("--vtol2", "--val-tolerance2", dest="vtol2", default=2.0, type="float", help="Report severely nuisances whose value changes by more than this amount of sigmas")
23     parser.add_option("--stol2", "--sig-tolerance2", dest="stol2", default=0.50, type="float", help="Report severely nuisances whose sigma changes by more than this amount")
24     parser.add_option("-a", "--all", dest="all", default=False, action="store_true", help="Print all nuisances, even the ones which are unchanged w.r.t. pre-fit values.")
25     parser.add_option("-A", "--absolute", dest="abs", default=False, action="store_true", help="Report also absolute values of nuisance values and errors, not only the ones normalized to the input sigma")
26     parser.add_option("-p", "--poi", dest="poi", default="r", type="string", help="Name of signal strength parameter (default is 'r' as per text2workspace.py)")
27     parser.add_option("-f", "--format", dest="format", default="text", type="string", help="Output format ('text', 'latex', 'twiki'")
28     parser.add_option("-g", "--histogram", dest="plotfile", default=None, type="string", help="If true, plot the pulls of the nuisances to the given file.")
29     parser.add_option("--sf", "--scale-factor", dest="plotsf", default=None, type="string", help="If true, plot the scale factors in a histograms.")
30    
31     (options, args) = parser.parse_args()
32     if len(args) == 0:
33     parser.print_usage()
34     exit(1)
35    
36     file = ROOT.TFile(args[0])
37     if file == None: raise RuntimeError, "Cannot open file %s" % args[0]
38     fit_s = file.Get("fit_s")
39     fit_b = file.Get("fit_b")
40     prefit = file.Get("nuisances_prefit")
41     if fit_s == None or fit_s.ClassName() != "RooFitResult": raise RuntimeError, "File %s does not contain the output of the signal fit 'fit_s'" % args[0]
42     if fit_b == None or fit_b.ClassName() != "RooFitResult": raise RuntimeError, "File %s does not contain the output of the background fit 'fit_b'" % args[0]
43     if prefit == None or prefit.ClassName() != "RooArgSet": raise RuntimeError, "File %s does not contain the prefit nuisances 'nuisances_prefit'" % args[0]
44    
45     isFlagged = {}
46     table = {}
47     fpf_b = fit_b.floatParsFinal()
48     fpf_s = fit_s.floatParsFinal()
49     pulls = []
50     for i in range(fpf_s.getSize()):
51     nuis_s = fpf_s.at(i)
52     name = nuis_s.GetName();
53     nuis_b = fpf_b.find(name)
54     nuis_p = prefit.find(name)
55     row = []
56     flag = False;
57     mean_p, sigma_p = 0,0
58     if nuis_p == None:
59     if not options.abs: continue
60     row += [ "[%.2f, %.2f]" % (nuis_s.getMin(), nuis_s.getMax()) ]
61     else:
62     mean_p, sigma_p = (nuis_p.getVal(), nuis_p.getError())
63     if options.abs: row += [ "%.2f +/- %.2f" % (nuis_p.getVal(), nuis_p.getError()) ]
64     for fit_name, nuis_x in [('b', nuis_b), ('s',nuis_s)]:
65     if nuis_x == None:
66     row += [ " n/a " ]
67     else:
68     row += [ "%+.2f +/- %.2f" % (nuis_x.getVal(), nuis_x.getError()) ]
69     if nuis_p != None:
70     valShift = (nuis_x.getVal() - mean_p)/sigma_p
71     if fit_name == 'b':
72     pulls.append(valShift)
73     sigShift = nuis_x.getError()/sigma_p
74     if options.abs:
75     row[-1] += " (%+4.2fsig, %4.2f)" % (valShift, sigShift)
76     else:
77     row[-1] = " %+4.2f, %4.2f" % (valShift, sigShift)
78     if (abs(valShift) > options.vtol2 or abs(sigShift-1) > options.stol2):
79     isFlagged[(name,fit_name)] = 2
80     flag = True
81     elif (abs(valShift) > options.vtol or abs(sigShift-1) > options.stol):
82     if options.all: isFlagged[(name,fit_name)] = 1
83     flag = True
84     elif options.all:
85     flag = True
86     row += [ "%+4.2f" % fit_s.correlation(name, options.poi) ]
87     if flag or options.all: table[name] = row
88    
89     fmtstring = "%-40s %15s %15s %10s"
90     highlight = "*%s*"
91     morelight = "!%s!"
92     pmsub, sigsub = None, None
93     if options.format == 'text':
94     if options.abs:
95     fmtstring = "%-40s %15s %30s %30s %10s"
96     print fmtstring % ('name', 'pre fit', 'b-only fit', 's+b fit', 'rho')
97     else:
98     print fmtstring % ('name', 'b-only fit', 's+b fit', 'rho')
99     elif options.format == 'latex':
100     pmsub = (r"(\S+) \+/- (\S+)", r"$\1 \\pm \2$")
101     sigsub = ("sig", r"$\\sigma$")
102     highlight = "\\textbf{%s}"
103     morelight = "{{\\color{red}\\textbf{%s}}}"
104     if options.abs:
105     fmtstring = "%-40s & %15s & %30s & %30s & %6s \\\\"
106     print "\\begin{tabular}{|l|r|r|r|r|} \\hline ";
107     print (fmtstring % ('name', 'pre fit', '$b$-only fit', '$s+b$ fit', r'$\rho(\theta, \mu)$')), " \\hline"
108     else:
109     fmtstring = "%-40s & %15s & %15s & %6s \\\\"
110     print "\\begin{tabular}{|l|r|r|r|} \\hline ";
111     #what = r"$(x_\text{out} - x_\text{in})/\sigma_{\text{in}}$, $\sigma_{\text{out}}/\sigma_{\text{in}}$"
112     what = r"\Delta x/\sigma_{\text{in}}$, $\sigma_{\text{out}}/\sigma_{\text{in}}$"
113     print fmtstring % ('', '$b$-only fit', '$s+b$ fit', '')
114     print (fmtstring % ('name', what, what, r'$\rho(\theta, \mu)$')), " \\hline"
115     elif options.format == 'twiki':
116     pmsub = (r"(\S+) \+/- (\S+)", r"\1 ± \2")
117     sigsub = ("sig", r"σ")
118     highlight = "<b>%s</b>"
119     morelight = "<b style='color:red;'>%s</b>"
120     if options.abs:
121     fmtstring = "| <verbatim>%-40s</verbatim> | %-15s | %-30s | %-30s | %-15s |"
122     print "| *name* | *pre fit* | *b-only fit* | *s+b fit* | "
123     else:
124     fmtstring = "| <verbatim>%-40s</verbatim> | %-15s | %-15s | %-15s |"
125     print "| *name* | *b-only fit* | *s+b fit* | *corr.* |"
126     elif options.format == 'html':
127     pmsub = (r"(\S+) \+/- (\S+)", r"\1 &plusmn; \2")
128     sigsub = ("sig", r"&sigma;")
129     highlight = "<b>%s</b>"
130     morelight = "<strong>%s</strong>"
131     print """
132     <html><head><title>Comparison of nuisances</title>
133     <style type="text/css">
134     td, th { border-bottom: 1px solid black; padding: 1px 1em; }
135     td { font-family: 'Consolas', 'Courier New', courier, monospace; }
136     strong { color: red; font-weight: bolder; }
137     </style>
138     </head><body style="font-family: 'Verdana', sans-serif; font-size: 10pt;"><h1>Comparison of nuisances</h1>
139     <table>
140     """
141     if options.abs:
142     print "<tr><th>nuisance</th><th>pre fit</th><th>background fit </th><th>signal fit</th><th>correlation</th></tr>"
143     fmtstring = "<tr><td><tt>%-40s</tt> </td><td> %-15s </td><td> %-30s </td><td> %-30s </td><td> %-15s </td></tr>"
144     else:
145     what = "&Delta;x/&sigma;<sub>in</sub>, &sigma;<sub>out</sub>/&sigma;<sub>in</sub>";
146     print "<tr><th>nuisance</th><th>background fit<br/>%s </th><th>signal fit<br/>%s</th><th>&rho;(&mu;, &theta;)</tr>" % (what,what)
147     fmtstring = "<tr><td><tt>%-40s</tt> </td><td> %-15s </td><td> %-15s </td><td> %-15s </td></tr>"
148    
149     names = table.keys()
150     names.sort()
151     highlighters = { 1:highlight, 2:morelight };
152     for n in names:
153     v = table[n]
154     if options.format == "latex": n = n.replace(r"_", r"\_")
155     if pmsub != None: v = [ re.sub(pmsub[0], pmsub[1], i) for i in v ]
156     if sigsub != None: v = [ re.sub(sigsub[0], sigsub[1], i) for i in v ]
157     if (n,'b') in isFlagged: v[-3] = highlighters[isFlagged[(n,'b')]] % v[-3]
158     if (n,'s') in isFlagged: v[-2] = highlighters[isFlagged[(n,'s')]] % v[-2]
159     if options.abs:
160     print fmtstring % (n, v[0], v[1], v[2], v[3])
161     else:
162     print fmtstring % (n, v[0], v[1], v[2])
163    
164     if options.format == "latex":
165     print " \\hline\n\end{tabular}"
166     elif options.format == "html":
167     print "</table></body></html>"
168    
169     if options.plotfile:
170     import ROOT
171     ROOT.gROOT.SetStyle("Plain")
172     ROOT.gStyle.SetOptFit(1)
173     histogram = ROOT.TH1F("pulls", "Pulls", 60, -3, 3)
174     for pull in pulls:
175     histogram.Fill(pull)
176     canvas = ROOT.TCanvas("asdf", "asdf", 800, 800)
177     histogram.GetXaxis().SetTitle("pull")
178     histogram.SetTitle("Post-fit nuisance pull distribution")
179     histogram.SetMarkerStyle(20)
180     histogram.SetMarkerSize(2)
181     #histogram.Fit("gaus")
182     histogram.Draw("pe")
183     canvas.SaveAs(options.plotfile)
184    
185    
186     ########### PIER ###############
187     import numpy
188     if options.plotsf:
189     n=0
190     labels=[]
191     v_s=[]
192     v_b=[]
193     rho=[]
194     sys=[]
195     x_position=[]
196     y_position=[]
197     for name in names:
198     if ('SF' in name ):
199     print name
200     labels.append(name)
201     n+=1
202     v = table[name]
203     v = [ re.sub('!','',i) for i in v ]
204     if pmsub != None: v = [ re.sub(pmsub[0], pmsub[1], i) for i in v ]
205     if sigsub != None: v = [ re.sub(sigsub[0], sigsub[1], i) for i in v ]
206     # if (name,'b') in isFlagged: v[-3] = highlighters[isFlagged[(name,'b')]] % v[-3]
207     # if (name,'s') in isFlagged: v[-2] = highlighters[isFlagged[(name,'s')]] % v[-2]
208     v_b.append(v[0].split(','))
209     v_s.append(v[1].split(','))
210     rho.append(v[2].split(','))
211     x_position.append(0.)
212     y_position.append(n+0.5)
213     sys.append(0.1)
214     print n
215     print labels
216     print v_s
217     print v_b
218     print rho
219     sf=[]
220     sf_e=[]
221     initial_uncertainty=0.2
222     for i in v_b:
223     try:
224     sf.append(1+initial_uncertainty*eval(i[0]))
225     sf_e.append(initial_uncertainty*eval(i[1]))
226     except:
227     print 'Problem evaluating the SF or the SF errors'
228     print sf
229     print sf_e
230     c = ROOT.TCanvas("c","c",600,600)
231    
232     #labels = ["W+udscg","W+b#bar{b}","Z+udscg","Z+b#bar{b}","t#bar{t}"]
233     #d = numpy.array([0.94, 1.72, 1.10,1.08,1.01])
234     d = numpy.array(sf)
235     #e = numpy.array([0.02,0.16,0.02,0.04,0.02])
236     e = numpy.array(sf_e)
237     #for the moment just random systematics
238     sys_e = numpy.array(sys)
239     #TO FIX: Y position of the point.
240     p = numpy.array(y_position)
241     zero = numpy.array(x_position)
242    
243     h2 = ROOT.TH2F("h2","",1,0.7,2.2,5,0,5)
244     h2.GetXaxis().SetTitle("Scale factor")
245    
246     for i in range(n):
247     h2.GetYaxis().SetBinLabel(i+1,labels[i])
248    
249     g = ROOT.TGraphErrors(n,d,p,e,zero)
250     g.SetFillColor(0)
251     g.SetLineColor(2)
252     g.SetLineWidth(3)
253     g.SetMarkerStyle(21)
254    
255     g2 = ROOT.TGraphErrors(n,d,p,sys_e,zero)
256     g2.SetFillColor(0)
257     #g2.SetLineColor(2);
258     g2.SetLineWidth(3);
259     g2.SetMarkerStyle(21);
260    
261     h2.Draw(); ROOT.gStyle.SetOptStat(0);
262     h2.GetXaxis().SetTitleSize(0.04);
263     h2.GetXaxis().SetLabelSize(0.04);
264     h2.GetYaxis().SetLabelSize(0.06);
265     #h2.SetFillStyle(4000)
266     c.SetFillStyle(4000)
267    
268     globalFitBand = ROOT.TBox(1.0, 0., 1.5, n);
269     globalFitBand.SetFillStyle(3013);
270     globalFitBand.SetFillColor(65);
271     globalFitBand.SetLineStyle(0);
272     #globalFitBand.Draw("same");
273     globalFitLine = ROOT.TLine(1.0, 0., 1.0, 5.);
274     globalFitLine.SetLineWidth(2);
275     globalFitLine.SetLineColor(214);#214
276     globalFitLine.Draw("same");
277    
278     #l2 = ROOT.TLegend(0.5, 0.82,0.92,0.95)
279     l2 = ROOT.TLegend(0.55, 0.65,0.80,0.87)
280     l2.SetLineWidth(2)
281     l2.SetBorderSize(0)
282     l2.SetFillColor(0)
283     l2.SetFillStyle(4000)
284     l2.SetTextFont(62)
285     l2.AddEntry(g,"Scale factor","p")
286     l2.AddEntry(g,"Statistical","l")
287     l2.AddEntry(g2,"Systematics","l")
288     l2.SetTextSize(0.035)
289     #l2.SetNColumns(2)
290     l2.Draw("same")
291    
292     g.Draw("P same")
293     g2.Draw("[] same")
294     ROOT.gPad.SetLeftMargin(0.2)
295     ROOT.gPad.Update()
296     c.Print("histo.pdf")
297