ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/VHbb/python/stack_from_dc.py
Revision: 1.13
Committed: Tue Dec 11 17:59:25 2012 UTC (12 years, 5 months ago) by bortigno
Content type: text/x-python
Branch: MAIN
Changes since 1.12: +12 -10 lines
Log Message:
fix help functionality

File Contents

# User Rev Content
1 nmohr 1.1 #!/usr/bin/env python
2     import pickle
3 bortigno 1.13
4 nmohr 1.1 from BetterConfigParser import BetterConfigParser
5     import sys, os
6     from optparse import OptionParser
7    
8     #CONFIGURE
9     argv = sys.argv
10     parser = OptionParser()
11     parser.add_option("-D", "--datacard", dest="dc", default="",
12     help="Datacard to be plotted")
13     parser.add_option("-B", "--bin", dest="bin", default="",
14     help="DC bin to plot")
15     parser.add_option("-M", "--mlfit", dest="mlfit", default="",
16     help="mlfit file for nuisances")
17     parser.add_option("-F", "--fitresult", dest="fit", default="s",
18     help="Fit result to be used, 's' (signal+background) or 'b' (background only), default is 's'")
19     parser.add_option("-C", "--config", dest="config", default=[], action="append",
20     help="configuration file")
21     (opts, args) = parser.parse_args(argv)
22    
23 bortigno 1.13 from copy import copy,deepcopy
24     from StackMaker import StackMaker
25     from math import sqrt
26     import math
27     from HiggsAnalysis.CombinedLimit.DatacardParser import *
28     from HiggsAnalysis.CombinedLimit.ShapeTools import *
29     import ROOT
30     ROOT.gROOT.SetBatch(True)
31     ROOT.gSystem.Load("libHiggsAnalysisCombinedLimit.so")
32    
33    
34 nmohr 1.1
35     def readBestFit(theFile):
36     file = ROOT.TFile(theFile)
37 nmohr 1.4 if file == None: raise RuntimeError, "Cannot open file %s" % theFile
38 nmohr 1.1 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     nuiVariation = {}
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     if nuis_p != None:
56     mean_p, sigma_p = (nuis_p.getVal(), nuis_p.getError())
57     for fit_name, nuis_x in [('b', nuis_b), ('s',nuis_s)]:
58     if nuis_p != None:
59     valShift = (nuis_x.getVal() - mean_p)/sigma_p
60     #sigShift = nuis_x.getError()/sigma_p
61     print fit_name, name
62     print valShift
63     nuiVariation['%s_%s'%(fit_name,name)] = valShift
64     #print valShift
65     return nuiVariation
66    
67 nmohr 1.6 def getBestFitShapes(procs,theShapes,shapeNui,theBestFit,DC,setup,opts,Dict):
68 nmohr 1.4 b = opts.bin
69     for p in procs:
70     counter = 0
71     nom = theShapes[p].Clone()
72     for (lsyst,nofloat,pdf,pdfargs,errline) in DC.systs:
73     if errline[b][p] == 0: continue
74 nmohr 1.11 if ("shape" in pdf):
75     if shapeNui[p+lsyst] > 0.:
76 nmohr 1.4 theVari = 'Up'
77     else:
78     theVari = 'Down'
79     bestNuiVar = theShapes[p+lsyst+theVari].Clone()
80     bestNuiVar.Add(nom,-1.)
81 nmohr 1.11 #print p,lsyst,abs(shapeNui[p+lsyst]),bestNuiVar.Integral()
82     bestNuiVar.Scale(abs(shapeNui[p+lsyst]))
83 nmohr 1.4 if counter == 0:
84     bestNui = bestNuiVar.Clone()
85     else:
86     bestNui.Add(bestNuiVar)
87     counter +=1
88 nmohr 1.10 nom.Add(bestNui)
89 nmohr 1.6 #nom.Scale(theBestFit[p])
90     nom.Scale(theShapes[p].Integral()/nom.Integral()*theBestFit[p])
91 nmohr 1.4 nBins = nom.GetNbinsX()
92     for bin in range(1,nBins+1):
93     nom.SetBinError(bin,theShapes[p].GetBinError(bin))
94     theShapes['%s_%s'%(opts.fit,p)] = nom.Clone()
95     histos = []
96     typs = []
97 nmohr 1.8 sigCount = 0
98 nmohr 1.4 for s in setup:
99 nmohr 1.8 if 'ZH' == s or 'WH' == s:
100     if sigCount ==0:
101     Overlay=copy(theShapes[Dict[s]])
102     else:
103     Overlay.Add(theShapes[Dict[s]])
104     sigCount += 1
105 nmohr 1.4 else:
106     histos.append(theShapes['%s_%s'%(opts.fit,Dict[s])])
107     typs.append(s)
108 nmohr 1.8 return histos,Overlay,typs
109 nmohr 1.4
110 nmohr 1.1
111     def drawFromDC():
112     config = BetterConfigParser()
113     config.read(opts.config)
114 nmohr 1.8 dataname = ''
115     if 'Zmm' in opts.bin: dataname = 'Zmm'
116     elif 'Zee' in opts.bin: dataname = 'Zee'
117 nmohr 1.9 elif 'Wmunu' in opts.bin: dataname = 'Wmn'
118     elif 'Wenu' in opts.bin: dataname = 'Wen'
119 nmohr 1.8 elif 'Znunu' in opts.bin: dataname = 'Znn'
120    
121     var = 'BDT'
122     if dataname == 'Zmm' or dataname == 'Zee': var = 'BDT_Zll'
123     elif dataname == 'Wmn' or dataname == 'Wen': var = 'BDT_Wln'
124     elif dataname == 'Znn':
125     if 'HighPt' in opts.bin: var = 'BDT_ZnnHighPt'
126     if 'LowPt' in opts.bin: var = 'BDT_ZnnLowPt'
127     if 'LowCSV' in opts.bin: var = 'BDT_ZnnLowCSV'
128     if dataname == '' or var == 'BDT': raise RuntimeError, "Did not recognise mode or var from %s" % opts.bin
129    
130 nmohr 1.1 region = 'BDT'
131     ws_var = config.get('plotDef:%s'%var,'relPath')
132 nmohr 1.12 ws_var = ROOT.RooRealVar(ws_var,ws_var,-1.,1.)
133 nmohr 1.1 blind = eval(config.get('Plot:%s'%region,'blind'))
134     Stack=StackMaker(config,var,region,True)
135    
136 nmohr 1.4 preFit = False
137 nmohr 1.6 addName = 'PostFit_%s' %(opts.fit)
138 nmohr 1.4 if not opts.mlfit:
139 nmohr 1.6 addName = 'PreFit'
140 nmohr 1.4 preFit = True
141    
142 nmohr 1.6 Stack.options[6] = '%s_%s_%s.pdf' %(var,opts.bin,addName)
143    
144 nmohr 1.1 log = eval(config.get('Plot:%s'%region,'log'))
145    
146     setup = config.get('Plot_general','setup').split(',')
147 nmohr 1.8 if dataname == 'Zmm' or dataname == 'Zee':
148     setup.remove('Wb')
149     setup.remove('Wlight')
150     setup.remove('WH')
151 nmohr 1.1 Dict = eval(config.get('LimitGeneral','Dict'))
152     lumi = eval(config.get('Plot_general','lumi'))
153    
154     options = copy(opts)
155     options.dataname = "data_obs"
156     options.mass = 0
157     options.format = "%8.3f +/- %6.3f"
158 nmohr 1.2 options.channel = opts.bin
159 nmohr 1.1 options.excludeSyst = []
160     options.norm = False
161     options.stat = False
162     options.bin = True # fake that is a binary output, so that we parse shape lines
163     options.out = "tmp.root"
164     options.fileName = args[0]
165     options.cexpr = False
166     options.fixpars = False
167     options.libs = []
168     options.verbose = 0
169     options.poisson = 0
170     options.nuisancesToExclude = []
171     options.noJMax = None
172 nmohr 1.12 theBinning = ROOT.RooFit.Binning(Stack.nBins,Stack.xMin,Stack.xMax)
173 nmohr 1.1
174     file = open(opts.dc, "r")
175     os.chdir(os.path.dirname(opts.dc))
176     DC = parseCard(file, options)
177     if not DC.hasShapes: DC.hasShapes = True
178     MB = ShapeBuilder(DC, options)
179     theShapes = {}
180     theSyst = {}
181 nmohr 1.4 nuiVar = {}
182 nmohr 1.1 if opts.mlfit:
183     nuiVar = readBestFit(opts.mlfit)
184 nmohr 1.8 if not opts.bin in DC.bins: raise RuntimeError, "Cannot open find %s in bins %s of %s" % (opts.bin,DC.bins,opts.dc)
185 nmohr 1.1 for b in DC.bins:
186     if options.channel != None and (options.channel != b): continue
187     exps = {}
188     expNui = {}
189     shapeNui = {}
190     for (p,e) in DC.exp[b].items(): # so that we get only self.DC.processes contributing to this bin
191     exps[p] = [ e, [] ]
192     expNui[p] = [ e, [] ]
193     for (lsyst,nofloat,pdf,pdfargs,errline) in DC.systs:
194     if pdf in ('param', 'flatParam'): continue
195     # begin skip systematics
196     skipme = False
197     for xs in options.excludeSyst:
198     if re.search(xs, lsyst):
199     skipme = True
200     if skipme: continue
201     # end skip systematics
202     counter = 0
203     for p in DC.exp[b].keys(): # so that we get only self.DC.processes contributing to this bin
204     if errline[b][p] == 0: continue
205 nmohr 1.7 if p == 'QCD': continue
206 nmohr 1.1 if pdf == 'gmN':
207     exps[p][1].append(1/sqrt(pdfargs[0]+1));
208     elif pdf == 'gmM':
209     exps[p][1].append(errline[b][p]);
210     elif type(errline[b][p]) == list:
211     kmax = max(errline[b][p][0], errline[b][p][1], 1.0/errline[b][p][0], 1.0/errline[b][p][1]);
212     exps[p][1].append(kmax-1.);
213     elif pdf == 'lnN':
214     exps[p][1].append(max(errline[b][p], 1.0/errline[b][p])-1.);
215     if not nuiVar.has_key('%s_%s'%(opts.fit,lsyst)):
216     nui = 0.
217     else:
218     nui= nuiVar['%s_%s'%(opts.fit,lsyst)]
219     expNui[p][1].append(abs(1-errline[b][p])*nui);
220 nmohr 1.11 elif ("shape" in pdf):
221 nmohr 1.7 #print 'shape %s %s: %s'%(pdf,p,lsyst)
222 nmohr 1.1 s0 = MB.getShape(b,p)
223     sUp = MB.getShape(b,p,lsyst+"Up")
224     sDown = MB.getShape(b,p,lsyst+"Down")
225     if (s0.InheritsFrom("RooDataHist")):
226 nmohr 1.12 s0 = ROOT.RooAbsData.createHistogram(s0,p,ws_var,theBinning)
227 nmohr 1.1 s0.SetName(p)
228 nmohr 1.12 sUp = ROOT.RooAbsData.createHistogram(sUp,p+lsyst+'Up',ws_var,theBinning)
229 nmohr 1.1 sUp.SetName(p+lsyst+'Up')
230 nmohr 1.12 sDown = ROOT.RooAbsData.createHistogram(sDown,p+lsyst+'Down',ws_var,theBinning)
231 nmohr 1.1 sDown.SetName(p+lsyst+'Down')
232     theShapes[p] = s0.Clone()
233     theShapes[p+lsyst+'Up'] = sUp.Clone()
234     theShapes[p+lsyst+'Down'] = sDown.Clone()
235     if not nuiVar.has_key('%s_%s'%(opts.fit,lsyst)):
236     nui = 0.
237     else:
238     nui= nuiVar['%s_%s'%(opts.fit,lsyst)]
239 nmohr 1.11 shapeNui[p+lsyst] = nui
240     if not 'CMS_vhbb_stat' in lsyst:
241     if counter == 0:
242     theSyst[lsyst] = s0.Clone()
243     theSyst[lsyst+'Up'] = sUp.Clone()
244     theSyst[lsyst+'Down'] = sDown.Clone()
245     else:
246     theSyst[lsyst].Add(s0)
247     theSyst[lsyst+'Up'].Add(sUp.Clone())
248     theSyst[lsyst+'Down'].Add(sDown.Clone())
249     counter += 1
250    
251 nmohr 1.1 procs = DC.exp[b].keys(); procs.sort()
252 nmohr 1.7 if 'QCD' in procs:
253     procs.remove('QCD')
254 nmohr 1.1 fmt = ("%%-%ds " % max([len(p) for p in procs]))+" "+options.format;
255     #Compute norm uncertainty and best fit
256     theNormUncert = {}
257     theBestFit = {}
258     for p in procs:
259     relunc = sqrt(sum([x*x for x in exps[p][1]]))
260     print fmt % (p, exps[p][0], exps[p][0]*relunc)
261     theNormUncert[p] = relunc
262     absBestFit = sum([x for x in expNui[p][1]])
263     theBestFit[p] = 1.+absBestFit
264    
265     histos = []
266     typs = []
267    
268     setup2=copy(setup)
269    
270     shapesUp = [[] for _ in range(0,len(setup2))]
271     shapesDown = [[] for _ in range(0,len(setup2))]
272    
273 nmohr 1.8 sigCount = 0
274 nmohr 1.1 for p in procs:
275 nmohr 1.2 b = opts.bin
276 nmohr 1.1 for s in setup:
277     if not Dict[s] == p: continue
278 nmohr 1.8 if 'ZH' == s or 'WH' == s:
279     if sigCount ==0:
280     Overlay=copy(theShapes[Dict[s]])
281     else:
282     Overlay.Add(theShapes[Dict[s]])
283     sigCount += 1
284 nmohr 1.1 else:
285     histos.append(theShapes[Dict[s]])
286     typs.append(s)
287     for (lsyst,nofloat,pdf,pdfargs,errline) in DC.systs:
288     if errline[b][p] == 0: continue
289 nmohr 1.7 if ("shape" in pdf) and not 'CMS_vhbb_stat' in lsyst:
290 nmohr 1.1 print 'syst %s'%lsyst
291     shapesUp[setup2.index(s)].append(theShapes[Dict[s]+lsyst+'Up'])
292     shapesDown[setup2.index(s)].append(theShapes[Dict[s]+lsyst+'Down'])
293    
294     #-------------
295     #Compute absolute uncertainty from shapes
296     counter = 0
297     for (lsyst,nofloat,pdf,pdfargs,errline) in DC.systs:
298 nmohr 1.11 sumErr = 0
299     for p in procs:
300     sumErr += errline[b][p]
301     if ("shape" in pdf) and not 'CMS_vhbb_stat' in lsyst and not sumErr == 0:
302 nmohr 1.1 theSystUp = theSyst[lsyst+'Up'].Clone()
303     theSystUp.Add(theSyst[lsyst].Clone(),-1.)
304     theSystUp.Multiply(theSystUp)
305     theSystDown = theSyst[lsyst+'Down'].Clone()
306     theSystDown.Add(theSyst[lsyst].Clone(),-1.)
307     theSystDown.Multiply(theSystDown)
308     if counter == 0:
309     theAbsSystUp = theSystUp.Clone()
310     theAbsSystDown = theSystDown.Clone()
311     else:
312     theAbsSystUp.Add(theSystUp.Clone())
313     theAbsSystDown.Add(theSystDown.Clone())
314     counter +=1
315    
316     #-------------
317     #Best fit for shapes
318 nmohr 1.4 if not preFit:
319 nmohr 1.8 histos, Overlay, typs = getBestFitShapes(procs,theShapes,shapeNui,theBestFit,DC,setup,opts,Dict)
320 nmohr 1.1
321     counter = 0
322     errUp=[]
323     total=[]
324     errDown=[]
325     nBins = histos[0].GetNbinsX()
326     print 'total bins %s'%nBins
327     Error = ROOT.TGraphAsymmErrors(histos[0])
328     theTotalMC = histos[0].Clone()
329     for h in range(1,len(histos)):
330     theTotalMC.Add(histos[h])
331    
332     total = [[]]*nBins
333     errUp = [[]]*nBins
334     errDown = [[]]*nBins
335     for bin in range(1,nBins+1):
336     binError = theTotalMC.GetBinError(bin)
337     if math.isnan(binError):
338     binError = 0.
339     total[bin-1]=theTotalMC.GetBinContent(bin)
340     #Stat uncertainty of the MC outline
341     errUp[bin-1] = [binError]
342     errDown[bin-1] = [binError]
343     #Relative norm uncertainty of the individual MC
344     for h in range(0,len(histos)):
345     errUp[bin-1].append(histos[h].GetBinContent(bin)*theNormUncert[histos[h].GetName()])
346     errDown[bin-1].append(histos[h].GetBinContent(bin)*theNormUncert[histos[h].GetName()])
347     #Shape uncertainty of the MC
348     for bin in range(1,nBins+1):
349     #print sqrt(theSystUp.GetBinContent(bin))
350     errUp[bin-1].append(sqrt(theAbsSystUp.GetBinContent(bin)))
351     errDown[bin-1].append(sqrt(theAbsSystDown.GetBinContent(bin)))
352    
353    
354     #Add all in quadrature
355     totErrUp=[sqrt(sum([x**2 for x in bin])) for bin in errUp]
356     totErrDown=[sqrt(sum([x**2 for x in bin])) for bin in errDown]
357    
358     #Make TGraph with errors
359     for bin in range(1,nBins+1):
360     if not total[bin-1] == 0:
361     point=histos[0].GetXaxis().GetBinCenter(bin)
362     Error.SetPoint(bin-1,point,1)
363     Error.SetPointEYlow(bin-1,totErrDown[bin-1]/total[bin-1])
364     print 'down %s'%(totErrDown[bin-1]/total[bin-1])
365     Error.SetPointEYhigh(bin-1,totErrUp[bin-1]/total[bin-1])
366     print 'up %s'%(totErrUp[bin-1]/total[bin-1])
367    
368     #-----------------------
369     #Read data
370 nmohr 1.2 data0 = MB.getShape(opts.bin,'data_obs')
371 nmohr 1.1 if (data0.InheritsFrom("RooDataHist")):
372 nmohr 1.12 data0 = ROOT.RooAbsData.createHistogram(data0,'data_obs',ws_var,theBinning)
373 nmohr 1.1 data0.SetName('data_obs')
374     datas=[data0]
375     datatyps = [None]
376     datanames=[dataname]
377    
378    
379     if blind:
380     for bin in range(10,datas[0].GetNbinsX()+1):
381     datas[0].SetBinContent(bin,0)
382    
383     histos.append(copy(Overlay))
384 nmohr 1.8 if 'ZH' in setup and 'WH' in setup:
385     typs.append('VH')
386     Stack.setup.remove('ZH')
387     Stack.setup.remove('WH')
388     Stack.setup.insert(0,'VH')
389     elif 'ZH' in setup:
390     typs.append('ZH')
391     elif 'WH' in setup:
392     typs.append('WH')
393 nmohr 1.1
394     Stack.histos = histos
395     Stack.typs = typs
396     Stack.datas = datas
397     Stack.datatyps = datatyps
398     Stack.datanames= datanames
399     Stack.overlay = Overlay
400     Stack.AddErrors=Error
401     Stack.lumi = lumi
402     Stack.doPlot()
403    
404     print 'i am done!\n'
405     #-------------------------------------------------
406    
407    
408     if __name__ == "__main__":
409     drawFromDC()
410     sys.exit(0)