ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/VHbb/python/scaleFactorPlot.py
Revision: 1.5
Committed: Fri Apr 5 14:28:28 2013 UTC (12 years, 1 month ago) by bortigno
Content type: text/x-python
Branch: MAIN
CVS Tags: lhcp_UnblindFix, hcp_Unblind, lhcp_11April, LHCP_PreAppFixAfterFreeze, HEAD
Changes since 1.4: +27 -5 lines
Log Message:
@UPDATE style

File Contents

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