def main(options,args): cfg = options.config workspaceName = cfg.get('Global','workspace') ws = RooWorkspace(workspaceName) #ws.Print("v") setupWorkspace(ws,options) #create -log(likelihood) theNLL = ws.pdf('TopLevelPdf').createNLL(ws.data('allcountingdata'), RooFit.NumCPU(1), RooFit.ConditionalObservables(ws.set('condObs')), RooFit.Verbose(True)) ws.saveSnapshot('standardmodel',ws.allVars()) minuit = ROOT.RooMinuit(theNLL) minuit.setPrintLevel(1) minuit.setPrintEvalErrors(-1) minuit.setErrorLevel(.5) #find the values of the parameters that minimize the likelihood minuit.setStrategy(2) minuit.simplex() minuit.migrad() minuit.hesse() #ws.var('err_gl').setConstant(True) #ws.var('err_gs').setConstant(True) #ws.var('err_gb').setConstant(True) ws.defineSet('POI', ROOT.RooArgSet(ws.var('%s_%s'%(cfg.get('Global','par1Name'),cfg.get('Global','couplingType'))), ws.var('%s_%s'%(cfg.get('Global','par2Name'),cfg.get('Global','couplingType'))))) ws.saveSnapshot('%s_fitresult'%cfg.get('Global','couplingType'), ws.allVars()) #create profile likelihood level_68 = ROOT.TMath.ChisquareQuantile(.68,2)/2.0 # delta NLL for 68% confidence level for -log(LR) level_95 = ROOT.TMath.ChisquareQuantile(.95,2)/2.0 # delta NLL for 95% confidence level for -log(LR) print print '68% CL Delta-NLL 2 DOF=',level_68 print '95% CL Delta-NLL 2 DOF=',level_95 minuit.setPrintLevel(1) minuit.setPrintEvalErrors(-1) minuit.migrad() minuit.minos(ws.set('POI')) thePlot = minuit.contour(ws.var('%s_%s'%(cfg.get('Global','par1Name'),cfg.get('Global','couplingType'))), ws.var('%s_%s'%(cfg.get('Global','par2Name'),cfg.get('Global','couplingType'))), sqrt(2*level_95),sqrt(2*level_68)) # here the error is in sigmas thePlot.SetName('%s_%s_%s_contour'%(cfg.get('Global','par1Name'), cfg.get('Global','par2Name'), cfg.get('Global','couplingType'))) thePlot.SetTitle('68% & 95% CL on the Best Fit Values of '+cfg.get('Global','par1Name')+' and '+cfg.get('Global','par2Name')) legend = ROOT.TLegend(2.01612903225806439e-01,7.86016949152542388e-01, 7.15725806451612989e-01,9.13135593220338992e-01) legend.SetNColumns(2) thePlot.addObject(legend) # 1-D Limits level_95 = ROOT.TMath.ChisquareQuantile(.95,1)/2.0 # delta NLL for -log(LR) with 1 dof print '95% CL Delta-NLL 1 DOF=',level_95 minuit.setErrorLevel(level_95) #set 1-D limits on parameter 1 with parameter 2 == 0 ws.var('%s_%s'%(cfg.get('Global','par2Name'),cfg.get('Global','couplingType'))).setVal(0.0) ws.var('%s_%s'%(cfg.get('Global','par2Name'),cfg.get('Global','couplingType'))).setConstant(True) minuit.minos(ws.set('POI')) parm1 = ws.var('%s_%s'%(cfg.get('Global','par1Name'),cfg.get('Global','couplingType'))) print 'parameter 1 value: '+str(parm1.getVal()) if not (0 < parm1.getVal()+parm1.getErrorHi() and 0 > parm1.getVal()+parm1.getErrorLo()): print '95% CL does not cover SM for parameter 1' else: print '95% CL covers SM for parameter 1' par1Line = ROOT.TLine(parm1.getVal()+parm1.getErrorLo(),0, parm1.getVal()+parm1.getErrorHi(),0) par1Line.SetLineWidth(2) par1Line.SetLineColor(ROOT.kRed) thePlot.addObject(par1Line) #set 1-D limits on parameter 2 with parameter 1 == 0 ws.var('%s_%s'%(cfg.get('Global','par2Name'),cfg.get('Global','couplingType'))).setConstant(False) ws.var('%s_%s'%(cfg.get('Global','par1Name'),cfg.get('Global','couplingType'))).setVal(0.0) ws.var('%s_%s'%(cfg.get('Global','par1Name'),cfg.get('Global','couplingType'))).setConstant(True) minuit.minos(ws.set('POI')) parm2 = ws.var('%s_%s'%(cfg.get('Global','par2Name'),cfg.get('Global','couplingType'))) print 'parameter 2 value: '+str(parm2.getVal()) if not (0 < parm2.getVal()+parm2.getErrorHi() and 0 > parm2.getVal()+parm2.getErrorLo()): print '95% CL does not cover SM for parameter 2' else: print '95% CL covers SM for parameter 2' par2Line = ROOT.TLine(0,parm2.getVal()+parm2.getErrorLo(), 0,parm2.getVal()+parm2.getErrorHi()) par2Line.SetLineWidth(2) par2Line.SetLineColor(ROOT.kRed) thePlot.addObject(par2Line) ws.var('%s_%s'%(cfg.get('Global','par1Name'),cfg.get('Global','couplingType'))).setConstant(False) #construct likelihood scan histograms plot = parm1.frame() parm1.setBins(200) parm2.setBins(200) scanHist = ROOT.TH2F('scan2d_plot','2D Scan of the Likelihood', 200,parm1.getMin(),parm1.getMax(), 200,parm2.getMin(),parm2.getMax()) for i in range(200): for j in range(200): parm1.setVal(parm1.getMin() + (i+.5)*(parm1.getMax()-parm1.getMin())/200) parm2.setVal(parm2.getMin() + (j+.5)*(parm2.getMax()-parm2.getMin())/200) scanHist.SetBinContent(i+1,j+1,theNLL.getVal()) profNLL_par1 = theNLL.createProfile(RooArgSet(parm1)) profNLL_par1_plot = parm1.frame() profNLL_par1.plotOn(profNLL_par1_plot) profNLL_par2 = theNLL.createProfile(RooArgSet(parm2)) profNLL_par2_plot = parm2.frame() profNLL_par2.plotOn(profNLL_par2_plot) initCMSStyle() output = TFile.Open(workspaceName+'.root','RECREATE') ws.Write() contCanvas = ROOT.TCanvas('contour_canvas','',500,500) thePlot.Draw() prettyContour(contCanvas,cfg) contCanvas.Write() thePlot.Write() scanCanvas2D = ROOT.TCanvas('scan2d_canvas','',500,500) scanHist.Draw('colz') prettyScan(scanCanvas2D,cfg) scanCanvas2D.Write() scanHist.Write() par1ScanCanvas = ROOT.TCanvas('scan1d_par1','',500,500) par1ScanCanvas.cd() profNLL_par1_plot.Draw() par1ScanCanvas.Write() profNLL_par1_plot.Write() par2ScanCanvas = ROOT.TCanvas('scan1d_par2','',500,500) par2ScanCanvas.cd() profNLL_par2_plot.Draw() par2ScanCanvas.Write() profNLL_par2_plot.Write() prettyObsPlots(ws,cfg) output.Close() if options.makeCards: print print "Creating cards for Higgs Combined Limit calculator!" makeHCLCards(ws,cfg) return 0
class Wjj2DFitter: def __init__ (self, pars): self.pars = pars self.ws = RooWorkspace('wjj2dfitter') self.utils = Wjj2DFitterUtils(self.pars) self.useImportPars = False self.rangeString = None obs = [] for v in self.pars.var: try: vName = self.pars.varNames[v] except AttributeError: vName = v obs.append(vName) var1 = self.ws.factory('%s[%f,%f]' % (vName, self.pars.varRanges[v][1], self.pars.varRanges[v][2]) ) var1.setUnit('GeV') try: var1.SetTitle(self.pars.varTitles[v]) except AttributeError: var1.SetTitle('m_{jj}') var1.setPlotLabel(var1.GetTitle()) if len(self.pars.varRanges[v][3]) > 1: vbinning = RooBinning(len(self.pars.varRanges[v][3]) - 1, array('d', self.pars.varRanges[v][3]), '%sBinning' % vName) var1.setBinning(vbinning) else: var1.setBins(self.pars.varRanges[v][0]) var1.Print() if v in self.pars.exclude: var1.setRange('signalRegion', self.pars.exclude[v][0], self.pars.exclude[v][1]) var1.setRange('lowSideband', var1.getMin(), self.pars.exclude[v][0]) var1.setRange('highSideband', self.pars.exclude[v][1], var1.getMax()) self.rangeString = 'lowSideband,highSideband' if hasattr(self.pars, 'plotRanges'): var1.setRange('plotRange', self.pars.plotRanges[v][1], self.pars.plotRanges[v][2]) var1.setBins(self.pars.plotRanges[v][0], 'plotBins') else: var1.setRange('plotRange', var1.getMin(), var1.getMax()) var1.setBins(var1.getBins(), 'plotBins') self.ws.defineSet('obsSet', ','.join(obs)) def loadDataFromWorkspace(self, other, cut = None): #pull unbinned data from other workspace unbinnedData = other.data('data_unbinned') if not unbinnedData: unbinnedData = other.data('data_obs') if cut: unbinnedData = unbinnedData.reduce(cut) unbinnedData.Print() if self.pars.binData: #bin and import data unbinnedData.SetName('data_unbinned') getattr(self.ws, 'import')(unbinnedData) data = RooDataHist('data_obs', 'data_obs', other.set('obsSet'), unbinnedData) getattr(self.ws, 'import')(data) else: #just import data unbinnedData.SetName('data_obs') getattr(self.ws, 'import')(unbinnedData) def loadHistogramsFromWorkspace(self, other): #pull RooHist pdfs from other workspace pdfs = other.allPdfs() pdfIter = pdfs.createIterator() pdf = pdfIter.Next() while pdf: if pdf.IsA().InheritsFrom('RooHistPdf'): print 'importing',pdf.GetName(),'from old workspace' getattr(self.ws, 'import')(pdf) pdf = pdfIter.Next() def loadWorkspaceFromFile(self, filename, wsname = 'w', getFloatPars = True): print 'loading data workspace %s from file %s' % (wsname, filename) fin = TFile.Open(filename) if not fin: print 'failed to open the file',filename import os print 'cwd:',os.getcwd() print 'access of',filename,os.access(filename, os.R_OK) print 'list of root files in cwd' for f in os.listdir(os.getcwd()): if f[-5:] == '.root': print f,len(f),len(filename) fin = TFile.Open(os.getcwd() + '/' + filename) assert(fin) other = fin.Get(wsname) #pull unbinned data from other workspace self.loadDataFromWorkspace(other) #pull in histogram pdfs to save time self.loadHistogramsFromWorkspace(other) if getFloatPars and other.loadSnapshot('fitPars'): self.useImportPars = True self.ws.saveSnapshot('importParams', other.set('floatingParams'), True) # self.ws.Print() # put together a fitting model and return the pdf def makeFitter(self, useAlternateModels = False): if self.ws.pdf('total'): return self.ws.pdf('total') compPdfs = [] for component in self.pars.backgrounds: # print 'getting compModels' compModels = getattr(self.pars, '%sModels' % component) if hasattr(self.pars, '%sConvModels' % component): convModels = getattr(self.pars, '%sConvModels' % component) else: convModels = None if useAlternateModels: print 'loading Alternate Models' compModels = getattr(self.pars, '%sModelsAlt' % component) convModels = getattr(self.pars, '%sConvModelsAlt' % component) # print 'compModels = %s' % compModels compFiles = getattr(self.pars, '%sFiles' % component) compPdf = self.makeComponentPdf(component, compFiles, compModels, useAlternateModels, convModels) norm = self.ws.factory('prod::f_%s_norm' % component + \ '(n_%s[0.,1e6],' % component + \ '%s_nrm[1.,-0.5,5.])' % component) self.ws.var('n_%s' % component).setConstant(True) if hasattr(self, '%sExpected' % component): self.ws.var('n_%s' % component).setVal( getattr(self, '%sExpected' % component)) compPdfs.append( self.ws.factory('RooExtendPdf::%s_extended(%s,%s)' % \ (compPdf.GetName(), compPdf.GetName(), norm.GetName()) ) ) self.ws.factory('r_signal[0., -200., 200.]') self.ws.var('r_signal').setConstant(False) try: obs = [ self.pars.varNames[x] for x in self.pars.var ] except AttributeError: obs = self.pars.var for component in self.pars.signals: compFile = getattr(self.pars, '%sFiles' % component) compModels = getattr(self.pars, '%sModels' % component) if hasattr(self.pars, '%sConvModels' % component): convModels = getattr(self.pars, '%sConvModels' % component) else: convModels = None compPdf = self.makeComponentPdf(component, compFiles, compModels, useAlternateModels, convModels) norm = self.ws.factory( "prod::f_%s_norm(n_%s[0., 1e6],r_signal)" % \ (component, component) ) self.ws.var('n_%s' % component).setConstant(True) if hasattr(self, '%sExpected' % component): self.ws.var('n_%s' % component).setVal( getattr(self, '%sExpected' % component)) pdf = self.ws.factory('RooExtendPdf::%s_extended(%s,%s)' % \ (compPdf.GetName(), compPdf.GetName(), norm.GetName()) ) if (hasattr(self.pars, '%sInterference' % component)) and \ getattr(self.pars, '%sInterference' % component): getattr(self.ws, 'import') \ (pdf, RooFit.RenameAllNodes('interf_%sUp' % component), RooFit.RenameAllVariablesExcept('interf_%sUp' % component, ','.join(obs)), RooFit.Silence() ) getattr(self.ws, 'import') \ (pdf, RooFit.RenameAllNodes('interf_%sDown' % component), RooFit.RenameAllVariablesExcept('interf_%sDown'%component, ','.join(obs)), RooFit.Silence() ) if self.pars.includeSignal: compPdfs.append(pdf) #print compPdfs prodList = [ '%s' % (pdf.GetName()) \ for (idx, pdf) in enumerate(compPdfs) ] comps = RooArgList(self.ws.argSet(','.join(prodList))) getattr(self.ws, 'import')(RooAddPdf('total', 'total', comps)) return self.ws.pdf('total') # define the constraints on the yields, etc that will be part of the fit. def makeConstraints(self): if self.ws.set('constraintSet'): return self.ws.set('constraintSet') constraints = [] constrainedParameters = [] for constraint in self.pars.yieldConstraints: theYield = self.ws.var('%s_nrm' % constraint) if not theYield.isConstant(): self.ws.factory('RooGaussian::%s_const(%s, 1.0, %f)' % \ (constraint, theYield.GetName(), self.pars.yieldConstraints[constraint]) ) constraints.append('%s_const' % constraint) constrainedParameters.append(theYield.GetName()) if hasattr(self.pars, 'constrainShapes'): for component in self.pars.constrainShapes: pc = self.ws.pdf(component).getParameters(self.ws.set('obsSet')) parIter = pc.createIterator() par = parIter.Next() while par: if not par.isConstant(): theConst = self.ws.factory('RooGaussian::%s_const' % \ (par.GetName()) + \ '(%s, %f, %f)' % \ (par.GetName(), par.getVal(), par.getError()) ) constraints.append(theConst.GetName()) constrainedParameters.append(par.GetName()) par = parIter.Next() pc.IsA().Destructor(pc) self.ws.defineSet('constraintSet', ','.join(constraints)) self.ws.defineSet('constrainedSet', ','.join(constrainedParameters)) return self.ws.set('constraintSet') # make the constrained fitter def makeConstrainedFitter(self): if self.ws.pdf('totalFit_const'): return self.ws.pdf('totalFit_const') constraintSet = self.makeConstraints() fitter = self.makeFitter() print '\nfit constraints' constIter = constraintSet.createIterator() constraint = constIter.Next() constraints = [] while constraint: constraint.Print() constraints.append(constraint.GetName()) constraint = constIter.Next() if constraintSet.getSize() > 0: constraints.append(fitter.GetName()) fitter = self.ws.factory('PROD::totalFit_const(%s)' % \ (','.join(constraints)) ) return fitter # fit the data using the pdf def fit(self, keepParameterValues = False, overrideRangeCmd = False): print 'construct fit pdf ...' fitter = self.makeFitter() print 'load data ...' data = self.loadData() self.resetYields() constraintSet = self.makeConstraints() if not keepParameterValues: self.readParametersFromFile() self.resetYields() # print constraints, self.pars.yieldConstraints constraintCmd = RooCmdArg.none() if constraintSet.getSize() > 0: fitter = self.makeConstrainedFitter() constraintCmd = RooFit.Constrained() # constraintCmd = RooFit.ExternalConstraints(self.ws.set('constraintSet')) if self.useImportPars: self.ws.loadSnapshot('importParams') self.ws.Print() # for constraint in pars.constraints: # self.ws.pdf(constraint).Print() # print rangeCmd = RooCmdArg.none() if self.rangeString and self.pars.doExclude and not overrideRangeCmd: rangeCmd = RooFit.Range(self.rangeString) # print 'scanning parameter values...' # fitter.fitTo(data, RooFit.Minos(False), # RooFit.PrintEvalErrors(-1), # RooFit.Warnings(False), # RooFit.Minimizer("Minuit2", "scan"), # RooFit.PrintLevel(0), # constraintCmd, # rangeCmd) print 'fitting ...' fr = fitter.fitTo(data, RooFit.Save(True), # RooFit.Extended(True), RooFit.Minos(False), RooFit.PrintEvalErrors(-1), RooFit.Warnings(False), RooFit.Minimizer("Minuit2", "minimize"), constraintCmd, rangeCmd ) fr.Print('v') return fr # determine the fitting model for each component and return them def makeComponentPdf(self, component, files, models, useAlternateModels, convModels): print 'making ComponentPdf %s' % component # print 'models = %s' % models # print 'files = %s' % files if convModels and not (convModels[0] == -1): thePdf = self.makeConvolvedPdf(component, files, models, useAlternateModels, convModels) elif (models[0] == -1): thePdf = self.makeComponentHistPdf(component, files) elif (models[0] == -2): thePdf = self.makeMorphingPdf(component, useAlternateModels, convModels) elif (models[0] == -3): pass else: thePdf = self.makeComponentAnalyticPdf(component, models, useAlternateModels) return thePdf #create a simple 2D histogram pdf def makeComponentHistPdf(self, component, files): if self.ws.pdf(component): return self.ws.pdf(component) compHist = self.utils.newEmptyHist('hist%s' % component) sumYields = 0. sumxsec = 0. sumExpected = 0. for (idx,fset) in enumerate(files): if hasattr(self.pars, '%scuts' % component): cutOverride = getattr(self.pars, '%scuts' % component) else: cutOverride = None filename = fset[0] tmpHist = self.utils.File2Hist(filename, 'hist%s_%i' % (component, idx), False,cutOverride,False,True,0) sumYields += tmpHist.Integral() sumxsec += fset[2] compHist.Add(tmpHist, self.pars.integratedLumi*fset[2]/fset[1]) sumExpected += tmpHist.Integral()*fset[2]* \ self.pars.integratedLumi/fset[1] print filename,'acc x eff: %.3g' % (tmpHist.Integral()/fset[1]) print filename,'N_expected: %.1f' % \ (tmpHist.Integral()*fset[2]*self.pars.integratedLumi/fset[1]) #tmpHist.Print() #compHist.Print() print '%s acc x eff: %.3g' % \ (component, sumExpected/sumxsec/self.pars.integratedLumi) print 'Number of expected %s events: %.1f' % (component, sumExpected) setattr(self, '%sExpected' % component, sumExpected) return self.utils.Hist2Pdf(compHist, component, self.ws, self.pars.order) #create a pdf which is a convolution of any two pdf def makeConvolvedPdf(self, component, files, models, useAlternateModels, convModels): if self.ws.pdf(component): return self.ws.pdf(component) #If a morphing model is selected, then convolve each individual component first and then morph if (models[0] == -2): return self.makeMorphingPdf(component, useAlternateModels, convModels) basePdf = self.makeComponentPdf('%s_base' % component, files, models, useAlternateModels, [-1]) convComponent = 'Global' ##Overwrite to use the same convolution model for all Pdfs convModel = getattr(self.pars, '%sConvModels' % convComponent) if useAlternateModels: convModel = getattr(self.pars, '%sConvModelsAlt' % convComponent) convPdf = self.makeComponentPdf('%s_conv' % convComponent, files, convModel, useAlternateModels, [-1]) var = self.pars.var[0] try: vName = self.pars.varNames[var] except AttributeError: vName = var self.ws.factory('RooFFTConvPdf::%s(%s,%s,%s)' % \ (component, vName, basePdf.GetName(), convPdf.GetName())) return self.ws.pdf(component) # create a pdf using the "template morphing" technique def makeMorphingPdf(self, component, useAlternateModels, convModels): if self.ws.pdf(component): return self.ws.pdf(component) filesNom = getattr(self.pars, '%s_NomFiles' % component) modelsNom = getattr(self.pars, '%s_NomModels' % component) filesMU = getattr(self.pars, '%s_MUFiles' % component) modelsMU = getattr(self.pars, '%s_MUModels' % component) filesMD = getattr(self.pars, '%s_MDFiles' % component) modelsMD = getattr(self.pars, '%s_MDModels' % component) filesSU = getattr(self.pars, '%s_SUFiles' % component) modelsSU = getattr(self.pars, '%s_SUModels' % component) filesSD = getattr(self.pars, '%s_SDFiles' % component) modelsSD = getattr(self.pars, '%s_SDModels' % component) if useAlternateModels: modelsNom = getattr(self.pars, '%s_NomModelsAlt' % component) modelsMU = getattr(self.pars, '%s_MUModelsAlt' % component) modelsMD = getattr(self.pars, '%s_MDModelsAlt' % component) modelsSU = getattr(self.pars, '%s_SUModelsAlt' % component) modelsSD = getattr(self.pars, '%s_SDModelsAlt' % component) # Adds five (sub)components for the component with suffixes Nom, MU, MD, SU, SD NomPdf = self.makeComponentPdf('%s_Nom' % component, filesNom, modelsNom, False, convModels) if hasattr(self, '%s_NomExpected' % component): setattr(self, '%sExpected' % component, getattr(self, '%s_NomExpected' % component)) MUPdf = self.makeComponentPdf('%s_MU' % component, filesMU, modelsMU, False, convModels) MDPdf = self.makeComponentPdf('%s_MD' % component, filesMD, modelsMD, False, convModels) SUPdf = self.makeComponentPdf('%s_SU' % component, filesSU, modelsSU, False, convModels) SDPdf = self.makeComponentPdf('%s_SD' % component, filesSD, modelsSD, False, convModels) fMU_comp = self.ws.factory("fMU_%s[0., -1., 1.]" % component) fSU_comp = self.ws.factory("fSU_%s[0., -1., 1.]" % component) fMU = RooFormulaVar("f_fMU_%s" % component, "1.0*@0*(@0 >= 0.)", RooArgList( fMU_comp ) ) fMD = RooFormulaVar("f_fMD_%s" % component, "-1.0*@0*(@0 < 0.)", RooArgList( fMU_comp ) ) fSU = RooFormulaVar("f_fSU_%s" % component, "@0*(@0 >= 0.)", RooArgList( fSU_comp ) ) fSD = RooFormulaVar("f_fSD_%s" % component, "@0*(-1)*(@0 < 0.)", RooArgList( fSU_comp ) ) fNom = RooFormulaVar("f_fNom_%s" % component, "(1.-abs(@0)-abs(@1))", RooArgList(fMU_comp,fSU_comp) ) morphPdf = RooAddPdf(component,component, RooArgList(MUPdf,MDPdf,SUPdf,SDPdf,NomPdf), RooArgList(fMU, fMD, fSU, fSD, fNom)) morphPdf.SetName(component) getattr(self.ws, 'import')(morphPdf) return self.ws.pdf(component) # create a pdf using an analytic function. def makeComponentAnalyticPdf(self, component, models, useAlternateModels): if self.ws.pdf(component): return self.ws.pdf(component) pdfList = [] systMult = None if ( hasattr(self.pars, '%sInterference' % component) and \ getattr(self.pars, '%sInterference' % component) and \ hasattr(self.pars, "%sdoSystMult" % component) and \ getattr(self.pars, "%sdoSystMult" % component) ): systMult = getattr(self.pars, "%sSystMult" % component) for (idx,model) in enumerate(models): var = self.pars.var[idx] try: vName = self.pars.varNames[var] except AttributeError: vName = var auxModel = None if useAlternateModels: if hasattr(self.pars, '%sAuxModelsAlt' % component): auxModel = getattr(self.pars, '%sAuxModelsAlt' % component)[idx] else: if hasattr(self.pars, '%sAuxModels' % component): auxModel = getattr(self.pars, '%sAuxModels' % component)[idx] pdfList.append(self.utils.analyticPdf(self.ws, vName, model, '%s_%s'%(component,vName), '%s_%s'%(component,vName), auxModel, systMult ) ) pdfListNames = [ pdf.GetName() for pdf in pdfList ] if len(pdfList) > 1: self.ws.factory('PROD::%s(%s)' % \ (component, ','.join(pdfListNames))) else: pdfList[0].SetName(component) return self.ws.pdf(component) def loadData(self, weight = False): if self.ws.data('data_obs'): return self.ws.data('data_obs') unbinnedName = 'data_obs' if self.pars.binData: unbinnedName = 'data_unbinned' data = self.utils.File2Dataset(self.pars.DataFile, unbinnedName, self.ws, weighted = weight) if self.pars.binData: data = RooDataHist('data_obs', 'data_obs', self.ws.set('obsSet'), data) getattr(self.ws, 'import')(data) data = self.ws.data('data_obs') return data def stackedPlot(self, var, logy = False, pdfName = None, Silent = False): if not pdfName: pdfName = 'total' xvar = self.ws.var(var) nbins = xvar.getBins() # if hasattr(self.pars, 'plotRanges') and not xvar.hasRange('plotRange'): # xvar.setRange('plotRange', self.pars.plotRanges[var][1], # self.pars.plotRanges[var][2]) # xvar.setBins(self.pars.plotRanges[var][0], 'plotBins') # elif not xvar.hasRange('plotRange'): # xvar.setRange('plotRange', xvar.getMin(), xvar.getMax()) # xvar.setBins(nbins, 'plotBins') sframe = xvar.frame(RooFit.Range('plotRange'), RooFit.Bins(xvar.getBins('plotBins'))) sframe.SetName("%s_stacked" % var) pdf = self.ws.pdf(pdfName) if isinstance(pdf, RooAddPdf): compList = RooArgList(pdf.pdfList()) else: compList = None data = self.ws.data('data_obs') nexp = pdf.expectedEvents(self.ws.set('obsSet')) if not Silent: print pdf.GetName(),'expected: %.0f' % (nexp) print 'data events: %.0f' % (data.sumEntries()) if nexp < 1: nexp = data.sumEntries() theComponents = [] if self.pars.includeSignal: theComponents += self.pars.signals theComponents += self.pars.backgrounds data.plotOn(sframe, RooFit.Invisible(), RooFit.Binning('plotBins')) # dataHist = RooAbsData.createHistogram(data,'dataHist_%s' % var, xvar, # RooFit.Binning('%sBinning' % var)) # #dataHist.Scale(1., 'width') # invData = RooHist(dataHist, 1., 1, RooAbsData.SumW2, 1.0, False) # #invData.Print('v') # sframe.addPlotable(invData, 'pe', True, True) for (idx,component) in enumerate(theComponents): if not Silent: print 'plotting',component,'...', if hasattr(self.pars, '%sPlotting' % (component)): plotCharacteristics = getattr(self.pars, '%sPlotting' % \ (component)) else: plotCharacteristics = {'color' : colorwheel[idx%6], 'title' : component } compCmd = RooCmdArg.none() if compList: compSet = RooArgSet(compList) if compSet.getSize() > 0: compCmd = RooFit.Components(compSet) removals = compList.selectByName('%s*' % component) compList.remove(removals) if not Silent: print 'events', self.ws.function('f_%s_norm' % component).getVal() sys.stdout.flush() if abs(self.ws.function('f_%s_norm' % component).getVal()) >= 1.: pdf.plotOn(sframe, #RooFit.ProjWData(data), RooFit.DrawOption('LF'), RooFit.FillStyle(1001), RooFit.FillColor(plotCharacteristics['color']), RooFit.LineColor(plotCharacteristics['color']), RooFit.VLines(), RooFit.Range('plotRange'), RooFit.NormRange('plotRange'), RooFit.Normalization(nexp, RooAbsReal.NumEvent), compCmd ) tmpCurve = sframe.getCurve() tmpCurve.SetName(component) tmpCurve.SetTitle(plotCharacteristics['title']) if 'visible' in plotCharacteristics: sframe.setInvisible(component, plotCharacteristics['visible']) data.plotOn(sframe, RooFit.Name('theData'), RooFit.Binning('plotBins')) sframe.getHist('theData').SetTitle('data') # theData = RooHist(dataHist, 1., 1, RooAbsData.SumW2, 1.0, True) # theData.SetName('theData') # theData.SetTitle('data') # sframe.addPlotable(theData, 'pe') if (logy): sframe.SetMinimum(0.01) sframe.SetMaximum(1.0e6) else: sframe.SetMaximum(sframe.GetMaximum()*1.35) pass excluded = (var in self.pars.exclude) bname = var if not excluded: for v in self.pars.exclude: if hasattr(self.pars, 'varNames') and \ (self.pars.varNames[v] == var): excluded = True bname = v if excluded: blinder = TBox(self.pars.exclude[bname][0], sframe.GetMinimum(), self.pars.exclude[bname][1], sframe.GetMaximum()) # blinder.SetName('blinder') # blinder.SetTitle('signal region') blinder.SetFillColor(kBlack) if self.pars.blind: blinder.SetFillStyle(1001) else: blinder.SetFillStyle(0) blinder.SetLineStyle(2) sframe.addObject(blinder) elif self.pars.blind: if not Silent: print "blind but can't find exclusion region for", var print 'excluded',excluded,self.pars.exclude print 'hiding data points' sframe.setInvisible('theData', True) else: sframe.setInvisible('theData', False) #sframe.GetYaxis().SetTitle('Events / GeV') # dataHist.IsA().Destructor(dataHist) if not Silent: print xvar.setBins(nbins) return sframe def readParametersFromFile(self, fname=None): if (not fname): fname = self.pars.initialParametersFile if isinstance(fname, str): flist = [ fname ] else: flist = fname for tmpName in flist: if len(tmpName) > 0: print 'loading parameters from file',tmpName self.ws.allVars().readFromFile(tmpName) def expectedFromPars(self): components = self.pars.signals + self.pars.backgrounds for component in components: theYield = self.ws.var('n_%s' % component) setattr(self, '%sExpected' % component, theYield.getVal()) def initFromExplicitVals(self,opts): #,init_diboson= -1.0,init_WpJ=-1.0,init_top=-1.0,init_ZpJ=-1.0,init_QCD=-1.0 components = ['diboson', 'top', 'WpJ', 'ZpJ', 'QCD', 'WHbb'] for component in components: #double init init = getattr(opts, 'ext%s' % component) #init = -2.0 #setattr(self,init, 'init_%s' % component) #init = init_%s % component #print "init=", init #init = self.ws.var('init_%s' % component) #init.setVal(100.0) #init.setVal('init_%s' % component) #init = theYield.getVal() if (init>0.): print 'setting initial value for ',component,' to ',init setattr(self, '%sInitial' % component, init) def resetYields(self): if self.ws.data('data_obs'): Ndata = self.ws.data('data_obs').sumEntries() else: Ndata = 10000. print 'resetting yields...' components = self.pars.signals + self.pars.backgrounds for component in components: theYield = self.ws.var('n_%s' % component) theNorm = self.ws.var('%s_nrm' % component) if hasattr(self, '%sInitial' % component): print 'explicitly setting initial value for ',component theYield.setVal(getattr(self, '%sInitial' % component)) theNorm.setVal(1.0) theNorm.setConstant() else: fracofdata = -1. if hasattr(self.pars, '%sFracOfData' % component): fracofdata = getattr(self.pars, '%sFracOfData' % component) if (fracofdata >= 0.): print 'explicitly setting ', component,' yield to be', fracofdata,' of data' theYield.setVal(fracofdata*Ndata) elif hasattr(self, '%sExpected' % component): theYield.setVal(getattr(self, '%sExpected' % component)) else: print 'no expected value for',component theYield.setVal(Ndata/len(components)) if theNorm and not theNorm.isConstant(): theNorm.setVal(1.0) if component in self.pars.yieldConstraints: theYield.setError(theYield.getVal() * \ self.pars.yieldConstraints[component]) if theNorm: theNorm.setError(self.pars.yieldConstraints[component]) else: theYield.setError(sqrt(theYield.getVal())) theYield.Print() def generateToyMCSet(self,var,inputPdf,outFileName,NEvts): fMC = TFile(outFileName, "RECREATE"); # thevar = self.ws.var(var); print 'thevar=' print var # print thevar print '...' # varList = RooArgList() # varList.add(self.ws.var(var)) toymc = inputPdf.generate(RooArgSet(self.ws.var(var)),NEvts); tMC = toymc.tree(); fMC.cd(); tMC.Write(); fMC.Close(); def legend4Plot(plot, left = False): if left: theLeg = TLegend(0.2, 0.62, 0.55, 0.92, "", "NDC") else: theLeg = TLegend(0.60, 0.62, 0.92, 0.92, "", "NDC") theLeg.SetName('theLegend') theLeg.SetBorderSize(0) theLeg.SetLineColor(0) theLeg.SetFillColor(0) theLeg.SetFillStyle(0) theLeg.SetLineWidth(0) theLeg.SetLineStyle(0) theLeg.SetTextFont(42) theLeg.SetTextSize(.045) entryCnt = 0 for obj in range(0, int(plot.numItems())): objName = plot.nameOf(obj) if (not plot.getInvisible(objName)): theObj = plot.getObject(obj) objTitle = theObj.GetTitle() if len(objTitle) < 1: objTitle = objName dopts = plot.getDrawOptions(objName).Data() # print 'obj:',theObj,'title:',objTitle,'opts:',dopts,'type:',type(dopts) if theObj.IsA().InheritsFrom('TNamed'): theLeg.AddEntry(theObj, objTitle, dopts) entryCnt += 1 theLeg.SetY1NDC(0.9 - 0.05*entryCnt - 0.005) theLeg.SetY1(theLeg.GetY1NDC()) return theLeg legend4Plot = staticmethod(legend4Plot)
readData(ws, hidatafile, ppdatafile, cuts, mmin, mmax) mass = ws.var('invariantMass') ppBkgModel = 1 bkgModel = 0 if useKeys: bkgModel = 2 buildPdf(ws, False, ppBkgModel, True) buildPdf(ws, True, bkgModel, True) simPdf = buildSimPdf(ws, ws.cat('dataCat')) #ws.Print() data = ws.data('data').reduce('(QQsign==QQsign::PlusMinus)') pars = simPdf.getParameters(data) ws.var('nsig1_pp').setVal(90) ws.var('nsig1_pp').setError(10) ws.var('nsig1_hi').setVal(1200) ws.var('nsig1_hi').setError(40) ws.var('nbkg_pp').setVal(335*(mmax-mmin)/7.) ws.var('nbkg_pp').setError(12) ws.var('nbkg_hi').setVal(10000*(mmax-mmin)/7.) ws.var('nbkg_hi').setError(100) if len(simparamfile) > 0: pars.readFromFile(simparamfile) ws.Print()
def makeCard(TYPE, mZp, mChi, DIR): # Setup input and output files indir = DIR old_str = "" new_str = "" if (TYPE == "BARY"): old_str = "sig_ZpBaryonic_mZP10_mChi1" new_str = "sig_ZpBaryonic_mZP" + mZp + "_mChi" + mChi if (TYPE == "2HDM"): old_str = "sig_2HDM_mZP600_mA0300" new_str = "sig_2HDM_mZP" + mZp + "_mA0" + mChi fin = open(indir + "dataCard_" + old_str + "_13TeV.txt", "r") fout = open(indir + "dataCard_" + new_str + "_13TeV.txt", "w") rin = ROOT.TFile(indir + old_str + "_13TeV.root") rout = ROOT.TFile(indir + new_str + "_13TeV.root", "RECREATE") # Copy the datacard for new mass point for line in fin: if old_str in line: line = line.replace(old_str, new_str) fout.write(line) # Get the old and new eff mZ = float(mZp) mDM = float(mChi) old_efflowMET = 1.0 old_effhighMET = 1.0 new_efflowMET = 1.0 new_effhighMET = 1.0 if (TYPE == "BARY"): old_efflowMET = getEffBary(0, 10, 1) old_effhighMET = getEffBary(1, 10, 1) new_efflowMET = getEffBary(0, mZ, mDM) new_effhighMET = getEffBary(1, mZ, mDM) if (TYPE == "2HDM"): old_efflowMET = getEff2HDM(0, 600, 300) old_effhighMET = getEff2HDM(1, 600, 300) new_efflowMET = getEff2HDM(0, mZ, mDM) new_effhighMET = getEff2HDM(1, mZ, mDM) scale_lowMET = new_efflowMET / old_efflowMET scale_highMET = new_effhighMET / old_effhighMET #print("Old eff: low = %f, high = %f" %(old_efflowMET,old_effhighMET)) #print("New eff: low = %f, high = %f" %(new_efflowMET,new_effhighMET)) #print("Scale: low = %f, high = %f" %(scale_lowMET,scale_highMET)) # Copy the input file in_TObjString = TObjString(rin.cfg) out_TObjString = in_TObjString.Clone() in_RooWorkspace = RooWorkspace(rin.wtemplates) #in_RooWorkspace.Print() # print obj in input rooWorkspace w1 = ROOT.RooWorkspace("wtemplates") w1.rooImport = getattr(w1, 'import') var1 = in_RooWorkspace.var('mgg') var2 = in_RooWorkspace.var('model_signal_' + old_str + '_13TeV_met0-130_norm') var3 = in_RooWorkspace.var('model_signal_' + old_str + '_13TeV_met130_norm') # multiply old normalization by new scale valnorm_lowMET = scale_lowMET * var2.getValV() valnorm_highMET = scale_highMET * var3.getValV() norm1 = RooRealVar("model_signal_" + new_str + "_13TeV_met0-130_norm", "model_signal" + new_str + "13TeV_met0-130_norm", valnorm_lowMET) norm2 = RooRealVar("model_signal_" + new_str + "_13TeV_met130_norm", "model_signal" + new_str + "13TeV_met130_norm", valnorm_highMET) varlist = ROOT.RooArgList(var1, norm1, norm2) #print("%f * %f" %(scale_lowMET,var2.getValV())) #print("%f" %valnorm_lowMET) #print("%f" %norm1.getValV()) # get old pdfs and change names pdf1 = in_RooWorkspace.pdf('model_signal_' + old_str + '_13TeV_met0-130') pdf2 = in_RooWorkspace.pdf('model_signal_' + old_str + '_13TeV_met0-130_energyScalemet0-130Down') pdf3 = in_RooWorkspace.pdf('model_signal_' + old_str + '_13TeV_met0-130_energyScalemet0-130Up') pdf4 = in_RooWorkspace.pdf('model_signal_' + old_str + '_13TeV_met130') pdf5 = in_RooWorkspace.pdf('model_signal_' + old_str + '_13TeV_met130_energyScalemet130Down') pdf6 = in_RooWorkspace.pdf('model_signal_' + old_str + '_13TeV_met130_energyScalemet130Up') pdf1new = ROOT.RooHistPdf(pdf1, "model_signal_" + new_str + "_13TeV_met0-130") pdf2new = ROOT.RooHistPdf( pdf2, "model_signal_" + new_str + "_13TeV_met0-130_energyScalemet0-130Down") pdf3new = ROOT.RooHistPdf( pdf3, "model_signal_" + new_str + "_13TeV_met0-130_energyScalemet0-130Up") pdf4new = ROOT.RooHistPdf(pdf4, "model_signal_" + new_str + "_13TeV_met130") pdf5new = ROOT.RooHistPdf( pdf5, "model_signal_" + new_str + "_13TeV_met130_energyScalemet130Down") pdf6new = ROOT.RooHistPdf( pdf6, "model_signal_" + new_str + "_13TeV_met130_energyScalemet130Up") # these are null pointers -- probably don't have right classes (missing from dipho analysis) to read them # but they are also not needed for running higgs combine so left out for now dat1 = in_RooWorkspace.data('signal_' + old_str + '_13TeV_met130') dat2 = in_RooWorkspace.data('signalforPdf_' + old_str + '_13TeV_met130') dat3 = in_RooWorkspace.data('signal_' + old_str + '_13TeV_met0-130') dat4 = in_RooWorkspace.data('signalforPdf_' + old_str + '_13TeV_met0-130') #print("%f" %dat1.sumEntries()) # Write to output file #out_TObjString.Write() w1.rooImport(var1) w1.rooImport(norm1) w1.rooImport(norm2) w1.rooImport(pdf1new) w1.rooImport(pdf2new) w1.rooImport(pdf3new) w1.rooImport(pdf4new) w1.rooImport(pdf5new) w1.rooImport(pdf6new) #w1.Print() # print contents of workspace w1.Write() rout.Close()
if tree.itype == 72 or tree.itype == 82: data.add(getattr(ws, 'set')('observables')) getattr(ws, 'import')(mc) getattr(ws, 'import')(data) ws.Print() ws.factory("mean[5200,5300]") ws.factory( "CBShape:sig_cb1(mass,mean,sigma_1[10,200],alpha_1[0,1.],n_1[0.,50.])") ws.factory( "CBShape:sig_cb2(mass,mean,sigma_2[10,200],alpha_2[-1.,0.],n_2[0.,50.])") ws.factory("SUM::mcsig( f[0.5,0,1]*sig_cb1, sig_cb2)") ws.pdf("mcsig").fitTo(ws.data("mc")) mcplot = ws.var("mass").frame() ws.data("mc").plotOn(mcplot) ws.pdf("mcsig").plotOn(mcplot) # freeze obs argset = ws.pdf("mcsig").getParameters(RooArgSet(ws.var("mass"))) ws.defineSet("signal_params", argset) #RooArgSet(getattr(ws,'set')("signal_params")).setAttribAll("Constant") ws.factory("Exponential:bkg(mass,exp_p1[-0.02,0.])") ws.factory("SUM:pdf( sig_y[0,1000]*mcsig, bkg_y[0,2000]*bkg )") ws.pdf("pdf").fitTo(ws.data("data"))
def plotStuff(plotList, plotstring, cutstring, plotfile, plotname, xlabel, ylabel, unitnorm): isFirst = True w = RooWorkspace("w") w.factory("x[-100,100]") for dataset in plotList: dataset[0].Draw(plotstring.format(dataset[1]), cutstring, "goff") hist = gDirectory.Get(dataset[1]) data = RooDataHist(dataset[1], dataset[1], RooArgList(w.var("x")), hist) getattr(w, 'import')(data) w.factory("HistPdf::triPdf(x,tri)") w.factory("HistPdf::wabPdf(x,wab)") w.factory("prod::triscale(a[0.3,0,10],{0})".format( w.data("tri").sum(False))) w.factory("prod::wabscale(b[0.1,0,10],{0})".format( w.data("wab").sum(False))) w.factory("SUM::sumModel(triscale*triPdf,wabscale*wabPdf)") w.pdf("sumModel").fitTo(w.data("data"), RooFit.SumW2Error(True), RooFit.Extended(True), RooFit.Verbose(False), RooFit.PrintLevel(-1)) #w.pdf("sumModel").fitTo(w.data("data"),RooFit.Extended(True)) #w.pdf("sumModel").fitTo(w.data("data")) frame = w.var("x").frame() w.data("data").plotOn(frame) #w.pdf("triPdf").plotOn(frame) #w.pdf("wabPdf").plotOn(frame) w.pdf("sumModel").plotOn(frame) w.pdf("sumModel").paramOn(frame) frame.SetTitle(gDirectory.Get("data").GetTitle()) frame.Draw() c.Print(plotfile) c.Clear() dataHist = gDirectory.Get("data") triHist = gDirectory.Get("tri") wabHist = gDirectory.Get("wab") if legendright: leg = TLegend(0.7, 0.75, 0.9, 0.9) else: leg = TLegend(0.1, 0.75, 0.3, 0.9) hs = THStack("hs", plotname) for dataset in plotList: hist = gDirectory.Get(dataset[1]) #hist.Sumw2() if unitnorm: hist.Scale(1.0 / hist.Integral()) else: hist.Scale(1.0 / dataset[2]) print "{0} {1} {2}".format(plotname, dataset[4], hist.Integral()) hist.SetLineColor(dataset[3]) leg.AddEntry(hist, dataset[4]) hs.Add(hist) #hist.GetXaxis().SetTitle(xlabel) hist.GetYaxis().SetTitle(ylabel) #if isFirst: #hist.GetXaxis().SetTitle(xlabel) #hist.GetYaxis().SetTitle(ylabel) #hist.Draw() #else: #hist.Draw("same") isFirst = False sumHist = triHist.Clone("sum") sumHist.Add(wabHist) if unitnorm: sumHist.Scale(1.0 / sumHist.Integral()) sumHist.SetLineColor(6) leg.AddEntry(sumHist, "MC sum") hs.Add(sumHist) hs.Draw("nostack") hs.GetXaxis().SetTitle(xlabel) hs.GetYaxis().SetTitle(ylabel) leg.Draw() c.Print(plotfile)
ppdatafile = 'data/dimuonTree_2011_pp.root' cuts = '(muPlusPt > %0.1f) && (muMinusPt > %0.1f) && (abs(upsRapidity)<2.4) && (vProb > 0.05)' \ % (opts.pt, opts.pt) simparamfile = opts.paramfile useKeys = opts.keys ws = RooWorkspace("ws","ws") readData(ws, hidatafile, ppdatafile, cuts) buildPdf(ws, False, 1, True) buildPdf(ws, True, 0, True) simPdf = buildSimPdf(ws, ws.cat('dataCat')) pars = simPdf.getParameters(ws.data('data')) pars.readFromFile(simparamfile) Npp_tot = Long(ws.var("nsig1_pp").getVal() + \ ws.function("nsig2_pp").getVal() + \ ws.function("nsig3_pp").getVal() + \ ws.var("nbkg_pp").getVal() + 0.5) Nhi_tot = Long(ws.var("nsig1_hi").getVal() + \ ws.function("nsig2_hi").getVal() + \ ws.function("nsig3_hi").getVal() + \ ws.var("nbkg_hi").getVal() + 0.5) dataCat = ws.cat('dataCat') QQsign = ws.cat('QQsign') reducedCols = RooArgSet(dataCat,QQsign) dsToGen = ['os']
ws = RooWorkspace("ws","ws") readData(ws, hidatafile, ppdatafile, cuts) setBkgdPbPb = opts.bkgd_PbPb setBkgdpp = opts.bkgd_pp trkRotBkgd = opts.trkRot buildPdf(ws, True, setBkgdPbPb, trkRotBkgd) # pdf for PbPb buildPdf(ws, False, setBkgdpp, False) # pdf for pp simPdf = buildSimPdf(ws, ws.cat('dataCat')) mass = ws.var('invariantMass') upsRap = ws.var('Rapidity') ##upsRap.setRange("RapidityBin",'%0.1f' % (opts.ymin),'%0.1f' % ( opts.ymax)) data = ws.data('data').reduce('(QQsign==QQsign::PlusMinus)&&(%s>%0.1f)&&(%s<%0.1f)' % (mass.GetName(), mmin, mass.GetName(), mmax)) ##data = ws.data('data').reduce('(QQsign==QQsign::PlusMinus)') data_ls = ws.data('data').reduce('(QQsign!=0)') ##data = ws.data('data').reduce('(QQsign==QQsign::PlusMinus)&&(%s>%0.1f)&&(%s<%0.1f)' % (upsRap, opts.ymin, upsRap, opts.ymax)) ##data_ls = ws.data('data').reduce('(QQsign!=0)&&(%s>%0.1f)&&(%s<%0.1f)' % (upsRap, opts.ymin, upsRap, opts.ymax)) mass.setRange("fitRange",8.5,11.5) mass.setRange(8.5,11.5) ##parsRap = pdf.getParameters(data) pars = simPdf.getParameters(data) #data_hi = ws.data('data').reduce('(QQsign==QQsign::PlusMinus) && (dataCat == dataCat::hi)') #data_hi.SetName('data_heavy') #getattr(ws,'import')(data_hi) ws.Print() data.Print()
def ControlDataFit(free=True, sim=True): w = RooWorkspace('w_ctrl', 'w_ctrl') samples = ['b0g', 'bsg', 'cg', 'b0pi0', 'bspi0', 'cpi0'] # create the category w.factory('cat[%s]' % (','.join(samples))) files = { 'b0g': path + "../New/Tuples/Data/9_B2DstKpi_Dst2DgammTuple_BestCut.root", 'b0pi0': path + "../New/Tuples/Data/9_B2Dstpi0Tuple_BestCut.root", 'bsg': path + "../New/Tuples/Data/9_Bs2DstKpi_Dst2DgammaTuple_BestCut.root", 'bspi0': path + "../New/Tuples/Data/9_Bs2Dstpi0Tuple_BestCut.root", 'cg': path + "../New/Tuples/Data/9_B2Dstpipi_Dst2DgammTuple_BestCut.root", 'cpi0': path + "../New/Tuples/Data/9_B2Dstpipi_Dst2Dpi0Tuple_No16_BestCut.root" } # Make the dsets w.factory("B_DTFDict_D0_B_M[5100,5900]") w.var("B_DTFDict_D0_B_M").setBins(80) for samp in samples: assert (os.path.exists(files[samp])) tf = TFile(files[samp]) t = tf.Get('DecayTree') t.SetBranchStatus("*", 0) t.SetBranchStatus("B_DTFDict_D0_B_M", 1) dset = RooDataSet("data_%s" % (samp), "", t, RooArgSet(w.var("B_DTFDict_D0_B_M"))) getattr(w, 'import')(dset) tf.Close() c = TCanvas('ctrl', 'ctrl', 2100, 1200) c.Divide(3, 2) for i, samp in enumerate(samples): pdfname = 'data_pdf_%s' % (samp) dsetname = 'data_%s' % (samp) plot(c.cd(i + 1), w, pdfname, dsetname) c.Update() c.Modified() c.Print("plots/ctrl.pdf") # Make the total pdf # First try and merge the different bits from the different workspaces ImportMCShapes(w) # now want to make the ctrl pdfs # signal and misrec are the same as b0 sig_cg = w.pdf('sig_mc_pdf_b0g').Clone('sig_mc_pdf_cg') getattr(w, 'import')(sig_cg) sig_cpi0 = w.pdf('sig_mc_pdf_b0pi0').Clone('sig_mc_pdf_cpi0') getattr(w, 'import')(sig_cpi0) misrec_cg = w.pdf('misrec_mc_pdf_b0g').Clone('misrec_mc_pdf_cg') getattr(w, 'import')(misrec_cg) misrec_cpi0 = w.pdf('misrec_mc_pdf_b0pi0').Clone('misrec_mc_pdf_cpi0') getattr(w, 'import')(misrec_cpi0) # ignore the lambdas for now # there will be some Bs0 -> D*0 piK stuff with a misID'd K (I think this is the big bit which appears below the peak) # do 1CB for this w.factory('dm_ctrl_misidk2pi[-150,-450,-50]') w.factory('sum::bdstkp_cg_mean( b0g_mean, dm_ctrl_misidk2pi)') w.factory('sum::bdstkp_cpi0_mean( b0pi0_mean, dm_ctrl_misidk2pi)') w.factory('bdstkp_cg_sigma[40,5,200]') w.factory('bdstkp_cpi0_sigma[40,5,200]') w.factory('bdstkp_c_alpha1[-2.1,-4,0]') w.factory('bdstkp_c_n1[3]') w.factory( 'CBShape::bdstkp_mc_pdf_cg( B_DTFDict_D0_B_M, bdstkp_cg_mean, bdstkp_cg_sigma, bdstkp_c_alpha1, bdstkp_c_n1 )' ) w.factory( 'CBShape::bdstkp_mc_pdf_cpi0( B_DTFDict_D0_B_M, bdstkp_cpi0_mean, bdstkp_cpi0_sigma, bdstkp_c_alpha1, bdstkp_c_n1 )' ) # the stuff above the peak is probably mostly B- -> D*0 pi- with another random pi so could get this shape and shift it w.factory('dm_ctrl_dstpi[100,10,300]') w.factory('sum::bdsth_cg_mean( bdsth_b0g_mean, dm_ctrl_dstpi )') w.factory('sum::bdsth_cpi0_mean( bdsth_b0pi0_mean, dm_ctrl_dstpi )') w.factory( "CBShape::bdsth_cg_cb1( B_DTFDict_D0_B_M, bdsth_cg_mean, bdsth_b0g_sigma, bdsth_alpha1, bdsth_n1 )" ) w.factory( "CBShape::bdsth_cg_cb2( B_DTFDict_D0_B_M, bdsth_cg_mean, bdsth_b0g_sigma, bdsth_alpha2, bdsth_n2 )" ) w.factory("SUM::bdsth_mc_pdf_cg( bdsth_f1*bdsth_cg_cb1, bdsth_cg_cb2 )") w.factory( "CBShape::bdsth_cpi0_cb1( B_DTFDict_D0_B_M, bdsth_cpi0_mean, bdsth_b0pi0_sigma, bdsth_alpha1, bdsth_n1 )" ) w.factory( "CBShape::bdsth_cpi0_cb2( B_DTFDict_D0_B_M, bdsth_cpi0_mean, bdsth_b0pi0_sigma, bdsth_alpha2, bdsth_n2 )" ) w.factory( "SUM::bdsth_mc_pdf_cpi0( bdsth_f1*bdsth_cpi0_cb1, bdsth_cpi0_cb2 )") # Then make combinatorial shape in each cateogry # let these be independent for now for samp in samples: w.factory("comb_mc_%s_p0[-0.001,-0.1,0.]" % samp) w.factory( "Exponential::comb_mc_pdf_%s( B_DTFDict_D0_B_M, comb_mc_%s_p0 )" % (samp, samp)) w.factory("%s_comb_y[3000,0,12000]" % samp) # Now need to figure out what yields to restrict # sig yield first (require b0 / bs ratio consistent between g and pi0) w.factory("b0g_sig_y[3000,0,12000]") w.factory("b0pi0_sig_y[800,0,4000]") w.factory("bs2b0_rat[2.5,1.,4.]") w.factory("prod::bsg_sig_y(b0g_sig_y, bs2b0_rat)") w.factory("prod::bspi0_sig_y(b0pi0_sig_y, bs2b0_rat)") w.factory("cg_sig_y[6000,0,32000]") w.factory("cpi0_sig_y[1000,0,8000]") # now mis rec yield (ratio of this to sig should be the same for b0 and bs but will be different for g vs pi0) w.factory("misrec_to_sig_rat_g[0.2,0.001,0.6]") w.factory("misrec_to_sig_rat_pi0[0.2,0.001,0.6]") w.factory("prod::b0g_misrec_y( misrec_to_sig_rat_g, b0g_sig_y )") w.factory("prod::b0pi0_misrec_y( misrec_to_sig_rat_pi0, b0pi0_sig_y )") w.factory("prod::bsg_misrec_y( misrec_to_sig_rat_g, bsg_sig_y )") w.factory("prod::bspi0_misrec_y( misrec_to_sig_rat_pi0, bspi0_sig_y )") w.factory("prod::cg_misrec_y( misrec_to_sig_rat_g, cg_sig_y )") w.factory("prod::cpi0_misrec_y( misrec_to_sig_rat_pi0, cpi0_sig_y )") # the cases of B->D*pipi, B->D*KK, Lb->D*ph all involve a misID so will # be different for B0 and Bs (as they differ with a K or pi misID) however # for all of these the ratio of g -> pi0 should be the same # there is also Bs->D*KK which should scale the same for g and pi0 modes w.factory("misid_g2pi0_rat[0.1,0.0001,10.]") w.factory("b0g_bdstpp_y[1000,0,12000]") w.factory("bsg_bdstpp_y[1000,0,12000]") w.factory("prod::b0pi0_bdstpp_y( misid_g2pi0_rat, b0g_bdstpp_y )") w.factory("prod::bspi0_bdstpp_y( misid_g2pi0_rat, bsg_bdstpp_y )") w.factory("b0g_bdstkk_y[1000,0,12000]") w.factory("bsg_bdstkk_y[1000,0,12000]") w.factory("prod::b0pi0_bdstkk_y( misid_g2pi0_rat, b0g_bdstkk_y )") w.factory("prod::bspi0_bdstkk_y( misid_g2pi0_rat, bsg_bdstkk_y )") w.factory("b0g_lbdstph_y[1000,0,12000]") w.factory("bsg_lbdstph_y[1000,0,12000]") w.factory("prod::b0pi0_lbdstph_y( misid_g2pi0_rat, b0g_lbdstph_y )") w.factory("prod::bspi0_lbdstph_y( misid_g2pi0_rat, bsg_lbdstph_y )") w.factory("bsdstkk_to_bdstkk_rat[1.,0.1,2.]") w.factory("prod::b0g_bsdstkk_y( bsdstkk_to_bdstkk_rat, b0g_bdstkk_y )") w.factory("prod::b0pi0_bsdstkk_y( bsdstkk_to_bdstkk_rat, b0pi0_bdstkk_y )") w.factory("prod::bsg_bsdstkk_y( bsdstkk_to_bdstkk_rat, bsg_bdstkk_y )") w.factory("prod::bspi0_bsdstkk_y( bsdstkk_to_bdstkk_rat, bspi0_bdstkk_y )") # B -> DKpi same logic as misrec w.factory("bdkp_to_sig_rat_g[0.2,0.001,0.6]") w.factory("bdkp_to_sig_rat_pi0[0.2,0.001,0.6]") w.factory("prod::b0g_bdkp_y( bdkp_to_sig_rat_g, b0g_sig_y )") w.factory("prod::b0pi0_bdkp_y( bdkp_to_sig_rat_pi0, b0pi0_sig_y )") w.factory("prod::bsg_bdkp_y( bdkp_to_sig_rat_g, bsg_sig_y )") w.factory("prod::bspi0_bdkp_y( bdkp_to_sig_rat_pi0, bspi0_sig_y )") # infact can be much more sophisitcated with efficiencies etc here # i.e. if the PID cut distinguishing B -> D0 Kpi from B -> D0 pipi is binary one knows the exact yield of the cross feed in each # the B -> DKp cross feed yield (float for now) w.factory("cg_bdstkp_y[3000,0,12000]") w.factory("cpi0_bdstkp_y[800,0,4000]") # B -> D* K / B -> D* pi (adding random pi- to B0 and random K- to Bs0) # so ratio to signal should be same for both g and pi0 modes but # different for B0 -> Bs w.factory("bdsth_to_sig_rat_addpi[0.2,0.001,0.6]") w.factory("bdsth_to_sig_rat_addk[0.2,0.001,0.6]") w.factory("prod::b0g_bdsth_y( bdsth_to_sig_rat_addpi, b0g_sig_y )") w.factory("prod::b0pi0_bdsth_y( bdsth_to_sig_rat_addpi, b0pi0_sig_y )") w.factory("prod::bsg_bdsth_y( bdsth_to_sig_rat_addk, bsg_sig_y )") w.factory("prod::bspi0_bdsth_y( bdsth_to_sig_rat_addk, bspi0_sig_y )") # the B- -> D* pi- (can probably constrain this better as well) w.factory("cg_bdsth_y[3000,0,12000]") w.factory("cpi0_bdsth_y[800,0,4000]") # Lb -> Dph (mid-ID k for p and pi for p and add random g or pi0) so will be different for all 4 really # express this ratio to the Lb -> D*ph one (they should be similar in magnitude?) w.factory("lbdph_to_lbdstph_b0g[1.,0.5,2.]") w.factory("lbdph_to_lbdstph_b0pi0[1.,0.5,2.]") w.factory("lbdph_to_lbdstph_bsg[1.,0.5,2.]") w.factory("lbdph_to_lbdstph_bspi0[1.,0.5,2.]") w.factory("prod::b0g_lbdph_y( lbdph_to_lbdstph_b0g, b0g_lbdstph_y )") w.factory("prod::b0pi0_lbdph_y( lbdph_to_lbdstph_b0pi0, b0pi0_lbdstph_y )") w.factory("prod::bsg_lbdph_y( lbdph_to_lbdstph_bsg, bsg_lbdstph_y )") w.factory("prod::bspi0_lbdph_y( lbdph_to_lbdstph_bspi0, bspi0_lbdstph_y )") # Part reco shape should have same Bs / B0 ratio w.factory("partrec_to_sig_rat_g[0.2,0.001,0.6]") w.factory("partrec_to_sig_rat_pi0[0.2,0.001,0.6]") w.factory("prod::b0g_partrec_y( partrec_to_sig_rat_g, b0g_sig_y )") w.factory("prod::b0pi0_partrec_y( partrec_to_sig_rat_pi0, b0pi0_sig_y )") w.factory("prod::bsg_partrec_y( partrec_to_sig_rat_g, bsg_sig_y )") w.factory("prod::bspi0_partrec_y( partrec_to_sig_rat_pi0, bspi0_sig_y )") # make the yields (different for ctrl and b0 / bs) b_components = [ 'sig', 'misrec', 'bdstpp', 'bdstkk', 'bsdstkk', 'bdkp', 'bdsth', 'partrec', 'lbdph', 'lbdstph', 'comb' ] for samp in ['b0g', 'b0pi0', 'bsg', 'bspi0']: fact_str = "SUM::data_pdf_%s(" % samp for comp in b_components: fact_str += "%s_%s_y*%s_mc_pdf_%s," % (samp, comp, comp, samp) fact_str = fact_str[:-1] + ")" w.factory(fact_str) w.pdf('data_pdf_%s' % samp).Print('v') ctrl_components = ['sig', 'misrec', 'bdstkp', 'bdsth', 'comb'] for samp in ['cg', 'cpi0']: fact_str = "SUM::data_pdf_%s(" % samp for comp in ctrl_components: fact_str += "%s_%s_y*%s_mc_pdf_%s," % (samp, comp, comp, samp) fact_str = fact_str[:-1] + ")" w.factory(fact_str) w.pdf('data_pdf_%s' % samp).Print('v') CreateSimPdf(w, 'data') CreateSimData(w, 'data') # Now fix appropriate parameters # To start with we'll fix all shape parameters from MC and just float the yields (and exponential slope) for comp in b_components: if comp == 'comb': continue # no pre-defined shape for combinatorial if comp == 'bsdstkk': continue # this params for this piece are covered by bdstkk w.set('%s_mc_sim_pdf_pars' % comp).setAttribAll("Constant") # Now relax the constraints on a few important params w.var("b0g_mean").setConstant(False) w.var("b0g_sigma").setConstant(False) #w.var("dm_b02bs").setConstant(False) #w.var("dm_g2pi0").setConstant(False) #w.var("ssig_b02bs").setConstant(False) #w.var("ssig_g2pi0").setConstant(False) #w.var("b0g_misrec_mean").setConstant(False) #w.var("b0g_misrec_sigma").setConstant(False) #w.var("dm_missg2addg").setConstant(False) #w.var("ssig_missg2addg").setConstant(False) w.Print('v') w.pdf('data_sim_pdf').Print('v') w.data('data_sim_data').Print('v') # free fit first if free: for i, samp in enumerate(samples): pdfname = 'data_pdf_%s' % (samp) dsetname = 'data_%s' % (samp) w.pdf(pdfname).fitTo( w.data(dsetname)) # nothing to fit in this case pars = w.pdf(pdfname).getParameters( RooArgSet(w.var("B_DTFDict_D0_B_M"))) w.saveSnapshot('data_free_fit_%s' % samp, pars) if sim: pdfname = 'data_sim_pdf' dsetname = 'data_sim_data' w.pdf(pdfname).fitTo(w.data(dsetname)) pars = w.pdf(pdfname).getParameters( RooArgSet(w.var("B_DTFDict_D0_B_M"))) w.saveSnapshot('data_sim_fit', pars) w.writeToFile('files/w_ctrl.root')
def DataFit(free=True, sim=True): w = RooWorkspace('w_data', 'w_data') samples = ['b0g', 'b0pi0', 'bsg', 'bspi0'] # create the category w.factory('cat[%s]' % (','.join(samples))) files = { 'b0g': path + "B0gamma/9_B2DstKpi_Dst2DgammTuple_BestCut.root", 'b0pi0': path + "B0pi0/9_B2Dstpi0Tuple_BestCut.root", 'bsg': path + "Bsgamma/9_Bs2DstKpi_Dst2DgammaTuple_BestCut.root", 'bspi0': path + "Bspi0/9_Bs2Dstpi0Tuple_BestCut.root" } # Make the dsets w.factory("B_DTFDict_D0_B_M[5100,5900]") w.var("B_DTFDict_D0_B_M").setBins(80) for samp in samples: assert (os.path.exists(files[samp])) tf = TFile(files[samp]) t = tf.Get('DecayTree') t.SetBranchStatus("*", 0) t.SetBranchStatus("B_DTFDict_D0_B_M", 1) dset = RooDataSet("data_%s" % (samp), "", t, RooArgSet(w.var("B_DTFDict_D0_B_M"))) getattr(w, 'import')(dset) tf.Close() # Make the total pdf # First try and merge the different bits from the different workspaces ImportMCShapes(w) # Then make combinatorial shape in each cateogry # let these be independent for now for samp in samples: w.factory("comb_mc_%s_p0[-0.001,-0.1,0.]" % samp) w.factory( "Exponential::comb_mc_pdf_%s( B_DTFDict_D0_B_M, comb_mc_%s_p0 )" % (samp, samp)) w.factory("%s_comb_y[3000,0,12000]" % samp) # Now need to figure out what yields to restrict # sig yield first (require b0 / bs ratio consistent between g and pi0) w.factory("b0g_sig_y[3000,0,12000]") w.factory("b0pi0_sig_y[800,0,4000]") w.factory("bs2b0_rat[2.5,1.,4.]") w.factory("prod::bsg_sig_y(b0g_sig_y, bs2b0_rat)") w.factory("prod::bspi0_sig_y(b0pi0_sig_y, bs2b0_rat)") # now mis rec yield (ratio of this to sig should be the same for b0 and bs but will be different for g vs pi0) w.factory("misrec_to_sig_rat_g[0.2,0.001,0.6]") w.factory("misrec_to_sig_rat_pi0[0.2,0.001,0.6]") w.factory("prod::b0g_misrec_y( misrec_to_sig_rat_g, b0g_sig_y )") w.factory("prod::b0pi0_misrec_y( misrec_to_sig_rat_pi0, b0pi0_sig_y )") w.factory("prod::bsg_misrec_y( misrec_to_sig_rat_g, bsg_sig_y )") w.factory("prod::bspi0_misrec_y( misrec_to_sig_rat_pi0, bspi0_sig_y )") # the cases of B->D*pipi, B->D*KK, Lb->D*ph all involve a misID so will # be different for B0 and Bs (as they differ with a K or pi misID) however # for all of these the ratio of g -> pi0 should be the same # there is also Bs->D*KK which should scale the same for g and pi0 modes w.factory("misid_g2pi0_rat[0.1,0.0001,10.]") w.factory("b0g_bdstpp_y[1000,0,12000]") w.factory("bsg_bdstpp_y[1000,0,12000]") w.factory("prod::b0pi0_bdstpp_y( misid_g2pi0_rat, b0g_bdstpp_y )") w.factory("prod::bspi0_bdstpp_y( misid_g2pi0_rat, bsg_bdstpp_y )") w.factory("b0g_bdstkk_y[1000,0,12000]") w.factory("bsg_bdstkk_y[1000,0,12000]") w.factory("prod::b0pi0_bdstkk_y( misid_g2pi0_rat, b0g_bdstkk_y )") w.factory("prod::bspi0_bdstkk_y( misid_g2pi0_rat, bsg_bdstkk_y )") w.factory("b0g_lbdstph_y[1000,0,12000]") w.factory("bsg_lbdstph_y[1000,0,12000]") w.factory("prod::b0pi0_lbdstph_y( misid_g2pi0_rat, b0g_lbdstph_y )") w.factory("prod::bspi0_lbdstph_y( misid_g2pi0_rat, bsg_lbdstph_y )") w.factory("bsdstkk_to_bdstkk_rat[1.,0.1,2.]") w.factory("prod::b0g_bsdstkk_y( bsdstkk_to_bdstkk_rat, b0g_bdstkk_y )") w.factory("prod::b0pi0_bsdstkk_y( bsdstkk_to_bdstkk_rat, b0pi0_bdstkk_y )") w.factory("prod::bsg_bsdstkk_y( bsdstkk_to_bdstkk_rat, bsg_bdstkk_y )") w.factory("prod::bspi0_bsdstkk_y( bsdstkk_to_bdstkk_rat, bspi0_bdstkk_y )") # B -> DKpi same logic as misrec w.factory("bdkp_to_sig_rat_g[0.2,0.001,0.6]") w.factory("bdkp_to_sig_rat_pi0[0.2,0.001,0.6]") w.factory("prod::b0g_bdkp_y( bdkp_to_sig_rat_g, b0g_sig_y )") w.factory("prod::b0pi0_bdkp_y( bdkp_to_sig_rat_pi0, b0pi0_sig_y )") w.factory("prod::bsg_bdkp_y( bdkp_to_sig_rat_g, bsg_sig_y )") w.factory("prod::bspi0_bdkp_y( bdkp_to_sig_rat_pi0, bspi0_sig_y )") # B -> D* K / B -> D* pi (adding random pi- to B0 and random K- to Bs0) # so ratio to signal should be same for both g and pi0 modes but # different for B0 -> Bs w.factory("bdsth_to_sig_rat_addpi[0.2,0.001,0.6]") w.factory("bdsth_to_sig_rat_addk[0.2,0.001,0.6]") w.factory("prod::b0g_bdsth_y( bdsth_to_sig_rat_addpi, b0g_sig_y )") w.factory("prod::b0pi0_bdsth_y( bdsth_to_sig_rat_addpi, b0pi0_sig_y )") w.factory("prod::bsg_bdsth_y( bdsth_to_sig_rat_addk, bsg_sig_y )") w.factory("prod::bspi0_bdsth_y( bdsth_to_sig_rat_addk, bspi0_sig_y )") # Lb -> Dph (mid-ID k for p and pi for p and add random g or pi0) so will be different for all 4 really # express this ratio to the Lb -> D*ph one (they should be similar in magnitude?) w.factory("lbdph_to_lbdstph_b0g[1.,0.5,2.]") w.factory("lbdph_to_lbdstph_b0pi0[1.,0.5,2.]") w.factory("lbdph_to_lbdstph_bsg[1.,0.5,2.]") w.factory("lbdph_to_lbdstph_bspi0[1.,0.5,2.]") w.factory("prod::b0g_lbdph_y( lbdph_to_lbdstph_b0g, b0g_lbdstph_y )") w.factory("prod::b0pi0_lbdph_y( lbdph_to_lbdstph_b0pi0, b0pi0_lbdstph_y )") w.factory("prod::bsg_lbdph_y( lbdph_to_lbdstph_bsg, bsg_lbdstph_y )") w.factory("prod::bspi0_lbdph_y( lbdph_to_lbdstph_bspi0, bspi0_lbdstph_y )") # Part reco shape should have same Bs / B0 ratio w.factory("partrec_to_sig_rat_g[0.2,0.001,0.6]") w.factory("partrec_to_sig_rat_pi0[0.2,0.001,0.6]") w.factory("prod::b0g_partrec_y( partrec_to_sig_rat_g, b0g_sig_y )") w.factory("prod::b0pi0_partrec_y( partrec_to_sig_rat_pi0, b0pi0_sig_y )") w.factory("prod::bsg_partrec_y( partrec_to_sig_rat_g, bsg_sig_y )") w.factory("prod::bspi0_partrec_y( partrec_to_sig_rat_pi0, bspi0_sig_y )") components = [ 'sig', 'misrec', 'bdstpp', 'bdstkk', 'bsdstkk', 'bdkp', 'bdsth', 'partrec', 'lbdph', 'lbdstph', 'comb' ] for samp in samples: fact_str = "SUM::data_pdf_%s(" % samp for comp in components: fact_str += "%s_%s_y*%s_mc_pdf_%s," % (samp, comp, comp, samp) fact_str = fact_str[:-1] + ")" w.factory(fact_str) w.pdf('data_pdf_%s' % samp).Print('v') CreateSimPdf(w, 'data') CreateSimData(w, 'data') # Now fix appropriate parameters # To start with we'll fix all shape parameters from MC and just float the yields (and exponential slope) for comp in components: if comp == 'comb': continue # no pre-defined shape for combinatorial if comp == 'bsdstkk': continue # this params for this piece are covered by bdstkk w.set('%s_mc_sim_pdf_pars' % comp).setAttribAll("Constant") # Now relax the constraints on a few important params w.var("b0g_mean").setConstant(False) w.var("b0g_sigma").setConstant(False) #w.var("dm_b02bs").setConstant(False) #w.var("dm_g2pi0").setConstant(False) #w.var("ssig_b02bs").setConstant(False) #w.var("ssig_g2pi0").setConstant(False) #w.var("b0g_misrec_mean").setConstant(False) #w.var("b0g_misrec_sigma").setConstant(False) #w.var("dm_missg2addg").setConstant(False) #w.var("ssig_missg2addg").setConstant(False) w.Print('v') w.pdf('data_sim_pdf').Print('v') w.data('data_sim_data').Print('v') # free fit first if free: for i, samp in enumerate(samples): pdfname = 'data_pdf_%s' % (samp) dsetname = 'data_%s' % (samp) w.pdf(pdfname).fitTo( w.data(dsetname)) # nothing to fit in this case pars = w.pdf(pdfname).getParameters( RooArgSet(w.var("B_DTFDict_D0_B_M"))) w.saveSnapshot('data_free_fit_%s' % samp, pars) if sim: pdfname = 'data_sim_pdf' dsetname = 'data_sim_data' w.pdf(pdfname).fitTo(w.data(dsetname)) pars = w.pdf(pdfname).getParameters( RooArgSet(w.var("B_DTFDict_D0_B_M"))) w.saveSnapshot('data_sim_fit', pars) w.writeToFile('files/w_data.root')
def plotStuff(plotList,plotstring, cutstring, plotfile, plotname, xlabel, ylabel, unitnorm): isFirst = True w = RooWorkspace("w") w.factory("x[-100,100]") for dataset in plotList: dataset[0].Draw(plotstring.format(dataset[1]),cutstring,"goff") hist = gDirectory.Get(dataset[1]) data=RooDataHist(dataset[1],dataset[1],RooArgList(w.var("x")),hist) getattr(w,'import')(data) w.factory("HistPdf::triPdf(x,tri)") w.factory("HistPdf::wabPdf(x,wab)") w.factory("prod::triscale(a[0.3,0,10],{0})".format(w.data("tri").sum(False))) w.factory("prod::wabscale(b[0.1,0,10],{0})".format(w.data("wab").sum(False))) w.factory("SUM::sumModel(triscale*triPdf,wabscale*wabPdf)") w.pdf("sumModel").fitTo(w.data("data"),RooFit.SumW2Error(True),RooFit.Extended(True), RooFit.Verbose(False),RooFit.PrintLevel(-1)) #w.pdf("sumModel").fitTo(w.data("data"),RooFit.Extended(True)) #w.pdf("sumModel").fitTo(w.data("data")) frame=w.var("x").frame() w.data("data").plotOn(frame) #w.pdf("triPdf").plotOn(frame) #w.pdf("wabPdf").plotOn(frame) w.pdf("sumModel").plotOn(frame) w.pdf("sumModel").paramOn(frame) frame.SetTitle(gDirectory.Get("data").GetTitle()) frame.Draw() c.Print(plotfile) c.Clear() dataHist = gDirectory.Get("data") triHist = gDirectory.Get("tri") wabHist = gDirectory.Get("wab") if legendright: leg = TLegend(0.7,0.75,0.9,0.9) else: leg = TLegend(0.1,0.75,0.3,0.9) hs = THStack("hs",plotname); for dataset in plotList: hist = gDirectory.Get(dataset[1]) #hist.Sumw2() if unitnorm: hist.Scale(1.0/hist.Integral()) else: hist.Scale(1.0/dataset[2]) print "{0} {1} {2}".format(plotname,dataset[4],hist.Integral()) hist.SetLineColor(dataset[3]) leg.AddEntry(hist,dataset[4]) hs.Add(hist) #hist.GetXaxis().SetTitle(xlabel) hist.GetYaxis().SetTitle(ylabel) #if isFirst: #hist.GetXaxis().SetTitle(xlabel) #hist.GetYaxis().SetTitle(ylabel) #hist.Draw() #else: #hist.Draw("same") isFirst = False sumHist = triHist.Clone("sum") sumHist.Add(wabHist) if unitnorm: sumHist.Scale(1.0/sumHist.Integral()) sumHist.SetLineColor(6) leg.AddEntry(sumHist,"MC sum") hs.Add(sumHist) hs.Draw("nostack") hs.GetXaxis().SetTitle(xlabel) hs.GetYaxis().SetTitle(ylabel) leg.Draw() c.Print(plotfile)
if tree.itype == -88: mc.add(getattr(ws,'set')('observables')) if tree.itype == 72 or tree.itype == 82: data.add(getattr(ws,'set')('observables')) getattr(ws,'import')(mc) getattr(ws,'import')(data) ws.Print() ws.factory("mean[5200,5300]") ws.factory("CBShape:sig_cb1(mass,mean,sigma_1[10,200],alpha_1[0,1.],n_1[0.,50.])"); ws.factory("CBShape:sig_cb2(mass,mean,sigma_2[10,200],alpha_2[-1.,0.],n_2[0.,50.])"); ws.factory("SUM::mcsig( f[0.5,0,1]*sig_cb1, sig_cb2)"); ws.pdf("mcsig").fitTo(ws.data("mc")) mcplot = ws.var("mass").frame() ws.data("mc").plotOn(mcplot) ws.pdf("mcsig").plotOn(mcplot) # freeze obs argset = ws.pdf("mcsig").getParameters(RooArgSet(ws.var("mass"))) ws.defineSet("signal_params",argset) #RooArgSet(getattr(ws,'set')("signal_params")).setAttribAll("Constant") ws.factory("Exponential:bkg(mass,exp_p1[-0.02,0.])") ws.factory("SUM:pdf( sig_y[0,1000]*mcsig, bkg_y[0,2000]*bkg )") ws.pdf("pdf").fitTo(ws.data("data"))
class Wjj2DFitter: def __init__ (self, pars): self.pars = pars self.ws = RooWorkspace('wjj2dfitter') self.utils = Wjj2DFitterUtils(self.pars) self.useImportPars = False self.rangeString = None obs = [] for v in self.pars.var: try: vName = self.pars.varNames[v] except AttributeError: vName = v obs.append(vName) var1 = self.ws.factory('%s[%f,%f]' % (vName, self.pars.varRanges[v][1], self.pars.varRanges[v][2]) ) var1.setUnit('GeV') try: var1.SetTitle(self.pars.varTitles[v]) except AttributeError: var1.SetTitle('m_{jj}') var1.setPlotLabel(var1.GetTitle()) if len(self.pars.varRanges[v][3]) > 1: vbinning = RooBinning(len(self.pars.varRanges[v][3]) - 1, array('d', self.pars.varRanges[v][3]), '%sBinning' % vName) var1.setBinning(vbinning) else: var1.setBins(self.pars.varRanges[v][0]) var1.Print() if v in self.pars.exclude: var1.setRange('signalRegion', self.pars.exclude[v][0], self.pars.exclude[v][1]) var1.setRange('lowSideband', var1.getMin(), self.pars.exclude[v][0]) var1.setRange('highSideband', self.pars.exclude[v][1], var1.getMax()) self.rangeString = 'lowSideband,highSideband' self.ws.defineSet('obsSet', ','.join(obs)) def loadDataFromWorkspace(self, other, cut = None): #pull unbinned data from other workspace unbinnedData = other.data('data_unbinned') if not unbinnedData: unbinnedData = other.data('data_obs') if cut: unbinnedData = unbinnedData.reduce(cut) unbinnedData.Print() if self.pars.binData: #bin and import data unbinnedData.SetName('data_unbinned') getattr(self.ws, 'import')(unbinnedData) data = RooDataHist('data_obs', 'data_obs', other.set('obsSet'), unbinnedData) getattr(self.ws, 'import')(data) else: #just import data unbinnedData.SetName('data_obs') getattr(self.ws, 'import')(unbinnedData) def loadHistogramsFromWorkspace(self, other): #pull RooHist pdfs from other workspace pdfs = other.allPdfs() pdfIter = pdfs.createIterator() pdf = pdfIter.Next() while pdf: if pdf.IsA().InheritsFrom('RooHistPdf'): print 'importing',pdf.GetName(),'from old workspace' getattr(self.ws, 'import')(pdf) pdf = pdfIter.Next() def loadWorkspaceFromFile(self, filename, wsname = 'w', getFloatPars = True): print 'loading data workspace %s from file %s' % (wsname, filename) fin = TFile.Open(filename) if not fin: print 'failed to open the file',filename import os print 'cwd:',os.getcwd() print 'access of',filename,os.access(filename, os.R_OK) print 'list of root files in cwd' for f in os.listdir(os.getcwd()): if f[-5:] == '.root': print f,len(f),len(filename) fin = TFile.Open(os.getcwd() + '/' + filename) assert(fin) other = fin.Get(wsname) #pull unbinned data from other workspace self.loadDataFromWorkspace(other) #pull in histogram pdfs to save time self.loadHistogramsFromWorkspace(other) if getFloatPars and other.loadSnapshot('fitPars'): self.useImportPars = True self.ws.saveSnapshot('importParams', other.set('floatingParams'), True) # self.ws.Print() # put together a fitting model and return the pdf def makeFitter(self, useAlternateModels = False): if self.ws.pdf('total'): return self.ws.pdf('total') compPdfs = [] for component in self.pars.backgrounds: # print 'getting compModels' compModels = getattr(self.pars, '%sModels' % component) if hasattr(self.pars, '%sConvModels' % component): convModels = getattr(self.pars, '%sConvModels' % component) else: convModels = None if useAlternateModels: print 'loading Alternate Models' compModels = getattr(self.pars, '%sModelsAlt' % component) convModels = getattr(self.pars, '%sConvModelsAlt' % component) # print 'compModels = %s' % compModels compFiles = getattr(self.pars, '%sFiles' % component) compPdf = self.makeComponentPdf(component, compFiles, compModels, useAlternateModels, convModels) norm = self.ws.factory('prod::f_%s_norm' % component + \ '(n_%s[0.,1e6],' % component + \ '%s_nrm[1.,-0.5,5.])' % component) self.ws.var('n_%s' % component).setConstant(True) if hasattr(self, '%sExpected' % component): self.ws.var('n_%s' % component).setVal( getattr(self, '%sExpected' % component)) compPdfs.append( self.ws.factory('RooExtendPdf::%s_extended(%s,%s)' % \ (compPdf.GetName(), compPdf.GetName(), norm.GetName()) ) ) self.ws.factory('r_signal[0., -200., 200.]') self.ws.var('r_signal').setConstant(False) try: obs = [ self.pars.varNames[x] for x in self.pars.var ] except AttributeError: obs = self.pars.var for component in self.pars.signals: compFile = getattr(self.pars, '%sFiles' % component) compModels = getattr(self.pars, '%sModels' % component) if hasattr(self.pars, '%sConvModels' % component): convModels = getattr(self.pars, '%sConvModels' % component) else: convModels = None compPdf = self.makeComponentPdf(component, compFiles, compModels, useAlternateModels, convModels) norm = self.ws.factory( "prod::f_%s_norm(n_%s[0., 1e6],r_signal)" % \ (component, component) ) self.ws.var('n_%s' % component).setConstant(True) if hasattr(self, '%sExpected' % component): self.ws.var('n_%s' % component).setVal( getattr(self, '%sExpected' % component)) pdf = self.ws.factory('RooExtendPdf::%s_extended(%s,%s)' % \ (compPdf.GetName(), compPdf.GetName(), norm.GetName()) ) if (hasattr(self.pars, '%sInterference' % component)) and \ getattr(self.pars, '%sInterference' % component): getattr(self.ws, 'import') \ (pdf, RooFit.RenameAllNodes('interf_%sUp' % component), RooFit.RenameAllVariablesExcept('interf_%sUp' % component, ','.join(obs)), RooFit.Silence() ) getattr(self.ws, 'import') \ (pdf, RooFit.RenameAllNodes('interf_%sDown' % component), RooFit.RenameAllVariablesExcept('interf_%sDown'%component, ','.join(obs)), RooFit.Silence() ) if self.pars.includeSignal: compPdfs.append(pdf) #print compPdfs prodList = [ '%s' % (pdf.GetName()) \ for (idx, pdf) in enumerate(compPdfs) ] comps = RooArgList(self.ws.argSet(','.join(prodList))) getattr(self.ws, 'import')(RooAddPdf('total', 'total', comps)) return self.ws.pdf('total') # define the constraints on the yields, etc that will be part of the fit. def makeConstraints(self): if self.ws.set('constraintSet'): return self.ws.set('constraintSet') constraints = [] constrainedParameters = [] for constraint in self.pars.yieldConstraints: theYield = self.ws.var('%s_nrm' % constraint) if not theYield.isConstant(): self.ws.factory('RooGaussian::%s_const(%s, 1.0, %f)' % \ (constraint, theYield.GetName(), self.pars.yieldConstraints[constraint]) ) constraints.append('%s_const' % constraint) constrainedParameters.append(theYield.GetName()) if hasattr(self.pars, 'constrainShapes'): for component in self.pars.constrainShapes: pc = self.ws.pdf(component).getParameters(self.ws.set('obsSet')) parIter = pc.createIterator() par = parIter.Next() while par: if not par.isConstant(): theConst = self.ws.factory('RooGaussian::%s_const' % \ (par.GetName()) + \ '(%s, %f, %f)' % \ (par.GetName(), par.getVal(), par.getError()) ) constraints.append(theConst.GetName()) constrainedParameters.append(par.GetName()) par = parIter.Next() pc.IsA().Destructor(pc) self.ws.defineSet('constraintSet', ','.join(constraints)) self.ws.defineSet('constrainedSet', ','.join(constrainedParameters)) return self.ws.set('constraintSet') # fit the data using the pdf def fit(self, keepParameterValues = False): print 'construct fit pdf ...' fitter = self.makeFitter() print 'load data ...' data = self.loadData() self.resetYields() constraintSet = self.makeConstraints() if not keepParameterValues: self.readParametersFromFile() self.resetYields() # print constraints, self.pars.yieldConstraints print '\nfit constraints' constIter = constraintSet.createIterator() constraint = constIter.Next() constraints = [] while constraint: constraint.Print() constraints.append(constraint.GetName()) constraint = constIter.Next() constraintCmd = RooCmdArg.none() if constraintSet.getSize() > 0: constraints.append(fitter.GetName()) fitter = self.ws.pdf('totalFit_const') if not fitter: fitter = self.ws.factory('PROD::totalFit_const(%s)' % \ (','.join(constraints)) ) constraintCmd = RooFit.Constrained() # constraintCmd = RooFit.ExternalConstraints(self.ws.set('constraintSet')) if self.useImportPars: self.ws.loadSnapshot('importParams') self.ws.Print() # for constraint in pars.constraints: # self.ws.pdf(constraint).Print() # print rangeCmd = RooCmdArg.none() if self.rangeString and self.pars.doExclude: rangeCmd = RooFit.Range(self.rangeString) print 'fitting ...' fr = fitter.fitTo(data, RooFit.Save(True), RooFit.Extended(True), RooFit.Minos(False), RooFit.PrintEvalErrors(-1), RooFit.Warnings(False), constraintCmd, rangeCmd) fr.Print() return fr # determine the fitting model for each component and return them def makeComponentPdf(self, component, files, models, useAlternateModels, convModels): print 'making ComponentPdf %s' % component # print 'models = %s' % models # print 'files = %s' % files if convModels and not (convModels[0] == -1): thePdf = self.makeConvolvedPdf(component, files, models, useAlternateModels, convModels) elif (models[0] == -1): thePdf = self.makeComponentHistPdf(component, files) elif (models[0] == -2): thePdf = self.makeMorphingPdf(component, useAlternateModels, convModels) elif (models[0] == -3): pass else: thePdf = self.makeComponentAnalyticPdf(component, models, useAlternateModels) return thePdf #create a simple 2D histogram pdf def makeComponentHistPdf(self, component, files): if self.ws.pdf(component): return self.ws.pdf(component) compHist = self.utils.newEmptyHist('hist%s' % component) sumYields = 0. sumxsec = 0. sumExpected = 0. for (idx,fset) in enumerate(files): if hasattr(self.pars, '%scuts' % component): cutOverride = getattr(self.pars, '%scuts' % component) else: cutOverride = None filename = fset[0] tmpHist = self.utils.File2Hist(filename, 'hist%s_%i' % (component, idx), False,cutOverride,False,True,0) sumYields += tmpHist.Integral() sumxsec += fset[2] compHist.Add(tmpHist, self.pars.integratedLumi*fset[2]/fset[1]) sumExpected += tmpHist.Integral()*fset[2]* \ self.pars.integratedLumi/fset[1] print filename,'acc x eff: %.3g' % (tmpHist.Integral()/fset[1]) print filename,'N_expected: %.1f' % \ (tmpHist.Integral()*fset[2]*self.pars.integratedLumi/fset[1]) #tmpHist.Print() #compHist.Print() print '%s acc x eff: %.3g' % \ (component, sumExpected/sumxsec/self.pars.integratedLumi) print 'Number of expected %s events: %.1f' % (component, sumExpected) setattr(self, '%sExpected' % component, sumExpected) return self.utils.Hist2Pdf(compHist, component, self.ws, self.pars.order) #create a pdf which is a convolution of any two pdf def makeConvolvedPdf(self, component, files, models, useAlternateModels, convModels): if self.ws.pdf(component): return self.ws.pdf(component) #If a morphing model is selected, then convolve each individual component first and then morph if (models[0] == -2): return self.makeMorphingPdf(component, useAlternateModels, convModels) basePdf = self.makeComponentPdf('%s_base' % component, files, models, useAlternateModels, [-1]) convComponent = 'Global' ##Overwrite to use the same convolution model for all Pdfs convModel = getattr(self.pars, '%sConvModels' % convComponent) if useAlternateModels: convModel = getattr(self.pars, '%sConvModelsAlt' % convComponent) convPdf = self.makeComponentPdf('%s_conv' % convComponent, files, convModel, useAlternateModels, [-1]) var = self.pars.var[0] try: vName = self.pars.varNames[var] except AttributeError: vName = var self.ws.factory('RooFFTConvPdf::%s(%s,%s,%s)' % \ (component, vName, basePdf.GetName(), convPdf.GetName())) return self.ws.pdf(component) # create a pdf using the "template morphing" technique def makeMorphingPdf(self, component, useAlternateModels, convModels): if self.ws.pdf(component): return self.ws.pdf(component) filesNom = getattr(self.pars, '%s_NomFiles' % component) modelsNom = getattr(self.pars, '%s_NomModels' % component) filesMU = getattr(self.pars, '%s_MUFiles' % component) modelsMU = getattr(self.pars, '%s_MUModels' % component) filesMD = getattr(self.pars, '%s_MDFiles' % component) modelsMD = getattr(self.pars, '%s_MDModels' % component) filesSU = getattr(self.pars, '%s_SUFiles' % component) modelsSU = getattr(self.pars, '%s_SUModels' % component) filesSD = getattr(self.pars, '%s_SDFiles' % component) modelsSD = getattr(self.pars, '%s_SDModels' % component) if useAlternateModels: modelsNom = getattr(self.pars, '%s_NomModelsAlt' % component) modelsMU = getattr(self.pars, '%s_MUModelsAlt' % component) modelsMD = getattr(self.pars, '%s_MDModelsAlt' % component) modelsSU = getattr(self.pars, '%s_SUModelsAlt' % component) modelsSD = getattr(self.pars, '%s_SDModelsAlt' % component) # Adds five (sub)components for the component with suffixes Nom, MU, MD, SU, SD NomPdf = self.makeComponentPdf('%s_Nom' % component, filesNom, modelsNom, False, convModels) if hasattr(self, '%s_NomExpected' % component): setattr(self, '%sExpected' % component, getattr(self, '%s_NomExpected' % component)) MUPdf = self.makeComponentPdf('%s_MU' % component, filesMU, modelsMU, False, convModels) MDPdf = self.makeComponentPdf('%s_MD' % component, filesMD, modelsMD, False, convModels) SUPdf = self.makeComponentPdf('%s_SU' % component, filesSU, modelsSU, False, convModels) SDPdf = self.makeComponentPdf('%s_SD' % component, filesSD, modelsSD, False, convModels) fMU_comp = self.ws.factory("fMU_%s[0., -1., 1.]" % component) fSU_comp = self.ws.factory("fSU_%s[0., -1., 1.]" % component) fMU = RooFormulaVar("f_fMU_%s" % component, "1.0*@0*(@0 >= 0.)", RooArgList( fMU_comp ) ) fMD = RooFormulaVar("f_fMD_%s" % component, "-1.0*@0*(@0 < 0.)", RooArgList( fMU_comp ) ) fSU = RooFormulaVar("f_fSU_%s" % component, "@0*(@0 >= 0.)", RooArgList( fSU_comp ) ) fSD = RooFormulaVar("f_fSD_%s" % component, "@0*(-1)*(@0 < 0.)", RooArgList( fSU_comp ) ) fNom = RooFormulaVar("f_fNom_%s" % component, "(1.-abs(@0)-abs(@1))", RooArgList(fMU_comp,fSU_comp) ) morphPdf = RooAddPdf(component,component, RooArgList(MUPdf,MDPdf,SUPdf,SDPdf,NomPdf), RooArgList(fMU, fMD, fSU, fSD, fNom)) morphPdf.SetName(component) getattr(self.ws, 'import')(morphPdf) return self.ws.pdf(component) # create a pdf using an analytic function. def makeComponentAnalyticPdf(self, component, models, useAlternateModels): if self.ws.pdf(component): return self.ws.pdf(component) pdfList = [] for (idx,model) in enumerate(models): var = self.pars.var[idx] try: vName = self.pars.varNames[var] except AttributeError: vName = var auxModel = None if useAlternateModels: if hasattr(self.pars, '%sAuxModelsAlt' % component): auxModel = getattr(self.pars, '%sAuxModelsAlt' % component)[idx] else: if hasattr(self.pars, '%sAuxModels' % component): auxModel = getattr(self.pars, '%sAuxModels' % component)[idx] pdfList.append(self.utils.analyticPdf(self.ws, vName, model, '%s_%s'%(component,vName), '%s_%s'%(component,vName), auxModel ) ) pdfListNames = [ pdf.GetName() for pdf in pdfList ] if len(pdfList) > 1: self.ws.factory('PROD::%s(%s)' % \ (component, ','.join(pdfListNames))) else: pdfList[0].SetName(component) return self.ws.pdf(component) def loadData(self, weight = False): if self.ws.data('data_obs'): return self.ws.data('data_obs') unbinnedName = 'data_obs' if self.pars.binData: unbinnedName = 'data_unbinned' data = self.utils.File2Dataset(self.pars.DataFile, unbinnedName, self.ws, weighted = weight) if self.pars.binData: data = RooDataHist('data_obs', 'data_obs', self.ws.set('obsSet'), data) getattr(self.ws, 'import')(data) data = self.ws.data('data_obs') return data def stackedPlot(self, var, logy = False, pdfName = None, Silent = False): if not pdfName: pdfName = 'total' xvar = self.ws.var(var) nbins = xvar.getBins() if hasattr(self.pars, 'plotRanges'): xvar.setRange('plotRange', self.pars.plotRanges[var][1], self.pars.plotRanges[var][2]) xvar.setBins(self.pars.plotRanges[var][0], 'plotBins') else: xvar.setRange('plotRange', xvar.getMin(), xvar.getMax()) xvar.setBins(nbins, 'plotBins') sframe = xvar.frame() sframe.SetName("%s_stacked" % var) pdf = self.ws.pdf(pdfName) if isinstance(pdf, RooAddPdf): compList = RooArgList(pdf.pdfList()) else: compList = None data = self.ws.data('data_obs') nexp = pdf.expectedEvents(self.ws.set('obsSet')) if not Silent: print pdf.GetName(),'expected: %.0f' % (nexp) print 'data events: %.0f' % (data.sumEntries()) if nexp < 1: nexp = data.sumEntries() theComponents = [] if self.pars.includeSignal: theComponents += self.pars.signals theComponents += self.pars.backgrounds data.plotOn(sframe, RooFit.Invisible(), RooFit.Binning('plotBins')) # dataHist = RooAbsData.createHistogram(data,'dataHist_%s' % var, xvar, # RooFit.Binning('%sBinning' % var)) # #dataHist.Scale(1., 'width') # invData = RooHist(dataHist, 1., 1, RooAbsData.SumW2, 1.0, False) # #invData.Print('v') # sframe.addPlotable(invData, 'pe', True, True) for (idx,component) in enumerate(theComponents): if not Silent: print 'plotting',component,'...', if hasattr(self.pars, '%sPlotting' % (component)): plotCharacteristics = getattr(self.pars, '%sPlotting' % \ (component)) else: plotCharacteristics = {'color' : colorwheel[idx%6], 'title' : component } compCmd = RooCmdArg.none() if compList: compSet = RooArgSet(compList) if compSet.getSize() > 0: compCmd = RooFit.Components(compSet) removals = compList.selectByName('%s*' % component) compList.remove(removals) if not Silent: print 'events', self.ws.function('f_%s_norm' % component).getVal() sys.stdout.flush() if abs(self.ws.function('f_%s_norm' % component).getVal()) >= 1.: pdf.plotOn(sframe, #RooFit.ProjWData(data), RooFit.DrawOption('LF'), RooFit.FillStyle(1001), RooFit.FillColor(plotCharacteristics['color']), RooFit.LineColor(plotCharacteristics['color']), RooFit.VLines(), RooFit.Range('plotRange'), RooFit.NormRange('plotRange'), RooFit.Normalization(nexp, RooAbsReal.NumEvent), compCmd ) tmpCurve = sframe.getCurve() tmpCurve.SetName(component) tmpCurve.SetTitle(plotCharacteristics['title']) if 'visible' in plotCharacteristics: sframe.setInvisible(component, plotCharacteristics['visible']) data.plotOn(sframe, RooFit.Name('theData'), RooFit.Binning('plotBins')) sframe.getHist('theData').SetTitle('data') # theData = RooHist(dataHist, 1., 1, RooAbsData.SumW2, 1.0, True) # theData.SetName('theData') # theData.SetTitle('data') # sframe.addPlotable(theData, 'pe') if (logy): sframe.SetMinimum(0.01) sframe.SetMaximum(1.0e6) else: sframe.SetMaximum(sframe.GetMaximum()*1.35) pass excluded = (var in self.pars.exclude) bname = var if not excluded: for v in self.pars.exclude: if hasattr(self.pars, 'varNames') and \ (self.pars.varNames[v] == var): excluded = True bname = v if excluded: blinder = TBox(self.pars.exclude[bname][0], sframe.GetMinimum(), self.pars.exclude[bname][1], sframe.GetMaximum()) # blinder.SetName('blinder') # blinder.SetTitle('signal region') blinder.SetFillColor(kBlack) if self.pars.blind: blinder.SetFillStyle(1001) else: blinder.SetFillStyle(0) blinder.SetLineStyle(2) sframe.addObject(blinder) elif self.pars.blind: if not Silent: print "blind but can't find exclusion region for", var print 'excluded',excluded,self.pars.exclude print 'hiding data points' sframe.setInvisible('theData', True) #sframe.GetYaxis().SetTitle('Events / GeV') # dataHist.IsA().Destructor(dataHist) if not Silent: print xvar.setBins(nbins) return sframe def readParametersFromFile(self, fname=None): if (not fname): fname = self.pars.initialParametersFile if isinstance(fname, str): flist = [ fname ] else: flist = fname for tmpName in flist: if len(tmpName) > 0: print 'loading parameters from file',tmpName self.ws.allVars().readFromFile(tmpName) def expectedFromPars(self): components = self.pars.signals + self.pars.backgrounds for component in components: theYield = self.ws.var('n_%s' % component) setattr(self, '%sExpected' % component, theYield.getVal()) def initFromExplicitVals(self,opts): #,init_diboson= -1.0,init_WpJ=-1.0,init_top=-1.0,init_ZpJ=-1.0,init_QCD=-1.0 components = ['diboson', 'top', 'WpJ', 'ZpJ', 'QCD', 'WHbb'] for component in components: #double init init = getattr(opts, 'ext%s' % component) #init = -2.0 #setattr(self,init, 'init_%s' % component) #init = init_%s % component #print "init=", init #init = self.ws.var('init_%s' % component) #init.setVal(100.0) #init.setVal('init_%s' % component) #init = theYield.getVal() if (init>0.): print 'setting initial value for ',component,' to ',init setattr(self, '%sInitial' % component, init) def resetYields(self): if self.ws.data('data_obs'): Ndata = self.ws.data('data_obs').sumEntries() else: Ndata = 10000. print 'resetting yields...' components = self.pars.signals + self.pars.backgrounds for component in components: theYield = self.ws.var('n_%s' % component) theNorm = self.ws.var('%s_nrm' % component) if hasattr(self, '%sInitial' % component): print 'explicitly setting initial value for ',component theYield.setVal(getattr(self, '%sInitial' % component)) theNorm.setVal(1.0) theNorm.setConstant() else: fracofdata = -1. if hasattr(self.pars, '%sFracOfData' % component): fracofdata = getattr(self.pars, '%sFracOfData' % component) if (fracofdata >= 0.): print 'explicitly setting ', component,' yield to be', fracofdata,' of data' theYield.setVal(fracofdata*Ndata) elif hasattr(self, '%sExpected' % component): theYield.setVal(getattr(self, '%sExpected' % component)) else: print 'no expected value for',component theYield.setVal(Ndata/len(components)) if theNorm and not theNorm.isConstant(): theNorm.setVal(1.0) if component in self.pars.yieldConstraints: theYield.setError(theYield.getVal() * \ self.pars.yieldConstraints[component]) if theNorm: theNorm.setError(self.pars.yieldConstraints[component]) else: theYield.setError(sqrt(theYield.getVal())) theYield.Print() def generateToyMCSet(self,var,inputPdf,outFileName,NEvts): fMC = TFile(outFileName, "RECREATE"); # thevar = self.ws.var(var); print 'thevar=' print var # print thevar print '...' # varList = RooArgList() # varList.add(self.ws.var(var)) toymc = inputPdf.generate(RooArgSet(self.ws.var(var)),NEvts); tMC = toymc.tree(); fMC.cd(); tMC.Write(); fMC.Close(); def legend4Plot(plot, left = False): if left: theLeg = TLegend(0.2, 0.62, 0.55, 0.92, "", "NDC") else: theLeg = TLegend(0.60, 0.62, 0.92, 0.92, "", "NDC") theLeg.SetName('theLegend') theLeg.SetBorderSize(0) theLeg.SetLineColor(0) theLeg.SetFillColor(0) theLeg.SetFillStyle(0) theLeg.SetLineWidth(0) theLeg.SetLineStyle(0) theLeg.SetTextFont(42) theLeg.SetTextSize(.045) entryCnt = 0 for obj in range(0, int(plot.numItems())): objName = plot.nameOf(obj) if (not plot.getInvisible(objName)): theObj = plot.getObject(obj) objTitle = theObj.GetTitle() if len(objTitle) < 1: objTitle = objName dopts = plot.getDrawOptions(objName).Data() # print 'obj:',theObj,'title:',objTitle,'opts:',dopts,'type:',type(dopts) if theObj.IsA().InheritsFrom('TNamed'): theLeg.AddEntry(theObj, objTitle, dopts) entryCnt += 1 theLeg.SetY1NDC(0.9 - 0.05*entryCnt - 0.005) theLeg.SetY1(theLeg.GetY1NDC()) return theLeg legend4Plot = staticmethod(legend4Plot)
def main(options, args): cfg = options.config workspaceName = cfg.get('Global', 'workspace') ws = RooWorkspace(workspaceName) #ws.Print("v") setupWorkspace(ws, options) #create -log(likelihood) theNLL = ws.pdf('TopLevelPdf').createNLL( ws.data('allcountingdata'), RooFit.NumCPU(1), RooFit.ConditionalObservables(ws.set('condObs')), RooFit.Verbose(True)) ws.saveSnapshot('standardmodel', ws.allVars()) minuit = ROOT.RooMinuit(theNLL) minuit.setPrintLevel(1) minuit.setPrintEvalErrors(-1) minuit.setErrorLevel(.5) #find the values of the parameters that minimize the likelihood minuit.setStrategy(2) minuit.simplex() minuit.migrad() minuit.hesse() #ws.var('err_gl').setConstant(True) #ws.var('err_gs').setConstant(True) #ws.var('err_gb').setConstant(True) ws.defineSet( 'POI', ROOT.RooArgSet( ws.var('%s_%s' % (cfg.get( 'Global', 'par1Name'), cfg.get('Global', 'couplingType'))), ws.var('%s_%s' % (cfg.get( 'Global', 'par2Name'), cfg.get('Global', 'couplingType'))))) ws.saveSnapshot('%s_fitresult' % cfg.get('Global', 'couplingType'), ws.allVars()) #create profile likelihood level_68 = ROOT.TMath.ChisquareQuantile( .68, 2) / 2.0 # delta NLL for 68% confidence level for -log(LR) level_95 = ROOT.TMath.ChisquareQuantile( .95, 2) / 2.0 # delta NLL for 95% confidence level for -log(LR) print print '68% CL Delta-NLL 2 DOF=', level_68 print '95% CL Delta-NLL 2 DOF=', level_95 minuit.setPrintLevel(1) minuit.setPrintEvalErrors(-1) minuit.migrad() minuit.minos(ws.set('POI')) thePlot = minuit.contour( ws.var('%s_%s' % (cfg.get( 'Global', 'par1Name'), cfg.get('Global', 'couplingType'))), ws.var('%s_%s' % (cfg.get( 'Global', 'par2Name'), cfg.get('Global', 'couplingType'))), sqrt(2 * level_95), sqrt(2 * level_68)) # here the error is in sigmas thePlot.SetName( '%s_%s_%s_contour' % (cfg.get('Global', 'par1Name'), cfg.get( 'Global', 'par2Name'), cfg.get('Global', 'couplingType'))) thePlot.SetTitle('68% & 95% CL on the Best Fit Values of ' + cfg.get('Global', 'par1Name') + ' and ' + cfg.get('Global', 'par2Name')) legend = ROOT.TLegend(2.01612903225806439e-01, 7.86016949152542388e-01, 7.15725806451612989e-01, 9.13135593220338992e-01) legend.SetNColumns(2) thePlot.addObject(legend) # 1-D Limits level_95 = ROOT.TMath.ChisquareQuantile( .95, 1) / 2.0 # delta NLL for -log(LR) with 1 dof print '95% CL Delta-NLL 1 DOF=', level_95 minuit.setErrorLevel(level_95) #set 1-D limits on parameter 1 with parameter 2 == 0 ws.var('%s_%s' % (cfg.get( 'Global', 'par2Name'), cfg.get('Global', 'couplingType'))).setVal(0.0) ws.var('%s_%s' % (cfg.get('Global', 'par2Name'), cfg.get('Global', 'couplingType'))).setConstant(True) minuit.minos(ws.set('POI')) parm1 = ws.var( '%s_%s' % (cfg.get('Global', 'par1Name'), cfg.get('Global', 'couplingType'))) print 'parameter 1 value: ' + str(parm1.getVal()) if not (0 < parm1.getVal() + parm1.getErrorHi() and 0 > parm1.getVal() + parm1.getErrorLo()): print '95% CL does not cover SM for parameter 1' else: print '95% CL covers SM for parameter 1' par1Line = ROOT.TLine(parm1.getVal() + parm1.getErrorLo(), 0, parm1.getVal() + parm1.getErrorHi(), 0) par1Line.SetLineWidth(2) par1Line.SetLineColor(ROOT.kRed) thePlot.addObject(par1Line) #set 1-D limits on parameter 2 with parameter 1 == 0 ws.var('%s_%s' % (cfg.get('Global', 'par2Name'), cfg.get('Global', 'couplingType'))).setConstant(False) ws.var('%s_%s' % (cfg.get( 'Global', 'par1Name'), cfg.get('Global', 'couplingType'))).setVal(0.0) ws.var('%s_%s' % (cfg.get('Global', 'par1Name'), cfg.get('Global', 'couplingType'))).setConstant(True) minuit.minos(ws.set('POI')) parm2 = ws.var( '%s_%s' % (cfg.get('Global', 'par2Name'), cfg.get('Global', 'couplingType'))) print 'parameter 2 value: ' + str(parm2.getVal()) if not (0 < parm2.getVal() + parm2.getErrorHi() and 0 > parm2.getVal() + parm2.getErrorLo()): print '95% CL does not cover SM for parameter 2' else: print '95% CL covers SM for parameter 2' par2Line = ROOT.TLine(0, parm2.getVal() + parm2.getErrorLo(), 0, parm2.getVal() + parm2.getErrorHi()) par2Line.SetLineWidth(2) par2Line.SetLineColor(ROOT.kRed) thePlot.addObject(par2Line) ws.var('%s_%s' % (cfg.get('Global', 'par1Name'), cfg.get('Global', 'couplingType'))).setConstant(False) #construct likelihood scan histograms plot = parm1.frame() parm1.setBins(200) parm2.setBins(200) scanHist = ROOT.TH2F('scan2d_plot', '2D Scan of the Likelihood', 200, parm1.getMin(), parm1.getMax(), 200, parm2.getMin(), parm2.getMax()) for i in range(200): for j in range(200): parm1.setVal(parm1.getMin() + (i + .5) * (parm1.getMax() - parm1.getMin()) / 200) parm2.setVal(parm2.getMin() + (j + .5) * (parm2.getMax() - parm2.getMin()) / 200) scanHist.SetBinContent(i + 1, j + 1, theNLL.getVal()) profNLL_par1 = theNLL.createProfile(RooArgSet(parm1)) profNLL_par1_plot = parm1.frame() profNLL_par1.plotOn(profNLL_par1_plot) profNLL_par2 = theNLL.createProfile(RooArgSet(parm2)) profNLL_par2_plot = parm2.frame() profNLL_par2.plotOn(profNLL_par2_plot) initCMSStyle() output = TFile.Open(workspaceName + '.root', 'RECREATE') ws.Write() contCanvas = ROOT.TCanvas('contour_canvas', '', 500, 500) thePlot.Draw() prettyContour(contCanvas, cfg) contCanvas.Write() thePlot.Write() scanCanvas2D = ROOT.TCanvas('scan2d_canvas', '', 500, 500) scanHist.Draw('colz') prettyScan(scanCanvas2D, cfg) scanCanvas2D.Write() scanHist.Write() par1ScanCanvas = ROOT.TCanvas('scan1d_par1', '', 500, 500) par1ScanCanvas.cd() profNLL_par1_plot.Draw() par1ScanCanvas.Write() profNLL_par1_plot.Write() par2ScanCanvas = ROOT.TCanvas('scan1d_par2', '', 500, 500) par2ScanCanvas.cd() profNLL_par2_plot.Draw() par2ScanCanvas.Write() profNLL_par2_plot.Write() prettyObsPlots(ws, cfg) output.Close() if options.makeCards: print print "Creating cards for Higgs Combined Limit calculator!" makeHCLCards(ws, cfg) return 0
def main(options,args): pt_bins = [[12, 15], [15, 20]] eta_bins = [[0.0,1.4442]] # try to split material dependence # [1.560,2.5]] sieie = RooRealVar(options.showerShapeName,'#sigma_{i #eta i #eta}',.1,0,.15) sieie.setBins(200) pt = RooRealVar(options.ptName,'Photon p_{T}',50,10,1000) eta = RooRealVar(options.etaName,'Photon #eta',0.0,-3.0,3.0) chIso = RooRealVar(options.isoName, 'phoCHIso', 100, 0, 20) fakeMom = RooRealVar(options.momName, 'phohasFakemom', 0,1) #containor for the root variables vars = RooArgSet() vars.add(sieie) vars.add(pt) vars.add(eta) vars.add(chIso) vars.add(fakeMom) allSig = None allBkg = None if options.weight is not None: weight = RooRealVar(options.weight,'',1) vars.add(weight) allSig = RooDataSet('allSig','All Signal Template Events', vars, RooFit.ImportFromFile(options.signalInput, options.sigTreeName), RooFit.WeightVar(options.weight) ) if options.useFakeMCBkg: fake = RooRealVar('Fake','',0.5,1.5) #RooRealVar isSidebands("isSidebands","isSidebands",0,1); #fake = RooRealVar(options.momName,"phohasFakemom",0,1) vars.add(fake) weight.setVal(1) ctauStates = RooCategory('ctauRegion','Cut Region in lifetime') ctauStates.defineType('phohasFakemom',0) #ctauStates.defineType('nonPrompt',1) allBkg = RooDataSet('allBkg','All Background Template Events', RooArgSet(ctauStates,vars), RooFit.ImportFromFile(options.backgroundInput, options.bkgTreeName), RooFit.WeightVar(options.weight) ) else: allSig = RooDataSet('allSig','All Signal Template Events', vars, RooFit.ImportFromFile(options.signalInput, options.sigTreeName) ) allBkg = RooDataSet('allBkg','All Background Template Events', vars, RooFit.ImportFromFile(options.backgroundInput, options.bkgTreeName) ) output = TFile.Open(options.outputFile,'RECREATE') ws = RooWorkspace(options.outputFile[:options.outputFile.find('.root')],'Template Workspace') # put in the raw datasets, no cuts or manipulation getattr(ws,'import')(allSig, RooFit.RenameVariable(options.showerShapeName,'Pho_SigmaIEtaIEta'), RooFit.RenameVariable(options.ptName,'Pho_Pt'), #RooFit.RenameVariable(options.isoName,'phoCHIso'), RooFit.RenameVariable(options.etaName,'Pho_Eta')) getattr(ws,'import')(allBkg, RooFit.RenameVariable(options.showerShapeName,'Pho_SigmaIEtaIEta'), RooFit.RenameVariable(options.ptName,'Pho_Pt'), #RooFit.RenameVariable(options.isoName,'phoCHIso'), RooFit.RenameVariable(options.etaName,'Pho_Eta')) #loop through bins making all templates for etabin in eta_bins: for ptbin in pt_bins: if 'abs(Pho_Eta) < 1.4442': phoselsig = 'abs(Pho_Eta) > %f && abs(Pho_Eta) < %f && Pho_Pt > %f && Pho_Pt < %f'%(etabin[0], etabin[1], ptbin[0], ptbin[1]) # if fake: phoselbkg = 'phoCHIso < 2 && abs(Pho_Eta) > %f && abs(Pho_Eta) < %f && Pho_Pt > %f && Pho_Pt < %f'%(etabin[0], etabin[1], ptbin[0], ptbin[1]) postfix = '_Eta_%.4f_%.4f_Pt_%.2f_%.2f'%(etabin[0],etabin[1],ptbin[0],ptbin[1]) binSig = ws.data('allSig').reduce(RooFit.Cut(phoselsig), RooFit.Name('sigEta'+postfix), RooFit.Title('Signal Template Events')) binBkg = ws.data('allBkg').reduce(RooFit.Cut(phoselbkg), RooFit.Name('bkgEta'+postfix), RooFit.Title('Background Template Events')) #save it all in the workspace getattr(ws,'import')(binSig) getattr(ws,'import')(binBkg) smoothingPars = RooArgList(ws.var('Pho_SigmaIEtaIEta')) #ws.var('Pho_Pt'), print 'Making binSigTemplate'+postfix+' with '+str(binSig.numEntries())+' events.' bSigTempl = None if( binSig.numEntries() <= 80000 ): bSigTempl = RooNDKeysPdf('binSigTemplate'+postfix,'',smoothingPars,binSig,"am") else: bSigTempl = super(RooDataSet,binSig) print 'Making binBkgTemplate'+postfix+' with '+str(binBkg.numEntries())+' events.' bBkgTempl = None if( binBkg.numEntries() <= 80000 ): bBkgTempl = RooNDKeysPdf('binBkgTemplate'+postfix,'',smoothingPars,binBkg,"am") else: bBkgTempl = super(RooDataSet,binBkg) #finely binned histograms so that we can store the results of the smoothing #These will be linearly interpolated by RooHistPdf bsTHist = bSigTempl.createHistogram('binSigSmoothedHist'+postfix, ws.var('Pho_SigmaIEtaIEta'), RooFit.Binning(options.nBins,0,.15) ) getattr(ws,'import')(bsTHist) bbTHist = bBkgTempl.createHistogram('binBkgSmoothedHist'+postfix, ws.var('Pho_SigmaIEtaIEta'), RooFit.Binning(options.nBins,0,.15) ) getattr(ws,'import')(bbTHist) #make RooDataHists for consuption by RooHistPdf Later bsTDHist = RooDataHist('binSigSmoothedDataHist'+postfix, '', RooArgList(ws.var('Pho_SigmaIEtaIEta')), ws.obj('binSigSmoothedHist'+postfix+'__Pho_SigmaIEtaIEta')) getattr(ws,'import')(bsTDHist) bbTDHist = RooDataHist('binBkgSmoothedDataHist'+postfix, '', RooArgList(ws.var('Pho_SigmaIEtaIEta')), ws.obj('binBkgSmoothedHist'+postfix+'__Pho_SigmaIEtaIEta')) getattr(ws,'import')(bbTDHist) ws.Write() output.Close()