def signalFitInterpolation(category, ws, tupleSignalModelVariable, settings, **wargs):
    """
    assume the Workspace already exists and x-variable is already defined
    """
    # 
    # initialize the values from wargs
    # 
    pathToDir = "/tmp"
    if "pathToDir" in wargs:
        pathToDir = wargs["pathToDir"]

    #
    # the the canvas/frame
    #
    canvas = R.TCanvas("c1", "c1", 800, 600)
    canvas.cd()
    frame = ws.var("x").frame()
    
    #
    # for each mass point, perform a fit.
    # initial values for each consecutive model will be derived from the 
    # previous mass point
    #
    imodel = 0
    prevSignal=None; prevModel=None; prevVariable=None
    for (signal, model, variable) in tupleSignalModelVariable:
        fsdata = R.TFile(signal.pathToFile)

        hsdata_name = category + "/" + variable["name"]
        if settings.useInputFileUF: 
            hsdata_name = "signal_histos/" + category + "_" + signal.mc.uflabel

        hsdata = fsdata.Get(hsdata_name)
        if not settings.useInputFileUF:
            hsdata.Scale(1/signal.getWeight())
        rsdata = aux.buildRooHist(ws, hsdata)
        model.initialize(aux.buildSignalModelName(model, 
            settings.names2RepsToUse[category],
            signal.mc.buildProcessName(), variable["central"]))
        if imodel>0:
            model.setInitialValuesFromModel(prevModel, ws, 
                massDifference=(variable["central"] - prevVariable["central"]))
        model.createParameters(ws)
        pdf = model.build(ws, category=category)
        r = pdf.fitTo(rsdata, R.RooFit.Save(),
            R.RooFit.Range(variable["fitmin"], variable["fitmax"]))
        prevSignal = signal
        prevModel = model
        prevVariable = variable

        pdf.plotOn(frame, R.RooFit.LineColor(R.kBlue))
        imodel+=1

    #
    # save the canvas
    #
    frame.SetTitle("{category}_{processName}".format(category=category, processName=signal.mc.buildProcessName()))
    frame.Draw()
    fileName = "signalFitInterpolation__{category}__{processName}__{modelId}__{mods}.png".format(category=category, processName=signal.mc.buildProcessName(), modelId=model.modelId, mods="")
    canvas.SaveAs(os.path.join(pathToDir, fileName))
Exemple #2
0
def datacardsSingleGaus():
    physGroupToUse = physGroupTest
    orderedGroupsToUse = orderedGroupsTest
    workspaceName = "higgs"
    signalSplinesDir = os.path.join(signalfitinterpolationswithsplineDir,
                                    args.outDirName)
    backgroundsDir = os.path.join(backgroundfitswithroomultipdfDir,
                                  args.outDirName)
    datacardsDir = os.path.join(datacardsworkspacesDir, args.outDirName)
    fffTestDir = os.path.join(ftestDir, args.outDirName)
    aux.mkdir(signalSplinesDir)
    aux.mkdir(backgroundsDir)
    aux.mkdir(datacardsDir)
    aux.mkdir(fffTestDir)
    fTestResults = {}
    for category in categoriesToUse:
        fTestResults[category] = {}
        workspaceFileName = "workspace__{category}__{signalModelId}.root".format(
            category=names2RepsToUse[category],
            signalModelId=singleGaus120.modelId)
        ws = R.RooWorkspace(workspaceName)
        aux.buildMassVariable(ws, **diMuonMass125)
        aux.buildMH(ws, mhmin=120, mhmax=130)

        #
        # create the RooDataHist and import it into the Workspace here explicitly
        #
        fdata = R.TFile(data.pathToFile)

        hdata_name = category + "/DiMuonMass"
        if settings.useInputFileUF:
            hdata_name = "net_histos/" + category + "_Net_Data"

        hdata = fdata.Get(hdata_name)
        rdata = aux.buildRooHist(
            ws, hdata,
            "data_obs_{category}".format(category=names2RepsToUse[category]))
        getattr(ws, "import")(rdata, R.RooFit.RecycleConflictNodes())
        fdata.Close()

        #
        # Create the Signal Models
        #
        print "*" * 80
        print "Generating Single Gaus Splines"
        print "*" * 80
        vbfmodel = funcs.signalFitInterpolationWithSpline(
            category,
            ws, [
                (vbf120, singleGaus120, diMuonMass120),
                (vbf125, singleGaus125, diMuonMass125),
                (vbf130, singleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir)
        glumodel = funcs.signalFitInterpolationWithSpline(
            category,
            ws, [
                (glu120, singleGaus120, diMuonMass120),
                (glu125, singleGaus125, diMuonMass125),
                (glu130, singleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir)
        wpmodel = funcs.signalFitInterpolationWithSpline(
            category,
            ws, [
                (wp120, singleGaus120, diMuonMass120),
                (wp125, singleGaus125, diMuonMass125),
                (wp130, singleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir)
        wmmodel = funcs.signalFitInterpolationWithSpline(
            category,
            ws, [
                (wm120, singleGaus120, diMuonMass120),
                (wm125, singleGaus125, diMuonMass125),
                (wm130, singleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir)
        zhmodel = funcs.signalFitInterpolationWithSpline(
            category,
            ws, [
                (zh120, singleGaus120, diMuonMass120),
                (zh125, singleGaus125, diMuonMass125),
                (zh130, singleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir)

        #
        # Perform the F-Test and select the proper order of the
        #
        selectedOrderedModels = []
        for modelGroup in orderedGroupsToUse:
            counter = 0
            for m in modelGroup.models:
                m.color = colors[counter]
                counter += 1
            selectedModel, values = funcs.ftestPerFamily(
                (category, diMuonMass125),
                ws,
                data,
                modelGroup,
                settings,
                pathToDir=fffTestDir)
            if selectedModel is not None:
                selectedOrderedModels.append(selectedModel)
            fTestResults[category][modelGroup.name] = values

        #
        # Create the Background Model
        #
        totalModelGroup = ModelGroup(
            "bkgModels", physGroupTest.models + selectedOrderedModels)
        counter = 0
        for model in totalModelGroup.models:
            model.color = colors[counter]
            counter += 1
        funcs.backgroundsWithRooMultiPdf((category, diMuonMass125),
                                         ws,
                                         data,
                                         totalModelGroup.models,
                                         settings,
                                         pathToDir=backgroundsDir,
                                         groupName=totalModelGroup.name)

        #
        # Signal and Background Models are ready and are in the Workspace
        # create the datacard for this category
        #
        funcs.datacardAnalytic(category,
                               ws,
                               data,
                               [vbfmodel, glumodel, wpmodel, wmmodel, zhmodel],
                               ws.pdf("multipdf_{category}".format(
                                   category=names2RepsToUse[category])),
                               settings,
                               pathToDir=datacardsDir,
                               workspaceFileName=workspaceFileName,
                               workspaceName=workspaceName,
                               withSystematics=args.withSystematics)

        #
        # save the Workspacee
        #
        print "*" * 80
        print "*** Final RooWorkspace contents ***"
        print "*" * 80
        ws.Print("v")
        ws.SaveAs(os.path.join(datacardsDir, workspaceFileName))

    #
    # plot all the F-Test Results
    #
    funcs.plotFTestResults(fTestResults, pathToDir=fffTestDir)
Exemple #3
0
def datacardsTripleGaus():
    physGroupToUse = physGroupTest  # The physics derived background fit functions (non ordered)
    orderedGroupsToUse = orderedGroupsTest  # The ordered background fits (berenstein, sumexp, etc)

    # book keeping, set up output dirs for signal, bkg, datacards, and workspaces
    workspaceName = "higgs"
    signalSplinesDir = os.path.join(signalfitinterpolationswithsplineDir,
                                    args.outDirName)
    backgroundsDir = os.path.join(backgroundfitswithroomultipdfDir,
                                  args.outDirName)
    datacardsDir = os.path.join(datacardsworkspacesDir, args.outDirName)
    fffTestDir = os.path.join(ftestDir, args.outDirName)
    aux.mkdir(signalSplinesDir)
    aux.mkdir(backgroundsDir)
    aux.mkdir(datacardsDir)
    aux.mkdir(fffTestDir)
    fTestResults = {}

    # run over every category and fit the signal and background and make the workspaces
    for category in categoriesToUse:
        fTestResults[category] = {}

        # Create workspace for category
        # use the representation of the name rather than the complicated name, should set up reps in config file
        workspaceFileName = "workspace__{category}__{signalModelId}.root".format(
            category=names2RepsToUse[category],
            signalModelId=tripleGaus120.modelId)
        ws = R.RooWorkspace(workspaceName)
        aux.buildMassVariable(ws, **diMuonMass125)
        aux.buildMH(ws, mhmin=120, mhmax=130)

        #
        # Create the RooDataHist and import it into the Workspace
        #
        fdata = R.TFile(data.pathToFile)

        hdata_name = category + "/DiMuonMass"
        if settings.useInputFileUF:
            hdata_name = "net_histos/" + category + "_Net_Data"

        # Get data histogram from the input file for the category
        # Turn it into a roo data histogram to use with roofit
        hdata = fdata.Get(hdata_name)
        rdata = aux.buildRooHist(
            ws, hdata,
            "data_obs_{category}".format(category=names2RepsToUse[category]))
        getattr(ws, "import")(rdata, R.RooFit.RecycleConflictNodes())
        fdata.Close()

        #
        # Create the Signal Models
        #
        print "*" * 80
        print "Generating Triple Gaus Splines"
        print "*" * 80
        # vbf120, tripleGaus120, diMuonMass120 imported from config file
        # vbf120 is of defs.MC('NoCats', inputFileUF, vbf120MC, color=R.kRed)
        # vbf120MC = samp.mcMoriond2017datasets_1['VBF_120']
        # tripleGaus120 = models.TripleGaus(tripleGaus120_initialValues)
        # diMuonMass120 = {name: DiMuonMass, central: 120, min:110, max:160, fitmin:110, fitmax:130}
        vbfmodel = funcs.signalFitInterpolationWithSpline(
            category,
            ws,
            [
                (vbf120, tripleGaus120,
                 diMuonMass120),  # (mc sample, fit, fit window)
                (vbf125, tripleGaus125, diMuonMass125),
                (vbf130, tripleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir)
        glumodel = funcs.signalFitInterpolationWithSpline(
            category,
            ws, [
                (glu120, tripleGaus120, diMuonMass120),
                (glu125, tripleGaus125, diMuonMass125),
                (glu130, tripleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir)
        wpmodel = funcs.signalFitInterpolationWithSpline(
            category,
            ws, [
                (wp120, tripleGaus120, diMuonMass120),
                (wp125, tripleGaus125, diMuonMass125),
                (wp130, tripleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir)
        wmmodel = funcs.signalFitInterpolationWithSpline(
            category,
            ws, [
                (wm120, tripleGaus120, diMuonMass120),
                (wm125, tripleGaus125, diMuonMass125),
                (wm130, tripleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir)
        zhmodel = funcs.signalFitInterpolationWithSpline(
            category,
            ws, [
                (zh120, tripleGaus120, diMuonMass120),
                (zh125, tripleGaus125, diMuonMass125),
                (zh130, tripleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir)

        #
        # Perform the F-Test and select the proper order of the
        #
        selectedOrderedModels = [
        ]  # ordered models for this category that passed the f-test

        for modelGroup in orderedGroupsToUse:  # ModelGroup has a name for the group and a list of models
            counter = 0
            for m in modelGroup.models:
                m.color = colors[counter]
                counter += 1

            # return the model with the order that passes the ftest
            # e.g. berenstein6 for berensten model group or sumExp3 for sum exp model group

            # ftestPerFamily imported from Modeling/higgs2/generatingFunctions.py
            selectedModel, values = funcs.ftestPerFamily(
                (category, diMuonMass125),
                ws,
                data,
                modelGroup,
                settings,
                pathToDir=fffTestDir,
                unblind=args.unblind)
            if selectedModel is not None:
                selectedOrderedModels.append(selectedModel)

            # Save ftest results for each category,modelgroup
            fTestResults[category][modelGroup.name] = values

        #
        # Create the Background Model
        #
        totalModelGroup = ModelGroup(
            "bkgModels", physGroupTest.models + selectedOrderedModels)
        counter = 0
        for model in totalModelGroup.models:
            model.color = colors[counter]
            counter += 1

        # Multipdf for background with physics based models and the ftest passed ordered models
        # !!! DOES NOT use modelGroupForMultiPdf from config file !!!
        funcs.backgroundsWithRooMultiPdf((category, diMuonMass125),
                                         ws,
                                         data,
                                         totalModelGroup.models,
                                         settings,
                                         pathToDir=backgroundsDir,
                                         groupName=totalModelGroup.name,
                                         unblind=args.unblind)

        #
        # Signal and Background Models are ready and are in the Workspace
        # create the datacard for this category
        #
        funcs.datacardAnalytic(category,
                               ws,
                               data,
                               [vbfmodel, glumodel, wpmodel, wmmodel, zhmodel],
                               ws.pdf("multipdf_{category}".format(
                                   category=names2RepsToUse[category])),
                               settings,
                               pathToDir=datacardsDir,
                               workspaceFileName=workspaceFileName,
                               workspaceName=workspaceName,
                               withSystematics=args.withSystematics)

        #
        # save the Workspacee
        #
        ws.SaveAs(os.path.join(datacardsDir, workspaceFileName))

    #
    # plot all the F-test results
    #
    funcs.plotFTestResults(fTestResults, pathToDir=fffTestDir)
def signalFitInterpolation(category, ws, tupleSignalModelVariable, settings,
                           **wargs):
    """
    assume the Workspace already exists and x-variable is already defined
    """
    #
    # initialize the values from wargs
    #
    pathToDir = "/tmp"
    if "pathToDir" in wargs:
        pathToDir = wargs["pathToDir"]

    #
    # the the canvas/frame
    #
    canvas = R.TCanvas("c1", "c1", 800, 600)
    canvas.cd()
    frame = ws.var("x").frame()

    #
    # for each mass point, perform a fit.
    # initial values for each consecutive model will be derived from the
    # previous mass point
    #
    imodel = 0
    prevSignal = None
    prevModel = None
    prevVariable = None
    for (signal, model, variable) in tupleSignalModelVariable:
        fsdata = R.TFile(signal.pathToFile)

        hsdata_name = category + "/" + variable["name"]
        if settings.useInputFileUF:
            hsdata_name = "signal_histos/" + category + "_" + signal.mc.uflabel

        hsdata = fsdata.Get(hsdata_name)
        if not settings.useInputFileUF:
            hsdata.Scale(1 / signal.getWeight())
        rsdata = aux.buildRooHist(ws, hsdata)
        model.initialize(
            aux.buildSignalModelName(model, settings.names2RepsToUse[category],
                                     signal.mc.buildProcessName(),
                                     variable["central"]))
        if imodel > 0:
            model.setInitialValuesFromModel(
                prevModel,
                ws,
                massDifference=(variable["central"] - prevVariable["central"]))
        model.createParameters(ws)
        pdf = model.build(ws, category=category)
        r = pdf.fitTo(rsdata, R.RooFit.Save(),
                      R.RooFit.Range(variable["fitmin"], variable["fitmax"]))
        prevSignal = signal
        prevModel = model
        prevVariable = variable

        pdf.plotOn(frame, R.RooFit.LineColor(R.kBlue))
        imodel += 1

    #
    # save the canvas
    #
    frame.SetTitle("{category}_{processName}".format(
        category=category, processName=signal.mc.buildProcessName()))
    frame.Draw()
    fileName = "signalFitInterpolation__{category}__{processName}__{modelId}__{mods}.png".format(
        category=category,
        processName=signal.mc.buildProcessName(),
        modelId=model.modelId,
        mods="")
    canvas.SaveAs(os.path.join(pathToDir, fileName))
def signalFitInterpolationWithSpline(category, ws, tupleSignalModelVariable,
                                     settings, **wargs):
    """
    assume the Workspace already exists and x-variable is already defined
    """
    #
    # Load Combine's lib
    #
    R.gSystem.Load("libHiggsAnalysisCombinedLimit.so")

    #
    # initialize the values from wargs
    #
    pathToDir = "/tmp"
    if "pathToDir" in wargs:
        pathToDir = wargs["pathToDir"]

    #
    # the the canvas/frame
    #
    canvas = R.TCanvas("c1", "c1", 800, 600)
    canvas.cd()

    #
    # for each mass point, perform a fit.
    # initial values for each consecutive model will be derived from the
    # previous mass point
    #
    imodel = 0
    prevSignal = None
    prevModel = None
    prevVariable = None
    parameters = []
    massPoints = []
    norms = []
    for (signal, model, variable) in tupleSignalModelVariable:
        fsdata = R.TFile(signal.pathToFile)
        frame = ws.var("x").frame()

        hsdata_name = category + "/" + variable["name"]
        if settings.useInputFileUF:
            hsdata_name = "signal_histos/" + category + "_" + signal.mc.uflabel

        hsdata = fsdata.Get(hsdata_name)
        if not settings.useInputFileUF:
            hsdata.Scale(1 / signal.getWeight())
        rsdata = aux.buildRooHist(ws, hsdata)
        binfirst = hsdata.FindBin(variable["min"])
        binlast = hsdata.FindBin(variable["max"])
        #        norms.append(hsdata.Integral(binfirst, binlast))
        norms.append(rsdata.sumEntries())
        model.initialize(
            aux.buildSignalModelName(model, settings.names2RepsToUse[category],
                                     signal.mc.buildProcessName(),
                                     variable["central"]))
        if imodel > 0:
            model.setInitialValuesFromModel(
                prevModel,
                ws,
                massDifference=(variable["central"] - prevVariable["central"]))
        model.createParameters(ws)
        pdf = model.build(ws, category=category)
        #
        # Fit twice???
        # Andrea has it like that??? May be second time has better initial values???
        #
        r = pdf.fitTo(rsdata, R.RooFit.Save(),
                      R.RooFit.Range(variable["fitmin"], variable["fitmax"]),
                      R.RooFit.SumW2Error(R.kTRUE))
        prevSignal = signal
        prevModel = model
        prevVariable = variable
        imodel += 1
        massPoints.append(variable["central"])

        # plot this model together with signal histogram
        rsdata.plotOn(frame)
        pdf.plotOn(frame, R.RooFit.LineColor(R.kBlue))

        # draw the frame and save the canvas
        frame.SetTitle("{category}_{higgsMass}_{processName}".format(
            category=category,
            higgsMass=variable["central"],
            processName=signal.mc.buildProcessName()))
        frame.Draw()
        fileName = "signalFit__{category}__{higgsMass}__{processName}__{modelId}__{mods}.png".format(
            category=category,
            higgsMass=variable["central"],
            processName=signal.mc.buildProcessName(),
            modelId=model.modelId,
            mods="default")
        canvas.SaveAs(os.path.join(pathToDir, fileName))

        # exctract the parameters
        lParameters = model.getParameterValuesAsList(ws)
        parameters.append(lParameters)
        print "*" * 90 + "\n"
        print "*" * 90 + "\n"
        print lParameters
        print parameters
        r.Print("v")

        #        pdf.plotOn(frame, R.RooFit.LineColor(R.kBlue))
        imodel += 1

    #
    # build the Splines
    # create the spline for normalization
    # have to transpose the matrix of parameters first
    #
    frame = ws.var("x").frame()
    paramsTransposed = aux.transpose(parameters)
    print "*" * 90 + "\n"
    print "*" * 90 + "\n"
    print "*" * 90 + "\n"
    print "*" * 90 + "\n"
    print parameters
    print paramsTransposed
    finalmodel = prevModel.__class__()
    finalmodel.initialize(
        aux.buildSignalModelName(finalmodel,
                                 settings.names2RepsToUse[category],
                                 signal.mc.buildProcessName()))
    finalpdf = finalmodel.buildWithParameterMatrix(ws, massPoints,
                                                   paramsTransposed)
    finalmodel.setNormalization(ws, massPoints, norms)
    finalpdf.Print("v")

    #
    # plot for each GeV and save the canvas
    #
    for mh in [120 + i for i in range(11)]:
        ws.var("MH").setVal(mh)
        finalpdf.plotOn(frame)

    #
    # save the canvas
    #
    frame.SetTitle("{category}_{processName}".format(
        category=category, processName=signal.mc.buildProcessName()))
    frame.Draw()
    fileName = "signalFitInterpolationWithSpline__{category}__{processName}__{modelId}__{mods}.png".format(
        category=category,
        processName=signal.mc.buildProcessName(),
        modelId=model.modelId,
        mods="")
    canvas.SaveAs(os.path.join(pathToDir, fileName))

    #
    # return the model that you build with RooSplines
    #
    return finalmodel
    # get the histogram from the input root file
    # and convert to a roo hist
    #
    fsdata = R.TFile(signal.pathToFile)

    hsdata_name = category + "/" + variable["name"]
    if settings.useInputFileUF:
        hsdata_name = "signal_histos/" + category + "_" + signal.mc.uflabel

    hsdata = fsdata.Get(hsdata_name)
    if not settings.useInputFileUF:
        hsdata.Scale(1 / signal.getWeight())


#    hsdata.GetXaxis().SetRange(variable["min"], variable["max"])
    rsdata = aux.buildRooHist(ws, hsdata)

    #
    # set up the model and perform the fit
    #

    # Simply set the name for the model based upon the model, category, and M=120,125,or 130
    model.initialize(
        aux.buildSignalModelName(model, settings.names2RepsToUse[category],
                                 signal.mc.buildProcessName(),
                                 variable["central"]))

    # Set the initial signal model parameters based upon the mean and rms of the signal histogram
    # for this category, seems reasonable for single gauss, but not sure what it does for double
    # and triple gauss
    if initialValuesFromTH1:
Exemple #7
0
def datacardsTripleGaus():
    physGroupToUse = physGroupTest           # The physics derived background fit functions (non ordered)
    orderedGroupsToUse = orderedGroupsTest   # The ordered background fits (berenstein, sumexp, etc)

    # book keeping, set up output dirs for signal, bkg, datacards, and workspaces
    workspaceName = "higgs"
    signalSplinesDir = os.path.join(signalfitinterpolationswithsplineDir, args.outDirName)
    backgroundsDir = os.path.join(backgroundfitswithroomultipdfDir, args.outDirName)
    datacardsDir = os.path.join(datacardsworkspacesDir, args.outDirName)
    fffTestDir = os.path.join(ftestDir, args.outDirName)
    aux.mkdir(signalSplinesDir); aux.mkdir(backgroundsDir); aux.mkdir(datacardsDir)
    aux.mkdir(fffTestDir)
    fTestResults = {}

    # run over every category and fit the signal and background and make the workspaces
    for category in categoriesToUse:
        fTestResults[category] = {}

        # Create workspace for category
        # use the representation of the name rather than the complicated name, should set up reps in config file
        workspaceFileName = "workspace__{category}__{signalModelId}.root".format(
            category=names2RepsToUse[category], signalModelId = tripleGaus120.modelId)
        ws = R.RooWorkspace(workspaceName)
        aux.buildMassVariable(ws, **diMuonMass125)
        aux.buildMH(ws, mhmin=120, mhmax=130)
        
        #
        # Create the RooDataHist and import it into the Workspace
        #
        fdata = R.TFile(data.pathToFile)

        hdata_name = category + "/DiMuonMass"
        if settings.useInputFileUF:
            hdata_name = "net_histos/"+category+"_Net_Data"

        # Get data histogram from the input file for the category
        # Turn it into a roo data histogram to use with roofit
        hdata = fdata.Get(hdata_name)
        rdata = aux.buildRooHist(ws, hdata,
            "data_obs_{category}".format(category=names2RepsToUse[category]))
        getattr(ws, "import")(rdata, R.RooFit.RecycleConflictNodes())
        fdata.Close()
        
        #
        # Create the Signal Models
        #
        print "*"*80
        print "Generating Triple Gaus Splines"
        print "*"*80
        # vbf120, tripleGaus120, diMuonMass120 imported from config file
            # vbf120 is of defs.MC('NoCats', inputFileUF, vbf120MC, color=R.kRed)
                # vbf120MC = samp.mcMoriond2017datasets_1['VBF_120']
            # tripleGaus120 = models.TripleGaus(tripleGaus120_initialValues)
            # diMuonMass120 = {name: DiMuonMass, central: 120, min:110, max:160, fitmin:110, fitmax:130}
        vbfmodel = funcs.signalFitInterpolationWithSpline(category, ws, 
            [
                (vbf120, tripleGaus120, diMuonMass120),   # (mc sample, fit, fit window)
                (vbf125, tripleGaus125, diMuonMass125),
                (vbf130, tripleGaus130, diMuonMass130),
            ], 
            settings,
            pathToDir=signalSplinesDir
        )
        glumodel = funcs.signalFitInterpolationWithSpline(category, ws, 
            [
                (glu120, tripleGaus120, diMuonMass120),
                (glu125, tripleGaus125, diMuonMass125),
                (glu130, tripleGaus130, diMuonMass130),
            ],
            settings, 
            pathToDir=signalSplinesDir
        )
        wpmodel = funcs.signalFitInterpolationWithSpline(category, ws, 
            [
                (wp120, tripleGaus120, diMuonMass120),
                (wp125, tripleGaus125, diMuonMass125),
                (wp130, tripleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir
        )
        wmmodel = funcs.signalFitInterpolationWithSpline(category, ws, 
            [
                (wm120, tripleGaus120, diMuonMass120),
                (wm125, tripleGaus125, diMuonMass125),
                (wm130, tripleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir
        )
        zhmodel = funcs.signalFitInterpolationWithSpline(category, ws, 
            [
                (zh120, tripleGaus120, diMuonMass120),
                (zh125, tripleGaus125, diMuonMass125),
                (zh130, tripleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir
        )
        
        #
        # Perform the F-Test and select the proper order of the 
        #
        selectedOrderedModels = [] # ordered models for this category that passed the f-test

        for modelGroup in orderedGroupsToUse:  # ModelGroup has a name for the group and a list of models
            counter = 0;
            for m in modelGroup.models:
                m.color = colors[counter]
                counter+=1

            # return the model with the order that passes the ftest
                # e.g. berenstein6 for berensten model group or sumExp3 for sum exp model group
            
            # ftestPerFamily imported from Modeling/higgs2/generatingFunctions.py
            selectedModel, values = funcs.ftestPerFamily(
                (category, diMuonMass125), ws, data, modelGroup,
                settings, pathToDir=fffTestDir, unblind=args.unblind)
            if selectedModel is not None:
                selectedOrderedModels.append(selectedModel)

            # Save ftest results for each category,modelgroup
            fTestResults[category][modelGroup.name] = values

        #
        # Create the Background Model
        #
        totalModelGroup = ModelGroup("bkgModels",
            physGroupTest.models + selectedOrderedModels)
        counter = 0
        for model in totalModelGroup.models:
            model.color = colors[counter]
            counter += 1

        # Multipdf for background with physics based models and the ftest passed ordered models
        # !!! DOES NOT use modelGroupForMultiPdf from config file !!!
        funcs.backgroundsWithRooMultiPdf((category, diMuonMass125), ws, data, 
            totalModelGroup.models, settings, pathToDir=backgroundsDir,
            groupName=totalModelGroup.name, unblind=args.unblind)

        #
        # Signal and Background Models are ready and are in the Workspace
        # create the datacard for this category
        #
        funcs.datacardAnalytic(category, ws, data, 
            [vbfmodel, glumodel, wpmodel, wmmodel, zhmodel], 
            ws.pdf("multipdf_{category}".format(category=names2RepsToUse[category])),
            settings,
            pathToDir=datacardsDir,
            workspaceFileName=workspaceFileName,
            workspaceName=workspaceName,
            withSystematics=args.withSystematics
        )

        #
        # save the Workspacee
        #
        ws.SaveAs(os.path.join(datacardsDir, workspaceFileName))

    #
    # plot all the F-test results
    #
    funcs.plotFTestResults(fTestResults, pathToDir=fffTestDir)
Exemple #8
0
def datacardsSingleGaus():
    physGroupToUse = physGroupTest
    orderedGroupsToUse = orderedGroupsTest
    workspaceName = "higgs"
    signalSplinesDir = os.path.join(signalfitinterpolationswithsplineDir, args.outDirName)
    backgroundsDir = os.path.join(backgroundfitswithroomultipdfDir, args.outDirName)
    datacardsDir = os.path.join(datacardsworkspacesDir, args.outDirName)
    fffTestDir = os.path.join(ftestDir, args.outDirName)
    aux.mkdir(signalSplinesDir); aux.mkdir(backgroundsDir); aux.mkdir(datacardsDir)
    aux.mkdir(fffTestDir)
    fTestResults = {}
    for category in categoriesToUse:
        fTestResults[category] = {}
        workspaceFileName = "workspace__{category}__{signalModelId}.root".format(
            category=names2RepsToUse[category], signalModelId = singleGaus120.modelId)
        ws = R.RooWorkspace(workspaceName)
        aux.buildMassVariable(ws, **diMuonMass125)
        aux.buildMH(ws, mhmin=120, mhmax=130)

        #
        # create the RooDataHist and import it into the Workspace here explicitly
        #
        fdata = R.TFile(data.pathToFile)

        hdata_name = category + "/DiMuonMass"
        if settings.useInputFileUF:
            hdata_name = "net_histos/"+category+"_Net_Data"

        hdata = fdata.Get(hdata_name)
        rdata = aux.buildRooHist(ws, hdata,
            "data_obs_{category}".format(category=names2RepsToUse[category]))
        getattr(ws, "import")(rdata, R.RooFit.RecycleConflictNodes())
        fdata.Close()
        
        #
        # Create the Signal Models
        #
        print "*"*80
        print "Generating Single Gaus Splines"
        print "*"*80
        vbfmodel = funcs.signalFitInterpolationWithSpline(category, ws, 
            [
                (vbf120, singleGaus120, diMuonMass120),
                (vbf125, singleGaus125, diMuonMass125),
                (vbf130, singleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir
        )
        glumodel = funcs.signalFitInterpolationWithSpline(category, ws, 
            [
                (glu120, singleGaus120, diMuonMass120),
                (glu125, singleGaus125, diMuonMass125),
                (glu130, singleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir
        )
        wpmodel = funcs.signalFitInterpolationWithSpline(category, ws, 
            [
                (wp120, singleGaus120, diMuonMass120),
                (wp125, singleGaus125, diMuonMass125),
                (wp130, singleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir
        )
        wmmodel = funcs.signalFitInterpolationWithSpline(category, ws, 
            [
                (wm120, singleGaus120, diMuonMass120),
                (wm125, singleGaus125, diMuonMass125),
                (wm130, singleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir
        )
        zhmodel = funcs.signalFitInterpolationWithSpline(category, ws, 
            [
                (zh120, singleGaus120, diMuonMass120),
                (zh125, singleGaus125, diMuonMass125),
                (zh130, singleGaus130, diMuonMass130),
            ],
            settings,
            pathToDir=signalSplinesDir
        )

        #
        # Perform the F-Test and select the proper order of the 
        #
        selectedOrderedModels = []
        for modelGroup in orderedGroupsToUse:
            counter = 0;
            for m in modelGroup.models:
                m.color = colors[counter]
                counter+=1
            selectedModel, values = funcs.ftestPerFamily(
                (category, diMuonMass125), ws, data, modelGroup,
                settings, pathToDir=fffTestDir)
            if selectedModel is not None:
                selectedOrderedModels.append(selectedModel)
            fTestResults[category][modelGroup.name] = values

        #
        # Create the Background Model
        #
        totalModelGroup = ModelGroup("bkgModels", 
            physGroupTest.models + selectedOrderedModels)
        counter = 0
        for model in totalModelGroup.models:
            model.color = colors[counter]
            counter += 1
        funcs.backgroundsWithRooMultiPdf((category, diMuonMass125), ws, data, 
            totalModelGroup.models, settings,
            pathToDir=backgroundsDir,
            groupName=totalModelGroup.name)

        #
        # Signal and Background Models are ready and are in the Workspace
        # create the datacard for this category
        #
        funcs.datacardAnalytic(category, ws, data, 
            [vbfmodel, glumodel, wpmodel, wmmodel, zhmodel], 
            ws.pdf("multipdf_{category}".format(category=names2RepsToUse[category])),
            settings,
            pathToDir=datacardsDir,
            workspaceFileName=workspaceFileName,
            workspaceName=workspaceName,
            withSystematics=args.withSystematics
        )

        #
        # save the Workspacee
        #
        print "*"*80
        print "*** Final RooWorkspace contents ***"
        print "*"*80
        ws.Print("v")
        ws.SaveAs(os.path.join(datacardsDir, workspaceFileName))

    #
    # plot all the F-Test Results
    #
    funcs.plotFTestResults(fTestResults, pathToDir=fffTestDir)
def signalFitInterpolationWithSpline(category, ws, tupleSignalModelVariable, settings,
    **wargs):
    """
    assume the Workspace already exists and x-variable is already defined
    """
    #
    # Load Combine's lib
    #
    R.gSystem.Load("libHiggsAnalysisCombinedLimit.so")

    # 
    # initialize the values from wargs
    # 
    pathToDir = "/tmp"
    if "pathToDir" in wargs:
        pathToDir = wargs["pathToDir"]

    #
    # the the canvas/frame
    #
    canvas = R.TCanvas("c1", "c1", 800, 600)
    canvas.cd()
    
    #
    # for each mass point, perform a fit.
    # initial values for each consecutive model will be derived from the 
    # previous mass point
    #
    imodel = 0
    prevSignal=None; prevModel=None; prevVariable=None
    parameters = []
    massPoints = []
    norms = []
    for (signal, model, variable) in tupleSignalModelVariable:
        fsdata = R.TFile(signal.pathToFile)
        frame = ws.var("x").frame()

        hsdata_name = category + "/" + variable["name"]
        if settings.useInputFileUF: 
            hsdata_name = "signal_histos/" + category + "_" + signal.mc.uflabel

        hsdata = fsdata.Get(hsdata_name)
        if not settings.useInputFileUF:
            hsdata.Scale(1/signal.getWeight())
        rsdata = aux.buildRooHist(ws, hsdata)
        binfirst = hsdata.FindBin(variable["min"])
        binlast = hsdata.FindBin(variable["max"])
#        norms.append(hsdata.Integral(binfirst, binlast))
        norms.append(rsdata.sumEntries())
        model.initialize(aux.buildSignalModelName(model, 
            settings.names2RepsToUse[category],
            signal.mc.buildProcessName(), variable["central"]))
        if imodel>0:
            model.setInitialValuesFromModel(prevModel, ws, 
                massDifference=(variable["central"] - prevVariable["central"]))
        model.createParameters(ws)
        pdf = model.build(ws, category=category)
        #
        # Fit twice???
        # Andrea has it like that??? May be second time has better initial values???
        #
        r = pdf.fitTo(rsdata, R.RooFit.Save(),
            R.RooFit.Range(variable["fitmin"], variable["fitmax"]),
            R.RooFit.SumW2Error(R.kTRUE))
        prevSignal = signal
        prevModel = model
        prevVariable = variable
        imodel +=1
        massPoints.append(variable["central"])

        # plot this model together with signal histogram
        rsdata.plotOn(frame)
        pdf.plotOn(frame, R.RooFit.LineColor(R.kBlue))

        # draw the frame and save the canvas
        frame.SetTitle("{category}_{higgsMass}_{processName}".format(category=category, higgsMass=variable["central"], processName=signal.mc.buildProcessName()))
        frame.Draw()
        fileName = "signalFit__{category}__{higgsMass}__{processName}__{modelId}__{mods}.png".format(
            category=category, higgsMass=variable["central"], processName=signal.mc.buildProcessName(),
            modelId=model.modelId, mods="default")
        canvas.SaveAs(os.path.join(pathToDir, fileName))

        # exctract the parameters
        lParameters = model.getParameterValuesAsList(ws)
        parameters.append(lParameters)
        print "*"*90 + "\n"
        print "*"*90 + "\n"
        print lParameters
        print parameters
        r.Print("v")

#        pdf.plotOn(frame, R.RooFit.LineColor(R.kBlue))
        imodel+=1

    #
    # build the Splines
    # create the spline for normalization
    # have to transpose the matrix of parameters first
    #
    frame = ws.var("x").frame()
    paramsTransposed = aux.transpose(parameters)
    print "*"*90 + "\n"
    print "*"*90 + "\n"
    print "*"*90 + "\n"
    print "*"*90 + "\n"
    print parameters
    print paramsTransposed
    finalmodel = prevModel.__class__()
    finalmodel.initialize(aux.buildSignalModelName(finalmodel, 
        settings.names2RepsToUse[category], signal.mc.buildProcessName()))
    finalpdf = finalmodel.buildWithParameterMatrix(ws, massPoints, paramsTransposed)
    finalmodel.setNormalization(ws, massPoints, norms)
    finalpdf.Print("v")

    #
    # plot for each GeV and save the canvas
    #
    for mh in [120+i for i in range(11)]:
        ws.var("MH").setVal(mh)
        finalpdf.plotOn(frame)

    #
    # save the canvas
    #
    frame.SetTitle("{category}_{processName}".format(category=category, processName=signal.mc.buildProcessName()))
    frame.Draw()
    fileName = "signalFitInterpolationWithSpline__{category}__{processName}__{modelId}__{mods}.png".format(category=category, processName=signal.mc.buildProcessName(), modelId=model.modelId, mods="")
    canvas.SaveAs(os.path.join(pathToDir, fileName))

    #
    # return the model that you build with RooSplines
    #
    return finalmodel
    #
    # get the histogram from the input root file
    # and convert to a roo hist
    #
    fsdata = R.TFile(signal.pathToFile)

    hsdata_name = category + "/" + variable["name"]
    if settings.useInputFileUF: 
        hsdata_name = "signal_histos/" + category + "_" + signal.mc.uflabel

    hsdata = fsdata.Get(hsdata_name)
    if not settings.useInputFileUF:
        hsdata.Scale(1/signal.getWeight())
#    hsdata.GetXaxis().SetRange(variable["min"], variable["max"])
    rsdata = aux.buildRooHist(ws, hsdata)

    #
    # set up the model and perform the fit
    #

    # Simply set the name for the model based upon the model, category, and M=120,125,or 130 
    model.initialize(aux.buildSignalModelName(model, settings.names2RepsToUse[category], 
        signal.mc.buildProcessName(), variable["central"]))

    # Set the initial signal model parameters based upon the mean and rms of the signal histogram
    # for this category, seems reasonable for single gauss, but not sure what it does for double
    # and triple gauss
    if initialValuesFromTH1:
        model.setInitialValuesFromTH1(hsdata)
    model.createParameters(ws)                 # Create params for model and add to workspace