예제 #1
0
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
예제 #2
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)
예제 #3
0
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()
예제 #4
0
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()
예제 #5
0
    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"))
예제 #6
0
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)
예제 #7
0
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']
예제 #8
0
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()
예제 #9
0
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')
예제 #10
0
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')
예제 #11
0
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)
예제 #12
0
  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"))
예제 #13
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'
        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)
예제 #14
0
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()