ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/VHbb/python/scaleFactorPlot.py
Revision: 1.3
Committed: Tue Mar 19 19:09:36 2013 UTC (12 years, 1 month ago) by bortigno
Content type: text/x-python
Branch: MAIN
CVS Tags: LHCP_PreAppFreeze
Changes since 1.2: +272 -65 lines
Log Message:
@UPDATE

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 bortigno 1.3 from HiggsAnalysis.CombinedLimit.DatacardParser import *
6     from HiggsAnalysis.CombinedLimit.ShapeTools import *
7     from copy import copy,deepcopy
8    
9    
10    
11     def removeDouble(seq):
12     seen = set()
13     seen_add = seen.add
14     return [ x for x in seq if x not in seen and not seen_add(x)]
15    
16    
17     def getInputSigma(options):
18     opts = copy(options)
19     # options = copy(opts)
20     # options.dataname = "data_obs"
21     # options.mass = 0
22     # options.format = "%8.3f +/- %6.3f"
23     # options.channel = opts.bins
24    
25     # options.norm = False
26    
27     # options.bin = True # fake that is a binary output, so that we parse shape lines
28     # options.out = "tmp.root"
29     # options.fileName = args[0]
30     # options.cexpr = False
31     # options.fixpars = False
32     # options.libs = []
33     # options.verbose = 0
34     # options.poisson = 0
35    
36     # options.noJMax = None
37     # theBinning = ROOT.RooFit.Binning(Stack.nBins,Stack.xMin,Stack.xMax)
38    
39     file = open(opts.dc, "r")
40     # os.chdir(os.path.dirname(opts.dc))
41     opts.bin = True
42     opts.noJMax = None
43     opts.nuisancesToExclude = []
44     opts.stat = False
45     opts.excludeSyst = ['SF']
46     DC = parseCard(file, opts)
47    
48     theSyst = {}
49     nuiVar = {}
50     # if not opts.bin in DC.bins: raise RuntimeError, "Cannot open find %s in bins %s of %s" % (opts.bin,DC.bins,opts.dc)
51     b = DC.bins[0]
52     exps = {}
53     expNui = {}
54     for (p,e) in DC.exp[b].items(): # so that we get only self.DC.processes contributing to this bin
55     exps[p] = [ e, [] ]
56     expNui[p] = [ e, [] ]
57     # print DC.systs
58     for (lsyst,nofloat,pdf,pdfargs,errline) in DC.systs:
59     if pdf in ('param', 'flatParam'): continue
60     # begin skip systematics
61     skipme = False
62     for xs in opts.excludeSyst:
63     if not re.search(xs, lsyst):
64     skipme = True
65     if skipme: continue
66     # end skip systematics
67     counter = 0
68     for p in DC.exp[b].keys(): # so that we get only self.DC.processes contributing to this bin
69     if errline[b][p] == 0: continue
70     if p == 'QCD': continue
71     if pdf == 'gmN':
72     exps[p][1].append(1/sqrt(pdfargs[0]+1));
73     elif pdf == 'gmM':
74     exps[p][1].append(errline[b][p]);
75     elif type(errline[b][p]) == list:
76     kmax = max(errline[b][p][0], errline[b][p][1], 1.0/errline[b][p][0], 1.0/errline[b][p][1]);
77     exps[p][1].append(kmax-1.);
78     elif pdf == 'lnN':
79     exps[p][1].append(max(errline[b][p], 1.0/errline[b][p])-1.);
80     # print exps
81     return exps
82     # if not nuiVar.has_key('%s_%s'%(opts.fit,lsyst)):
83     # nui = 0.
84     # else:
85     # nui= nuiVar['%s_%s'%(opts.fit,lsyst)]
86     # expNui[p][1].append(abs(1-errline[b][p])*nui);
87    
88    
89    
90    
91     def getGraph(channel,labels,shift,v_b,input_sigma,x_position,y_position,nuisances):
92     print 'Channel' + channel
93     sf=[]
94     sf_e=[]
95     # correspondency_dictionary = {"TT":"TT","s_Top":"s_Top","Zj0b":"Z0b","Zj1b":"Z1b","Zj2b":"Z2b","Wj0b":"Wj0b","Wj1b":"Wj1b","Wj2b":"Wj2b","Zj1HF":"Z1b","Zj2HF":"Z2b","ZjLF":"Z0b"}
96     correspondency_dictionary = {"TT":"TT","s_Top":"s_Top","Zj0b":"Zj0b","Zj1b":"Zj1b","Zj2b":"Zj2b","Wj0b":"Wj0b","Wj1b":"Wj1b","Wj2b":"Wj2b","Zj1HF":"Z1b","Zj2HF":"Z2b","ZjLF":"Z0b","s_Top":"s_Top"}
97     # print input_sigma
98     # print input_sigma['TT'][1][0]
99     # initial_uncertainty=0.2 # initial uncertainty. @TO FIX: this can go in a config or as input arg
100     count=0
101     print labels
102     channels = ['high','High','low','Low','Med','med']
103     for i in v_b:
104     print 'Nuisances ' + nuisances[count]
105     for h in channels:
106     if h in channel and h in re.sub('M','m',re.sub('L','l',re.sub('H','h',nuisances[count]))):
107     print count
108     try:
109     print 'Label : ' + str(labels[count])
110     print 'Relative SF : ' + i[0]
111     print 'Relative Error : ' + i[1]
112     print 'Correspondance : ' + str(correspondency_dictionary[labels[count]])
113     print 'Input sigma list : ' + str(input_sigma[correspondency_dictionary[labels[count]]])
114     print 'Input sigma value : ' + str(input_sigma[correspondency_dictionary[labels[count]]][1][0])
115     sf.append(1+input_sigma[correspondency_dictionary[labels[count]]][1][0]*eval(i[0])) # calculate the actual value for the scale factors
116     sf_e.append(input_sigma[correspondency_dictionary[labels[count]]][1][0]*eval(i[1])) # calculate the actula value for the uncertainties
117     print sf
118     print sf_e
119     except:
120     print 'Problem evaluating the SF or the SF errors'
121     # elif( any(lowPt) in channel and any(lowPt) in nuisances[count]):
122     # print count
123     # try:
124     # print labels[count]
125     # print i
126     # sf.append(1+input_sigma[correspondency_dictionary[labels[count]]][1][0]*eval(i[0])) # calculate the actual value for the scale factors
127     # sf_e.append(input_sigma[correspondency_dictionary[labels[count]]][1][0]*eval(i[1])) # calculate the actula value for the uncertainties
128     # print sf
129     # except:
130     # print 'Problem evaluating the SF or the SF errors'
131     # else:
132     # try:
133     # print labels[count]
134     # print correspondency_dictionary[labels[count]]
135     # print input_sigma[correspondency_dictionary[labels[count]]]
136     # print input_sigma[correspondency_dictionary[labels[count]]][1][0]
137     # sf.append(1+input_sigma[correspondency_dictionary[labels[count]]][1][0]*eval(i[0])) # calculate the actual value for the scale factors
138     # sf_e.append(input_sigma[correspondency_dictionary[labels[count]]][1][0]*eval(i[1])) # calculate the actula value for the uncertainties
139     # except:
140     # print 'Problem evaluating the SF or the SF errors'
141     count+=1
142     print sf
143     print sf_e
144    
145     d = numpy.array(sf) # store scale factors in array
146     e = numpy.array(sf_e) # store scale factors errors in array
147     p = numpy.array(y_position)
148     zero = numpy.array(x_position)
149    
150     # for i in range(len(labels)):
151     # print 'CMSSW_vhbb_'+labels[i]+'_Zll_SF_8TeV '+ str(d[i]) + ' +/- ' + str(e[i])
152    
153     markerStyle = 20
154     if ('high' in channel or 'High' in channel ):
155     markerStyle = 21
156     if ('med' in channel or 'Med' in channel ):
157     markerStyle = 22
158    
159     for i in range(len(p)): p[i] = p[i]+shift
160     print 'POSITIONS: '
161     print p
162     g = ROOT.TGraphErrors(n,d,p,e,zero)
163     g.SetFillColor(0)
164     g.SetLineColor(2)
165     g.SetLineWidth(3)
166     g.SetMarkerStyle(markerStyle)
167     return g
168    
169    
170    
171 bortigno 1.1
172     # import ROOT with a fix to get batch mode (http://root.cern.ch/phpBB3/viewtopic.php?t=3198)
173     hasHelp = False
174     for X in ("-h", "-?", "--help"):
175     if X in argv:
176     hasHelp = True
177     argv.remove(X)
178     argv.append( '-b-' )
179     import ROOT
180     ROOT.gROOT.SetBatch(True)
181     ROOT.gSystem.Load("libHiggsAnalysisCombinedLimit.so")
182     argv.remove( '-b-' )
183     if hasHelp: argv.append("-h")
184    
185     parser = OptionParser(usage="usage: %prog [options] in.root \nrun with --help to get list of options")
186     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")
187     parser.add_option("--stol", "--sig-tolerance", dest="stol", default=0.10, type="float", help="Report nuisances whose sigma changes by more than this amount")
188     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")
189     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")
190     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.")
191     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")
192     parser.add_option("-p", "--poi", dest="poi", default="r", type="string", help="Name of signal strength parameter (default is 'r' as per text2workspace.py)")
193     parser.add_option("-f", "--format", dest="format", default="text", type="string", help="Output format ('text', 'latex', 'twiki'")
194     parser.add_option("-g", "--histogram", dest="plotfile", default=None, type="string", help="If true, plot the pulls of the nuisances to the given file.")
195     parser.add_option("--sf", "--scale-factor", dest="plotsf", default=None, type="string", help="If true, plot the scale factors in a histograms.")
196 bortigno 1.3 parser.add_option("-D", "--datacard", dest="dc", default="", help="Datacard to be plotted")
197 bortigno 1.1
198     (options, args) = parser.parse_args()
199     if len(args) == 0:
200     parser.print_usage()
201     exit(1)
202    
203     file = ROOT.TFile(args[0])
204     if file == None: raise RuntimeError, "Cannot open file %s" % args[0]
205     fit_s = file.Get("fit_s")
206     fit_b = file.Get("fit_b")
207     prefit = file.Get("nuisances_prefit")
208     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]
209     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]
210     if prefit == None or prefit.ClassName() != "RooArgSet": raise RuntimeError, "File %s does not contain the prefit nuisances 'nuisances_prefit'" % args[0]
211    
212     isFlagged = {}
213     table = {}
214     fpf_b = fit_b.floatParsFinal()
215     fpf_s = fit_s.floatParsFinal()
216     pulls = []
217     for i in range(fpf_s.getSize()):
218     nuis_s = fpf_s.at(i)
219     name = nuis_s.GetName();
220     nuis_b = fpf_b.find(name)
221     nuis_p = prefit.find(name)
222     row = []
223     flag = False;
224     mean_p, sigma_p = 0,0
225     if nuis_p == None:
226     if not options.abs: continue
227     row += [ "[%.2f, %.2f]" % (nuis_s.getMin(), nuis_s.getMax()) ]
228     else:
229     mean_p, sigma_p = (nuis_p.getVal(), nuis_p.getError())
230     if options.abs: row += [ "%.2f +/- %.2f" % (nuis_p.getVal(), nuis_p.getError()) ]
231     for fit_name, nuis_x in [('b', nuis_b), ('s',nuis_s)]:
232     if nuis_x == None:
233     row += [ " n/a " ]
234     else:
235     row += [ "%+.2f +/- %.2f" % (nuis_x.getVal(), nuis_x.getError()) ]
236     if nuis_p != None:
237     valShift = (nuis_x.getVal() - mean_p)/sigma_p
238     if fit_name == 'b':
239     pulls.append(valShift)
240     sigShift = nuis_x.getError()/sigma_p
241 bortigno 1.3 # print name
242     # print nuis_x.getError()
243     # print nuis_p.getVal()
244     # print sigShift
245 bortigno 1.1 if options.abs:
246     row[-1] += " (%+4.2fsig, %4.2f)" % (valShift, sigShift)
247     else:
248     row[-1] = " %+4.2f, %4.2f" % (valShift, sigShift)
249     if (abs(valShift) > options.vtol2 or abs(sigShift-1) > options.stol2):
250     isFlagged[(name,fit_name)] = 2
251     flag = True
252     elif (abs(valShift) > options.vtol or abs(sigShift-1) > options.stol):
253     if options.all: isFlagged[(name,fit_name)] = 1
254     flag = True
255     elif options.all:
256     flag = True
257     row += [ "%+4.2f" % fit_s.correlation(name, options.poi) ]
258     if flag or options.all: table[name] = row
259    
260     fmtstring = "%-40s %15s %15s %10s"
261     highlight = "*%s*"
262     morelight = "!%s!"
263     pmsub, sigsub = None, None
264     if options.format == 'text':
265     if options.abs:
266     fmtstring = "%-40s %15s %30s %30s %10s"
267     print fmtstring % ('name', 'pre fit', 'b-only fit', 's+b fit', 'rho')
268     else:
269     print fmtstring % ('name', 'b-only fit', 's+b fit', 'rho')
270     elif options.format == 'latex':
271     pmsub = (r"(\S+) \+/- (\S+)", r"$\1 \\pm \2$")
272     sigsub = ("sig", r"$\\sigma$")
273     highlight = "\\textbf{%s}"
274     morelight = "{{\\color{red}\\textbf{%s}}}"
275     if options.abs:
276     fmtstring = "%-40s & %15s & %30s & %30s & %6s \\\\"
277     print "\\begin{tabular}{|l|r|r|r|r|} \\hline ";
278     print (fmtstring % ('name', 'pre fit', '$b$-only fit', '$s+b$ fit', r'$\rho(\theta, \mu)$')), " \\hline"
279     else:
280     fmtstring = "%-40s & %15s & %15s & %6s \\\\"
281     print "\\begin{tabular}{|l|r|r|r|} \\hline ";
282     #what = r"$(x_\text{out} - x_\text{in})/\sigma_{\text{in}}$, $\sigma_{\text{out}}/\sigma_{\text{in}}$"
283     what = r"\Delta x/\sigma_{\text{in}}$, $\sigma_{\text{out}}/\sigma_{\text{in}}$"
284     print fmtstring % ('', '$b$-only fit', '$s+b$ fit', '')
285     print (fmtstring % ('name', what, what, r'$\rho(\theta, \mu)$')), " \\hline"
286     elif options.format == 'twiki':
287     pmsub = (r"(\S+) \+/- (\S+)", r"\1 ± \2")
288     sigsub = ("sig", r"σ")
289     highlight = "<b>%s</b>"
290     morelight = "<b style='color:red;'>%s</b>"
291     if options.abs:
292     fmtstring = "| <verbatim>%-40s</verbatim> | %-15s | %-30s | %-30s | %-15s |"
293     print "| *name* | *pre fit* | *b-only fit* | *s+b fit* | "
294     else:
295     fmtstring = "| <verbatim>%-40s</verbatim> | %-15s | %-15s | %-15s |"
296     print "| *name* | *b-only fit* | *s+b fit* | *corr.* |"
297     elif options.format == 'html':
298     pmsub = (r"(\S+) \+/- (\S+)", r"\1 &plusmn; \2")
299     sigsub = ("sig", r"&sigma;")
300     highlight = "<b>%s</b>"
301     morelight = "<strong>%s</strong>"
302     print """
303     <html><head><title>Comparison of nuisances</title>
304     <style type="text/css">
305     td, th { border-bottom: 1px solid black; padding: 1px 1em; }
306     td { font-family: 'Consolas', 'Courier New', courier, monospace; }
307     strong { color: red; font-weight: bolder; }
308     </style>
309     </head><body style="font-family: 'Verdana', sans-serif; font-size: 10pt;"><h1>Comparison of nuisances</h1>
310     <table>
311     """
312     if options.abs:
313     print "<tr><th>nuisance</th><th>pre fit</th><th>background fit </th><th>signal fit</th><th>correlation</th></tr>"
314     fmtstring = "<tr><td><tt>%-40s</tt> </td><td> %-15s </td><td> %-30s </td><td> %-30s </td><td> %-15s </td></tr>"
315     else:
316     what = "&Delta;x/&sigma;<sub>in</sub>, &sigma;<sub>out</sub>/&sigma;<sub>in</sub>";
317     print "<tr><th>nuisance</th><th>background fit<br/>%s </th><th>signal fit<br/>%s</th><th>&rho;(&mu;, &theta;)</tr>" % (what,what)
318     fmtstring = "<tr><td><tt>%-40s</tt> </td><td> %-15s </td><td> %-15s </td><td> %-15s </td></tr>"
319    
320     names = table.keys()
321     names.sort()
322     highlighters = { 1:highlight, 2:morelight };
323     for n in names:
324     v = table[n]
325     if options.format == "latex": n = n.replace(r"_", r"\_")
326     if pmsub != None: v = [ re.sub(pmsub[0], pmsub[1], i) for i in v ]
327     if sigsub != None: v = [ re.sub(sigsub[0], sigsub[1], i) for i in v ]
328     if (n,'b') in isFlagged: v[-3] = highlighters[isFlagged[(n,'b')]] % v[-3]
329     if (n,'s') in isFlagged: v[-2] = highlighters[isFlagged[(n,'s')]] % v[-2]
330     if options.abs:
331     print fmtstring % (n, v[0], v[1], v[2], v[3])
332     else:
333     print fmtstring % (n, v[0], v[1], v[2])
334    
335     if options.format == "latex":
336     print " \\hline\n\end{tabular}"
337     elif options.format == "html":
338     print "</table></body></html>"
339    
340     if options.plotfile:
341     import ROOT
342     ROOT.gROOT.SetStyle("Plain")
343     ROOT.gStyle.SetOptFit(1)
344     histogram = ROOT.TH1F("pulls", "Pulls", 60, -3, 3)
345     for pull in pulls:
346     histogram.Fill(pull)
347     canvas = ROOT.TCanvas("asdf", "asdf", 800, 800)
348     histogram.GetXaxis().SetTitle("pull")
349     histogram.SetTitle("Post-fit nuisance pull distribution")
350     histogram.SetMarkerStyle(20)
351     histogram.SetMarkerSize(2)
352     #histogram.Fit("gaus")
353     histogram.Draw("pe")
354     canvas.SaveAs(options.plotfile)
355    
356    
357 bortigno 1.2 ########### SCALE FACTOR PLOT ###############
358     ## If you fit scale factors this part of ##
359     ## will create a plt reading from the ##
360     ## nuisances. All the nuisance cointaning ##
361     ## "SF" in their name will be plotted ##
362     #############################################
363    
364 bortigno 1.1 import numpy
365 bortigno 1.3 if options.plotsf and options.dc:
366 bortigno 1.1 n=0
367     labels=[]
368 bortigno 1.2 v_s=[] # dX/sigma_in values
369     v_b=[] # sigma_out/sigma_in values
370     rho=[] # rho
371     sys=[] # systematics. Not properly filled yet
372     x_position=[] # x position in the plot, basically the SF value
373     y_position=[] # y position in the plot. @TO IMPLEMENT: According to the number of entries per background the spacing is different.
374 bortigno 1.3 #!! loop on all the nuisances
375 bortigno 1.1 for name in names:
376 bortigno 1.3 #!! take only the nuisances which have SF in their name
377 bortigno 1.1 if ('SF' in name ):
378     print name
379     labels.append(name)
380     n+=1
381 bortigno 1.3 #!! take the values
382     #!! the usual order is: dX/sigma_in for background only - sigma_out/sigma_in for background only - dX/sigma_in for background+signal - sigma_out/sigma_in for background+signal - rho
383 bortigno 1.2 v = table[name]
384 bortigno 1.3 #!! forget about the flag
385 bortigno 1.1 v = [ re.sub('!','',i) for i in v ]
386 bortigno 1.3 v = [ re.sub('\*','',i) for i in v ]
387 bortigno 1.1 if pmsub != None: v = [ re.sub(pmsub[0], pmsub[1], i) for i in v ]
388     if sigsub != None: v = [ re.sub(sigsub[0], sigsub[1], i) for i in v ]
389     v_b.append(v[0].split(','))
390     v_s.append(v[1].split(','))
391     rho.append(v[2].split(','))
392     x_position.append(0.)
393 bortigno 1.2 y_position.append(n-1.)
394 bortigno 1.3 sys.append(0.1) #@TO FIX: need to decide how to quote the systematics and where to take them from
395 bortigno 1.2
396     # count the number of different channels
397 bortigno 1.3 channels = [0.,0.,0.,0.,0.]
398     ch={'Zll':0.,'Zll low Pt':0.,'Zll high Pt':0.,'Wln':0.,'Wln low Pt':0.,'Wln high Pt':0.,'Znn':0.,'Znn low Pt':0.,'Znn high Pt':0.,'Znn med Pt':0.}
399 bortigno 1.2 print labels
400     for label in labels:
401 bortigno 1.3 #!! create channel list and labels for legend
402     if label.find('Zll') > 0. :
403     if label.find('lowPt') > 0.:
404     ch['Zll low Pt'] = 1.
405     elif label.find('highPt') > 0.:
406     ch['Zll high Pt'] = 1.
407     else:
408     ch['Zll'] = 1.
409     if label.find('Wln') > 0. :
410     if label.find('lowPt') > 0.:
411     ch['Wln low Pt'] = 1.
412     elif label.find('highPt') > 0.:
413     ch['Wln high Pt'] = 1.
414     else:
415     ch['Wln'] = 1.
416     if label.find('Znunu') > 0. :
417     if label.find('LowPt') > 0.:
418     ch['Znunu low Pt'] = 1.
419     elif label.find('MedPt') > 0.:
420     ch['Znunu med Pt'] = 1.
421     elif label.find('HighPt') > 0.:
422     ch['Znunu high Pt'] = 1.
423     else:
424     ch['Znunu'] = 1.
425    
426 bortigno 1.2 # calculate the shift on the y position
427     shift=0.
428 bortigno 1.3 for channel,active in ch.iteritems(): shift+=active;
429 bortigno 1.2 shift=1./(shift+1)
430 bortigno 1.3
431 bortigno 1.2 #shift the elements in the array
432 bortigno 1.3 # for i in range(0,len(y_position)): y_position[i]+=shift
433    
434     print 'Y_POSITION'
435 bortigno 1.2 print y_position
436 bortigno 1.3 # clean the labels
437     nuisances = labels
438 bortigno 1.2 labels = [re.sub('CMS_vhbb_','',label) for label in labels ]
439     try:
440 bortigno 1.3 labels = [re.sub('_Zll_SF_','',label) for label in labels ]
441     labels = [re.sub('_Wln_SF_','',label) for label in labels ]
442     labels = [re.sub('_SF_Znunu','',label) for label in labels ]
443     labels = [re.sub('lowPt_8TeV','',label) for label in labels ]
444     labels = [re.sub('highPt_8TeV','',label) for label in labels ]
445     labels = [re.sub('medPt_8TeV','',label) for label in labels ]
446     labels = [re.sub('_Zll_lowPt_SF_8TeV','',label) for label in labels ]
447     labels = [re.sub('_Zll_highPt_SF_8TeV','',label) for label in labels ]
448     labels = [re.sub('LowPt_8TeV','',label) for label in labels ]
449     labels = [re.sub('MedPt_8TeV','',label) for label in labels ]
450     labels = [re.sub('HighPt_8TeV','',label) for label in labels ]
451     labels = [re.sub('8TeV','',label) for label in labels ]
452     labels = [re.sub('8TeV','',label) for label in labels ]
453    
454 bortigno 1.2 except:
455     print '@WARNING: No usual naming for datacard scale factors nuisances'
456     print labels
457    
458     #CMS_vhbb_TT_Zll_SF_8TeV ! +0.56, 0.13! ! +0.54, 0.13! -0.00
459     #CMS_vhbb_ZjHF_Zll_SF_8TeV +1.79, 1.14 +1.80, 1.13 +0.00
460     #CMS_vhbb_ZjLF_Zll_SF_8TeV ! +3.51, 0.94! ! +3.42, 0.95! -0.00
461    
462 bortigno 1.1 print n
463     print labels
464     print v_s
465     print v_b
466     print rho
467 bortigno 1.3
468     label_dictionary = {"TT":"t#bar{t}","ZjHF":"Z+bX","ZjLF":"Z+udscg","Zj1HF":"Z+b","Zj2HF":"Z+b#bar{b}","Wj0b":"W+light","Wj1b":"W+b","Wj2b":"W+b#bar{b}","Zj0b":"Z+light","Zj1b":"Z+b","Zj2b":"Z+b#bar{b}","s_Top":"t"}
469 bortigno 1.1 c = ROOT.TCanvas("c","c",600,600)
470    
471 bortigno 1.3 input_sigma = getInputSigma(options)
472     print 'Input sigma'
473     print input_sigma
474    
475     graphs={}
476     j=1
477     for channel,active in ch.iteritems():
478     print channel
479     print active
480     if active > 0.:
481     graphs[channel] = getGraph(channel,labels,j*shift,v_b,input_sigma,x_position,y_position,nuisances) # create the graph with the scale factors
482     j+=1
483    
484     print graphs
485    
486     labels = removeDouble(labels)
487     n= len(labels)
488     h2 = ROOT.TH2F("h2","",1,0.,2.5,n,0,n) # x min - max values.
489 bortigno 1.1 h2.GetXaxis().SetTitle("Scale factor")
490    
491     for i in range(n):
492 bortigno 1.2 h2.GetYaxis().SetBinLabel(i+1,label_dictionary[labels[i]])
493 bortigno 1.1
494 bortigno 1.3
495     drawSys=False
496     if(drawSys):
497     #for the moment just random systematics
498     sys_e = numpy.array(sys)
499     #!! Create the graph for the systematics, if any. It will show only error brackets, no points
500     g2 = ROOT.TGraphErrors(n,d,p,sys_e,zero)
501     g2.SetFillColor(0)
502     g2.SetLineWidth(3);
503 bortigno 1.1
504     h2.Draw(); ROOT.gStyle.SetOptStat(0);
505     h2.GetXaxis().SetTitleSize(0.04);
506     h2.GetXaxis().SetLabelSize(0.04);
507     h2.GetYaxis().SetLabelSize(0.06);
508     #h2.SetFillStyle(4000)
509     c.SetFillStyle(4000)
510    
511     globalFitBand = ROOT.TBox(1.0, 0., 1.5, n);
512     globalFitBand.SetFillStyle(3013);
513     globalFitBand.SetFillColor(65);
514     globalFitBand.SetLineStyle(0);
515     #globalFitBand.Draw("same");
516 bortigno 1.2 globalFitLine = ROOT.TLine(1.0, 0., 1.0, n);
517 bortigno 1.1 globalFitLine.SetLineWidth(2);
518     globalFitLine.SetLineColor(214);#214
519     globalFitLine.Draw("same");
520 bortigno 1.3
521     #!! Legend
522     l2 = ROOT.TLegend(0.60, 0.85,0.80,0.67)
523 bortigno 1.1 l2.SetLineWidth(2)
524     l2.SetBorderSize(0)
525     l2.SetFillColor(0)
526     l2.SetFillStyle(4000)
527     l2.SetTextFont(62)
528 bortigno 1.3 for channel,g in graphs.iteritems():
529     print channel
530     l2.AddEntry(g,channel,"pl")
531     #l2.AddEntry(g,"Stat.","l")
532     if(drawSys) : l2.AddEntry(g2,"Syst.","l")
533 bortigno 1.1 l2.SetTextSize(0.035)
534 bortigno 1.3 # l2.SetNColumns(3)
535 bortigno 1.1 l2.Draw("same")
536 bortigno 1.3
537     for channel,g in graphs.iteritems(): print channel; g.Draw("P same")
538     if(drawSys) : g2.Draw("[] same")
539 bortigno 1.1 ROOT.gPad.SetLeftMargin(0.2)
540     ROOT.gPad.Update()
541     c.Print("histo.pdf")
542    
543 bortigno 1.3
544    
545    
546