ra4_macros  bede988c286599a3a84b77a4d788ac0a971e89f9
rpv_sig_syst.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 """This script plots signal systematics for the RPV analysis"""
3 import sys
4 import math
5 import ROOT
6 from array import array
7 import argparse
8 parser = argparse.ArgumentParser()
9 parser.add_argument("-i", "--input")
10 parser.add_argument("-m", "--mass")
11 args = parser.parse_args()
12 GLUINOMASS = 1200
13 if (args.input):
14  infile = args.input
15 else:
16  sys.exit("Please provide an input root file")
17 if (args.mass):
18  GLUINOMASS = args.mass
19 
20 one_pdf = False #put all plots in one pdf file
21 verbose = True
22 
23 
24 # function to get pointers to histogram in root file
25 def get_hist_with_overflow(file,histname):
26  if verbose:
27  print" getting "+histname
28  hist = file.Get(histname)
29  nbinsX = hist.GetNbinsX()
30  content = hist.GetBinContent(nbinsX) + hist.GetBinContent(nbinsX+1)
31  error = math.sqrt(math.pow(hist.GetBinError(nbinsX),2) + math.pow(hist.GetBinError(nbinsX+1),2))
32  hist.SetBinContent(nbinsX,content)
33  hist.SetBinContent(nbinsX+1,0) #avoid adding overflow N times for N calls to function
34  hist.SetBinError(nbinsX+1,0)
35  hist.SetBinError(nbinsX,error)
36  return hist
37 
38 #This function calculates symmetrized relative errors for a single variation in a single kinematic bin
39 #Return a histogram binned in Nb with the mean of the absolute value of relative errors up and down
40 def get_symmetrized_relative_errors(sysName,nominal,proc,sysFile,directory):
41 
42 
43  # total hists for each variation, to include all processes
44  systHistUp = ROOT.TH1F(directory+"_"+sysName+"_u","",5,0,5)
45  systHistDown = ROOT.TH1F(directory+"_"+sysName+"_d","",5,0,5)
46 
47 
48  #load hists and calculate SFs for floating component for each variation
49 
50  up = get_hist_with_overflow(sysFile,directory + "/" + proc + "_" + sysName + "Up")
51  down = get_hist_with_overflow(sysFile,directory + "/" + proc + "_" + sysName + "Down")
52 
53 
54  #Put yields in new histogram to avoid modifying originals
55  systHistUp.Add(up)
56  systHistDown.Add(down)
57 
58  #Subtract nominal histogram from varied histograms
59  systHistUp.Add(nominal,-1)
60  systHistDown.Add(nominal,-1)
61 
62  for i in range(1,systHistUp.GetNbinsX()+1):
63  #Find absolute value of deviation
64  systHistUp.SetBinContent(i,abs(systHistUp.GetBinContent(i)))
65  systHistDown.SetBinContent(i,abs(systHistDown.GetBinContent(i)))
66 
67  #Fill histUp with symmetrized error by adding histDown and dividing by 2, then divide by nominal to get relative symmetrized error
68  systHistUp.Add(systHistDown)
69  systHistUp.Scale(0.5)
70  systHistUp.Divide(nominal) # now systHistUp contains our relative errors
71  return systHistUp
72 
73 def set_palette_gray(ncontours=20):
74  #stops = [0.00, 0.25, 0.50, 0.75, 1.00]
75  stops = [0.00, 0.10, 0.50, 0.90, 1.00]
76  red = [1.00, 0.80, 0.65, 0.50, 0.34]
77  green = [1.00, 0.80, 0.65, 0.50, 0.34]
78  blue = [1.00, 0.80, 0.65, 0.50, 0.34]
79  s = array('d', stops)
80  r = array('d', red)
81  g = array('d', green)
82  b = array('d', blue)
83  npoints = len(s)
84  fi = ROOT.TColor.CreateGradientColorTable(npoints, s, r, g, b, ncontours)
85  ROOT.gStyle.SetNumberContours(ncontours)
86 
87 
88 ROOT.gROOT.SetBatch(ROOT.kTRUE) #prevent th1->Draw() from trying to open X11 window
89 ROOT.gStyle.SetCanvasDefW(600)
90 ROOT.gStyle.SetCanvasDefH(600)
91 ROOT.gStyle.SetTitleOffset(1.2,"x")
92 #ROOT.gStyle.SetTitleOffset(1.7,"y")
93 ROOT.gStyle.SetTitleOffset(1.7,"z")
94 #ROOT.gStyle.SetPadRightMargin(0.19)
95 ROOT.gStyle.SetPadLeftMargin(0.12)
96 ROOT.gStyle.SetPadBottomMargin(0.12)
97 ROOT.gStyle.SetPadTopMargin(0.08)
98 ROOT.gStyle.SetPaintTextFormat("6.1f");
99 
100 
101 ROOT.gStyle.SetLabelFont(42)
102 ROOT.gStyle.SetLabelSize(0.05)
103 ROOT.gStyle.SetTitleFont(42)
104 ROOT.gStyle.SetTitleSize(0.07)
105 
106 #set_palette()
108 
109 #make list of systematics- name, title, plot color and line style
110 systList=[]
111 systList.append(["fs_btag_bc","FastSim b,c jet b-tag SF",2,1])
112 systList.append(["fs_btag_udsg","FastSim u,d,s,g jet b-tag SF",3,1])
113 systList.append(["fs_lep_eff","FastSim lepton efficiency",4,1])
114 systList.append(["btag_bc","b,c jet b-tag SF",5,1])
115 systList.append(["btag_udsg","u,d,s,g jet b-tag SF",6,1])
116 systList.append(["jes","Jet energy scale",7,1])
117 systList.append(["jer","Jet energy resolution",8,1])
118 systList.append(["lep_eff","Lepton efficiency",9,1])
119 systList.append(["pileup","Pileup",10,1])
120 systList.append(["isr","Initial state radiation",11,1])
121 systList.append(["gs45","Gluon splitting (N_{jet}=4,5)",12,1])
122 systList.append(["gs67","Gluon splitting (N_{jet}=6,7)",13,1])
123 systList.append(["gs89","Gluon splitting (N_{jet}=8,9)",14,1])
124 systList.append(["gs10Inf","Gluon splitting (N_{jet}#geq10)",15,1])
125 systList.append(["signal_mur","Renormalization scale",16,1])
126 systList.append(["signal_muf","Factorization scale",17,1])
127 systList.append(["signal_murf","Renorm. and fact. scale",18,1])
128 systList.append(["pdf","PDF",19,1])
129 systList.append(["mc_stat","MC statistics",1,2]) #must be done last!
130 
131 nSyst = len(systList)
132 #make list of bins
133 
134 binList = []
135 binList.append(["bin0","4 #leq n_{jets} #leq 5","500 #leq M_{J} < 800 GeV","n_{lep} = 0"])
136 binList.append(["bin1","6 #leq n_{jets} #leq 7","500 #leq M_{J} < 800 GeV","n_{lep} = 0"])
137 binList.append(["bin2","4 #leq n_{jets} #leq 5","500 #leq M_{J} < 800 GeV","n_{lep} = 1"])
138 binList.append(["bin3","4 #leq n_{jets} #leq 5","M_{J} #geq 800 GeV","n_{lep} = 0"])
139 binList.append(["bin4","6 #leq n_{jets} #leq 7","M_{J} #geq 800 GeV","n_{lep} = 0"])
140 binList.append(["bin5","4 #leq n_{jets} #leq 5","M_{J} #geq 800 GeV","n_{lep} = 1"])
141 #
142 #binList.append(["bin6","4 #leq n_{jets} #leq 5","300 #leq M_{J} < 500 GeV","n_{lep} = 0"])
143 #binList.append(["bin7","6 #leq n_{jets} #leq 7","300 #leq M_{J} < 500 GeV","n_{lep} = 0"])
144 #binList.append(["bin8","8 #leq n_{jets} #leq 9","300 #leq M_{J} < 500 GeV","n_{lep} = 0"])
145 #binList.append(["bin9","n_{jets} #geq 10","300 #leq M_{J} < 500 GeV","n_{lep} = 0"])
146 # signal regions
147 binList.append(["bin10","n_{jets} #geq 10","500 #leq M_{J} < 800 GeV","n_{lep} = 0"])
148 binList.append(["bin11","6 #leq n_{jets} #leq 7","500 #leq M_{J} < 800 GeV","n_{lep} = 1"])
149 binList.append(["bin12","n_{jets} #geq 8","500 #leq M_{J} < 800 GeV","n_{lep} = 1"])
150 binList.append(["bin13","n_{jets} #geq 10","M_{J} #geq 800 GeV","n_{lep} = 0"])
151 binList.append(["bin14","6 #leq n_{jets} #leq 7","M_{J} #geq 800 GeV","n_{lep} = 1"])
152 binList.append(["bin15","n_{jets} #geq 8","M_{J} #geq 800 GeV","n_{lep} = 1"])
153 binList.append(["bin16","8 #leq n_{jets} #leq 9","500 #leq M_{J} < 800 GeV","n_{lep} = 0"])
154 binList.append(["bin17","8 #leq n_{jets} #leq 9","M_{J} #geq 800 GeV","n_{lep} = 0"])
155 
156 
157 sysFile = ROOT.TFile(infile,"read")
158 proc = "signal_M" + str(GLUINOMASS)
159 
160 for ibin in binList:
161 
162  directory = ibin[0]
163  if verbose:
164  print "directory is "+directory
165 
166  nominal = get_hist_with_overflow(sysFile,(directory + "/" + proc))
167  nbinsX = nominal.GetNbinsX()
168 
169 
170  ROOT.gStyle.SetPadRightMargin()
171  ROOT.gStyle.SetPadLeftMargin(0.12) #so it's not messed by larger table margin each iteration of the loop
172  c = ROOT.TCanvas()
173  leg = ROOT.TLegend(0.12,0.7,0.54,0.92)
174 
175  table = ROOT.TH2F("table_"+directory,"",nbinsX,-0.5,nbinsX-0.5,nSyst,0,nSyst)
176  systHists_sym = []
177 
178 
179  for isys, syst in enumerate(systList,start=1):
180  sysName = syst[0]
181  systHist = ROOT.TH1F(directory+"_"+sysName+"_sym","",5,0,5) # will eventually contain errors; define now to remain in scope
182  if verbose:
183  print "starting "+sysName
184 
185  if "mc_stat" not in sysName:
186  #pdf treated separately
187  if "pdf" not in sysName:
188  #this function does everything
189  systHist = get_symmetrized_relative_errors(sysName,nominal,proc,sysFile,directory)
190 
191 
192  elif "pdf" in sysName:
193  #This systematic is calculated from 100 variations that all represent a single source of uncertainty.
194  #We want to use information from all variations without artifically inflating the total uncertainty just by sampling the same effect many times.
195  #Therefore, we find symmetrized uncertainties for each pdf variation up/down, add them in quadrature and divide by sqrt(100) to normalize
196  for i in range(0,100):
197  #if i == 9 : continue
198  #Get errors for this pdf variation
199  thisvar = get_symmetrized_relative_errors("w_pdf"+str(i),nominal,proc,sysFile,directory)
200  #Add in quadrature to running total
201  for i in range(1,systHist.GetNbinsX()+1):
202  thisvar.SetBinContent(i,math.pow(thisvar.GetBinContent(i),2))
203  systHist.Add(thisvar)
204 
205  #take square root and normalize by sqrt(100)
206  for i in range(1,systHist.GetNbinsX()+1):
207  systHist.SetBinContent(i,math.pow(systHist.GetBinContent(i),0.5)/10)
208 
209 
210  elif "mc_stat" in sysName:
211  systHist.Add(nominal)
212  for i in range(1,systHist.GetNbinsX()+1):
213  #in this case, we want our relative errors to just be the MC errors
214  if systHist.GetBinContent(i)>0:
215  systHist.SetBinContent(i,(systHist.GetBinError(i)/systHist.GetBinContent(i)))
216 
217  #normalize to percentage for humans
218  for i in range(1,systHist.GetNbinsX()+1):
219  if systHist.GetBinContent(i) < 0.001:
220  table.SetBinContent(i,isys,0.04)
221  else:
222  table.SetBinContent(i,isys,round(100*systHist.GetBinContent(i),1))
223  if verbose:
224  print "symmetrized rel error bin "+str(i)+" "+str(systHist.GetBinContent(i))
225 
226 
227 
228  systHists_sym.append(systHist)
229 
230 
231  table.GetYaxis().SetBinLabel(isys,syst[1])
232  systHists_sym[isys-1].SetTitle(";N_{b};Relative Error")
233  systHists_sym[isys-1].SetLineColor(syst[2])
234  systHists_sym[isys-1].SetLineStyle(syst[3])
235  systHists_sym[isys-1].SetLineWidth(2)
236  systHists_sym[isys-1].SetMaximum(0.4)
237  systHists_sym[isys-1].SetMinimum(0.)
238  systHists_sym[isys-1].SetAxisRange(1,4,"X")
239  systHists_sym[isys-1].SetStats(0)
240  systHists_sym[isys-1].GetYaxis().SetTitleOffset(1.4)
241  systHists_sym[isys-1].GetYaxis().SetTitleSize(0.04)
242  systHists_sym[isys-1].GetXaxis().SetTitleSize(0.04)
243  systHists_sym[isys-1].GetXaxis().SetNdivisions(505)
244  leg.AddEntry(systHists_sym[isys-1],syst[1],"l")
245  systHists_sym[isys-1].Draw("hist same")
246 
247 
248 
249  leg.Draw()
250  tla = ROOT.TLatex()
251  tla.SetTextSize(0.038)
252  tla.DrawLatexNDC(0.12,0.93,"#font[62]{CMS} #scale[0.8]{#font[52]{Simulation}}")
253  tla.SetTextFont(42)
254  tla.DrawLatexNDC(0.71,0.93,"#sqrt{s} = 13 TeV")
255 # tla.SetTextSize(0.045)
256  tla.DrawLatexNDC(0.17, 0.65, ibin[3])
257  tla.DrawLatexNDC(0.17, 0.6, ibin[1])
258  tla.DrawLatexNDC(0.17, 0.55, ibin[2])
259  if one_pdf:
260  if directory == binList[0][0]:
261  outname = "plots/sig_systs_all_m" + str(GLUINOMASS) + ".pdf("
262  elif directory == binList[len(binList)-1][0]:
263  outname = "plots/sig_systs_all_m" + str(GLUINOMASS) + ".pdf)"
264  else:
265  outname = "plots/sig_systs_all_m" + str(GLUINOMASS) + ".pdf"
266 
267  else:
268  outname = "plots/sig_systs_" + directory + "_m" + str(GLUINOMASS) + ".pdf"
269  print "outname is " +outname
270  c.Print(outname)
271 
272 
273  ROOT.gStyle.SetPadLeftMargin(0.35)
274  ROOT.gStyle.SetPadRightMargin(0.2)
275  ROOT.gStyle.SetPadBottomMargin(0.1)
276  c2 = ROOT.TCanvas()
277  table.GetXaxis().SetBinLabel(1,"0");
278  table.GetXaxis().SetBinLabel(2,"1");
279  table.GetXaxis().SetBinLabel(3,"2");
280  table.GetXaxis().SetBinLabel(4,"3");
281  table.GetXaxis().SetBinLabel(5,"#geq 4");
282  table.GetXaxis().SetNdivisions(400,0)
283  table.SetMaximum(20)
284  table.SetMinimum(0)
285  table.SetStats(0)
286  table.SetMarkerSize(1.5)
287  table.SetAxisRange(0.5,4.499,"X")
288  table.SetXTitle("N_{b}")
289  table.SetZTitle("Uncertainty [%]")
290  table.GetYaxis().SetTitleOffset(1.4)
291  table.GetYaxis().SetTitleSize(0.054)
292  table.GetYaxis().SetLabelSize(0.045)
293  table.GetXaxis().SetTitleSize(0.04)
294  table.Draw("colz text")
295  ROOT.gPad.SetTicks(1,0)
296  table.Draw("axis y+ same")
297  tla = ROOT.TLatex()
298  tla.SetTextSize(0.038)
299  tla.DrawLatexNDC(0.35,0.93,"#font[62]{CMS} #scale[0.8]{#font[52]{Simulation}}")
300  tla.SetTextFont(42)
301  tla.DrawLatexNDC(0.66,0.93,"#sqrt{s} = 13 TeV")
302  if one_pdf:
303  if directory == binList[0][0]:
304  outname = "plots/table_sig_systs_all_m" + str(GLUINOMASS) + ".pdf("
305  elif directory == binList[len(binList)-1][0]:
306  outname = "plots/table_sig_systs_all_m" + str(GLUINOMASS) + ".pdf)"
307  else:
308  outname = "plots/table_sig_systs_all_m" + str(GLUINOMASS) + ".pdf"
309 
310  else:
311  outname = "plots/table_sig_systs_" + directory + "_m" + str(GLUINOMASS) + ".pdf"
312 
313 
314  c2.Print(outname)
315 
316 
317 
318 
319 
320 
def set_palette_gray(ncontours=20)
Definition: rpv_sig_syst.py:73
def get_hist_with_overflow(file, histname)
Definition: rpv_sig_syst.py:25
def get_symmetrized_relative_errors(sysName, nominal, proc, sysFile, directory)
Definition: rpv_sig_syst.py:40