Beispiel #1
0
            return False
    return True


if __name__ == "__main__":
    parser = commonLimitTools.createOptionParser(lepType, lhcType,
                                                 lhcTypeAsymptotic)
    parser.add_option("--postfix",
                      dest="postfix",
                      default="",
                      help="Postfix to add to output directory name")
    opts = commonLimitTools.parseOptionParser(parser)
    # General settings

    myDirs = opts.dirs[:]
    if len(myDirs) == 0:
        myDirs.append(".")

    for myDir in myDirs:
        print "Considering directory:", myDir
        settings = commonLimitTools.GeneralSettings(myDir, opts.masspoints)
        print "The following masses are considered:", settings.getMassPoints(
            commonLimitTools.LimitProcessType.TAUJETS)
        if not main(opts, settings, myDir):
            print ""
            parser.print_help()
            print ""
            raise Exception(
                "You forgot to specify limit calculation method as a command line parameter!"
            )
Beispiel #2
0
  if not os.path.exists(_dirname):
      os.mkdir(_dirname)
  # Apply TDR style
  style = tdrstyle.TDRStyle()
  histograms.createLegend.moveDefaults(dx=-0.1, dh=-0.15)
  histograms.uncertaintyMode.set(histograms.Uncertainty.StatOnly)
  styles.ratioLineStyle.append(styles.StyleLine(lineColor=13))
  # Find out the mass points
 
  nameList = []
  allShapeNuisances = []
  signalTable = {}
  myDatacardPattern = ""
  myRootfilePattern = ""
  if opts.cardPattern == None:
      mySettings = limitTools.GeneralSettings(".",[])
      myDatacardPattern = mySettings.getDatacardPattern(limitTools.LimitProcessType.TAUJETS)
      myRootfilePattern = mySettings.getRootfilePattern(limitTools.LimitProcessType.TAUJETS)
  else:
      myDatacardPattern = opts.cardPattern.replace("MMM","M%s").replace("MM","%s")
      myRootfilePattern = opts.rootfilePattern.replace("MMM","M%s").replace("MM","%s")
  massPoints = DatacardReader.getMassPointsForDatacardPattern(".", myDatacardPattern)
  print "The following masses are considered:",massPoints
  for m in massPoints:
      # Obtain luminosity from datacard
      myLuminosity = float(limitTools.readLuminosityFromDatacard(".",myDatacardPattern%m))
      # Do plots
      doPlot(opts,int(m),nameList,allShapeNuisances,myLuminosity,myDatacardPattern,myRootfilePattern,signalTable)
  # Print signal table
  print "Max contracted uncertainty for signal:"
  for k in signalTable.keys():
Beispiel #3
0
def main(opts):
    # Check that input arguments are sufficient
    if opts.settings == None:
        raise Exception(
            ErrorLabel() +
            "Please provide input parameter file with -x or --params !")

    # Load settings
    print "Loading settings:", opts.settings
    if not os.path.exists(opts.settings):
        raise Exception(ErrorLabel() +
                        "Cannot find settings file '%s'!" % opts.settings)
    os.system("python %s" %
              opts.settings)  # Catch any errors in the input datacard
    config = aux.load_module(opts.settings)
    checkSettings(config)
    os.system("cp %s ." % opts.settings)
    myFitSettingsList = config.fitSettings[:]

    # Copy unfitted cards for provenance information if necessary
    if not os.path.exists(_myOriginalDir):
        os.mkdir(_myOriginalDir)
        os.system("mv *.txt %s/." % _myOriginalDir)
        os.system("mv *.root %s/." % _myOriginalDir)
        print "Moved original datacards as provenance info to %s" % _myOriginalDir
    else:
        items = glob.glob("*.txt")
        if len(items):
            os.system("rm *.txt")
        items = glob.glob("*.root")
        if len(items):
            os.system("rm *.root")

    # Find datacards
    myLimitSettings = limitTools.GeneralSettings(_myOriginalDir, [])
    massPoints = myLimitSettings.getMassPoints(
        limitTools.LimitProcessType.TAUJETS)
    myDatacardPattern = myLimitSettings.getDatacardPattern(
        limitTools.LimitProcessType.TAUJETS)
    myRootfilePattern = myLimitSettings.getRootfilePattern(
        limitTools.LimitProcessType.TAUJETS)

    # Loop over mass points
    myDrawPlotsStatus = True
    myShapeSensitivityTestStatus = False
    myShapeSensitivityTestLabel = ""
    for m in massPoints:
        myHistogramCache = []
        # Obtain luminosity
        myLuminosity = float(
            limitTools.readLuminosityFromDatacard(_myOriginalDir, "%s" %
                                                  myDatacardPattern % m))
        # Obtain root file
        myRootFile = ROOT.TFile.Open("%s/%s" %
                                     (_myOriginalDir, myRootfilePattern % m))
        # Obtain datacard
        myOriginalCardFile = open("%s/%s" %
                                  (_myOriginalDir, myDatacardPattern % m))
        myOriginalCardLines = myOriginalCardFile.readlines()
        myOriginalCardFile.close()
        # Obtain column and nuisance info
        myColumnNames = parseColumnNames(myOriginalCardLines)
        myNuisanceInfo = parseNuisanceNames(myOriginalCardLines, myColumnNames)
        myFitParNuisanceInfo = None
        # Treat observation
        hObs = getAndRebinRateHisto("data_obs", myRootFile,
                                    config.finalBinning["shape"])
        myPath = os.getcwd()
        if "SignalInjection" in myPath:
            for k in range(0, hObs.GetNbinsX() + 1):
                hObs.SetBinContent(k, round(hObs.GetBinContent(k)))
            for n in myNuisanceInfo:
                if n["name"] == "observation":
                    n["value"] = hObs.Integral()
        if "SHAPETEST" in myPath:
            hObs.Reset()
            myShapeSensitivityTestStatus = True
            mySplit = myPath.split("_")
            for i in range(0, len(mySplit)):
                if mySplit[i] == "SHAPETEST":
                    myShapeSensitivityTestLabel = "_".join(
                        map(str, mySplit[i + 1:len(mySplit)]))
                    myShapeSensitivityTestLabel = myShapeSensitivityTestLabel.replace(
                        "UP", "Up").replace("DOWN", "Down")
        myHistogramCache.append(hObs)
        # Loop over column names
        for c in myColumnNames:
            print HighlightStyle() + "Processing column %s for mass %s" % (
                c, m) + NormalStyle()
            if _isSignal(c) or c in config.Blacklist:
                print "... skipping fit (signal or blacklist)"
                # Obtain and rebin rate histo
                hRate = getAndRebinRateHisto(c, myRootFile,
                                             config.finalBinning["shape"])
                if _isSignal(c):
                    hRate.Scale(opts.lumiProjection)
                else:
                    hRate.Scale(opts.lumiProjection * opts.bkgxsecProjection)
                myHistogramCache.append(hRate.Clone())
                # Update rate
                for n in myNuisanceInfo:
                    if n["name"] == "rate":
                        n[c] = "%f" % hRate.Integral()
                # Obtain and rebin nuisance histos
                hNuisances = getAndRebinNuisanceHistos(
                    c, myRootFile, myNuisanceInfo,
                    config.finalBinning["shape"])
                for h in hNuisances:
                    if _isSignal(c):
                        h.Scale(opts.lumiProjection)
                    else:
                        h.Scale(opts.lumiProjection * opts.bkgxsecProjection)
                myHistogramCache.extend(hNuisances)
                # Treat QCD shape uncertainty separately (for testing only; one should use the tail fit for QCD)
                #hNuisances = getAndRebinQCDShapeNuisanceHistos(c, myRootFile, hRate, myNuisanceInfo, config.finalBinning["shape"])
                #myHistogramCache.extend(hNuisances)
                # Create bin-by-bin stat. histograms for fitted distribution and update the nuisance table
                myStatHistograms = addBinByBinStatUncert(config,
                                                         c,
                                                         hRate,
                                                         myColumnNames,
                                                         myNuisanceInfo,
                                                         isSignal=True)
                myHistogramCache.extend(myStatHistograms)
                if myShapeSensitivityTestStatus and not _isSignal(c):
                    hObs.Add(hRate)  # Add the fitted histogram
                    # Add the nuisance with proper binning
                    for h in hNuisances:
                        if myShapeSensitivityTestLabel in h.GetName():
                            hObs.Add(h)
                            hObs.Add(hRate, -1.0)
            else:
                # Not signal or blacklist, do fit
                hFineBinning = myRootFile.Get(c + "_fineBinning")
                for i in range(1, hFineBinning.GetNbinsX() + 1):
                    hFineBinning.SetBinContent(
                        i,
                        hFineBinning.GetBinContent(i) * opts.lumiProjection *
                        opts.bkgxsecProjection)
                    hFineBinning.SetBinError(
                        i,
                        hFineBinning.GetBinError(i) / math.sqrt(
                            opts.lumiProjection * opts.bkgxsecProjection))
                if hFineBinning == None:
                    raise Exception(ErrorLabel() +
                                    "Cannot find histogram '%s'!" %
                                    (c + "_fineBinning"))
                hOriginalShape = myRootFile.Get(c)
                hOriginalShape.SetName(hOriginalShape.GetName() + "Original")
                for i in range(1, hOriginalShape.GetNbinsX() + 1):
                    hOriginalShape.SetBinContent(
                        i,
                        hOriginalShape.GetBinContent(i) * opts.lumiProjection *
                        opts.bkgxsecProjection)
                    hOriginalShape.SetBinError(
                        i,
                        hOriginalShape.GetBinError(i) / math.sqrt(
                            opts.lumiProjection * opts.bkgxsecProjection))
                if hOriginalShape == None:
                    raise Exception(ErrorLabel() +
                                    "Cannot find histogram '%s'!" % (c))
                # Proceed
                myFitSettings = None
                for s in myFitSettingsList:
                    if s["id"] in c:
                        myFitSettings = s
                        print "... using fitfunc: %s and range %d-%d" % (
                            s["fitfunc"], s["fitmin"], s["fitmax"])
                if myFitSettings == None:
                    raise Exception(
                        "Could not determine fit function for column '%s'!" %
                        c)
                myFitter = TailFitter.TailFitter(hFineBinning,
                                                 c,
                                                 myFitSettings["fitfunc"],
                                                 myFitSettings["fitmin"],
                                                 myFitSettings["fitmax"],
                                                 myFitSettings["applyFrom"],
                                                 doPlots=myDrawPlotsStatus,
                                                 luminosity=myLuminosity)
                # Obtain fitted rate with final binning
                myFittedRateHistograms = myFitter.getFittedRateHistogram(
                    hFineBinning, config.finalBinning["shape"],
                    myFitSettings["applyFrom"])
                myHistogramCache.extend(myFittedRateHistograms)
                # Update rate
                for n in myNuisanceInfo:
                    if n["name"] == "rate":
                        n[c] = "%f" % myFittedRateHistograms[0].Integral()
                        print "... Updated rate because of fitting %.1f -> %.1f (diff=%f)" % (
                            hFineBinning.Integral(),
                            myFittedRateHistograms[0].Integral(),
                            myFittedRateHistograms[0].Integral() /
                            hFineBinning.Integral())
                # Update all those shape nuisances (update histograms only, no need to touch nuisance table)
                for n in myNuisanceInfo:
                    if n["name"] != "observation" and n[
                            "distribution"] == "shape" and n[c] == "1":
                        #print "... Updating shape nuisance '%s' tail"%n["name"]
                        myUpdatedNuisanceHistograms = updateNuisanceTail(
                            opts, hOriginalShape, myFittedRateHistograms[0],
                            myRootFile, "%s_%s" % (c, n["name"]))
                        myHistogramCache.extend(myUpdatedNuisanceHistograms)
                if myShapeSensitivityTestStatus:
                    # Check if the nuisance histograms exist for this column
                    myHistoName = "%s_%s" % (
                        c, myShapeSensitivityTestLabel.replace(
                            "Up", "").replace("Down", ""))
                    myList = updateNuisanceTail(opts,
                                                hOriginalShape,
                                                myFittedRateHistograms[0],
                                                myRootFile,
                                                myHistoName,
                                                skipNotFoundTest=True)
                    #print "DEBUG",myHistoName,len(myList)
                    if len(myList) > 0:
                        # Add the nuisance with proper binning
                        if "Up" in myShapeSensitivityTestLabel:
                            hObs.Add(myList[0])
                            #print "DEBUG: Added nuisance",myShapeSensitivityTestLabel,myList[0].GetName(),myList[0].Integral()
                        elif "Down" in myShapeSensitivityTestLabel:
                            hObs.Add(myList[1])
                            #print "DEBUG: Added nuisance",myShapeSensitivityTestLabel,myList[1].GetName(),myList[1].Integral()
                        else:
                            raise Exception()  # Should not happen
                    else:
                        hObs.Add(myFittedRateHistograms[0]
                                 )  # Add the fitted histogram
                        #print "DEBUG: Added",myFittedRateHistograms[0].Integral()
                print "Updated shape nuisance tails (rel.uncert. kept constant, but central value changed to the fitted one)"
                # Obtain fit uncertainty histograms and add them to cache
                (huplist, hdownlist) = myFitter.calculateVariationHistograms(
                    config.finalBinning["shape"], myFitSettings["applyFrom"])
                # Plot if requested
                if myDrawPlotsStatus:
                    myArray = array.array("d", config.finalBinning["shape"])
                    hFinalBinning = hFineBinning.Rebin(
                        len(myArray) - 1, "", myArray)
                    myFitter.makeVariationPlotDetailed(
                        "", hFinalBinning, myFittedRateHistograms[0], huplist,
                        hdownlist)
                    (hupTotal,
                     hdownTotal) = myFitter.calculateTotalVariationHistograms(
                         myFittedRateHistograms[0], huplist, hdownlist)
                    myFitter.makeVariationPlotSimple("", hFinalBinning,
                                                     myFittedRateHistograms[0],
                                                     hupTotal, hdownTotal,
                                                     s["fitmin"])
                    # print total uncertainty
                    print "*** Syst. uncert. from fit: +", 1.0 - hupTotal.Integral(
                    ) / myFittedRateHistograms[0].Integral(
                    ), "-", 1.0 - hdownTotal.Integral(
                    ) / myFittedRateHistograms[0].Integral()

                    hFinalBinning.Delete()

                # Treat blancs (norm == 0)
                for i in range(0, len(huplist)):
                    if huplist[i].Integral() == 0:
                        for k in range(0, huplist[i].GetNbinsX() + 2):
                            huplist[i].SetBinContent(
                                k, myFittedRateHistograms[0].GetBinContent(k))
                    if hdownlist[i].Integral() == 0:
                        for k in range(0, hdownlist[i].GetNbinsX() + 2):
                            hdownlist[i].SetBinContent(
                                k, myFittedRateHistograms[0].GetBinContent(k))
                if config.applyFitUncertaintyAsBinByBinUncertainty:
                    # Add fit uncertainty as bin-by-bin type uncertainty
                    (hupTotal,
                     hdownTotal) = myFitter.calculateTotalVariationHistograms(
                         myFittedRateHistograms[0], huplist, hdownlist)
                    (myBinByBinUpHistograms, myBinByBinDownHistograms
                     ) = createBinnedFitUncertaintyHistograms(
                         myFittedRateHistograms[0], hupTotal, hdownTotal,
                         myFitSettings["applyFrom"], opts)
                    if not opts.noFitUncert:
                        myHistogramCache.extend(myBinByBinUpHistograms)
                        myHistogramCache.extend(myBinByBinDownHistograms)
                        # Add fit parameter nuisances to nuisance table
                        for hup in myBinByBinUpHistograms:
                            addNuisanceForIndividualColumn(
                                myColumnNames, myNuisanceInfo, c,
                                hup.GetTitle().replace("%s_%s" % (c, c), c))
                else:
                    # Add fit uncertainty as nuisances parameters
                    if not opts.noFitUncert:
                        myHistogramCache.extend(huplist)
                        myHistogramCache.extend(hdownlist)
                        # Add fit parameter nuisances to nuisance table
                        for hup in huplist:
                            addNuisanceForIndividualColumn(
                                myColumnNames, myNuisanceInfo, c,
                                hup.GetTitle())
                # Create bin-by-bin stat. histograms for fitted distribution and update the nuisance table
                myStatHistograms = addBinByBinStatUncert(
                    config,
                    c,
                    myFittedRateHistograms[0],
                    myColumnNames,
                    myNuisanceInfo,
                    0.0,
                    myFitSettings["applyFrom"],
                    isSignal=False)
                myHistogramCache.extend(myStatHistograms)
                # Clear memory
                hFineBinning.Delete()
                hOriginalShape.Delete()
        for h in myHistogramCache:
            h.SetDirectory(None)
        myRootFile.Close()
        myDrawPlotsStatus = False
        myObsIntegral = hObs.Integral()
        # Print summary info
        printSummaryInfo(myColumnNames, myNuisanceInfo, myHistogramCache, hObs,
                         m, myLuminosity, opts)
        # Histogram cache contains now all root files and nuisance table is now up to date
        # Create new root file and write
        myRootFilename = myRootfilePattern % m
        myRootFile = ROOT.TFile.Open(myRootFilename, "RECREATE")
        if myRootFile == None:
            raise Exception(ErrorLabel() + " Cannot open file '" +
                            myRootFilename + "' for output!")
        for h in myHistogramCache:
            h.SetDirectory(myRootFile)
        myRootFile.Write()
        myRootFile.Close()
        # Create new datacard file and write
        myOutput = createDatacardOutput(myOriginalCardLines, myColumnNames,
                                        myNuisanceInfo, opts, myObsIntegral)
        myFilename = myDatacardPattern % m
        myFile = open(myFilename, "w")
        myFile.write(myOutput)
        myFile.close()
        print "... Generated datacard files %s and %s" % (myFilename,
                                                          myRootFilename)
Beispiel #4
0
def main(opts):

    # Apply TDR style
    style = tdrstyle.TDRStyle()
    style.setGridX(opts.gridx)
    style.setGridY(opts.gridy)
    style.setLogX(opts.logx)
    style.setLogY(opts.logy)

    # Create legend and set style
    histograms.createLegend.moveDefaults(dx=-0.1, dh=-0.15)
    histograms.uncertaintyMode.set(histograms.Uncertainty.StatOnly)
    styles.ratioLineStyle.append(styles.StyleLine(lineColor=13))

    # Define some variables
    nameList = []
    allShapeNuisances = []
    signalTable = {}
    myDatacardPattern = ""
    myRootfilePattern = ""

    # Find out the mass points
    if opts.cardPattern == None:
        mySettings = limitTools.GeneralSettings(".", [])
        myDatacardPattern = mySettings.getDatacardPattern(
            limitTools.LimitProcessType.TAUJETS)
        myRootfilePattern = mySettings.getRootfilePattern(
            limitTools.LimitProcessType.TAUJETS)
    else:
        myDatacardPattern = opts.cardPattern.replace("MMM", "M%s").replace(
            "MM", "%s")
        myRootfilePattern = opts.rootfilePattern.replace("MMM", "M%s").replace(
            "MM", "%s")

    # Get mass points to consider
    massPoints = DatacardReader.getMassPointsForDatacardPattern(
        ".", myDatacardPattern)
    Print(
        "The following masses will be considered: %s" %
        (ShellStyles.HighlightAltStyle() + ", ".join(massPoints) +
         ShellStyles.NormalStyle()), True)

    # For-loop: All mass points
    for i, m in enumerate(massPoints, 1):
        # Obtain luminosity from the datacard
        myLuminosity = float(
            limitTools.readLuminosityFromDatacard(".", myDatacardPattern % m))

        # Do the plots
        doPlot(opts, int(m), nameList, allShapeNuisances, myLuminosity,
               myDatacardPattern, myRootfilePattern, signalTable)

    # Print signal table
    Print("Max contracted uncertainty for signal:", True)
    table = []
    align = "{:>15} {:>15} {:>15}"
    hLine = "=" * 50
    table.append(hLine)
    table.append(align.format("Systematic", "Minimum", "Maximum"))
    table.append(hLine)
    # For-loop: All signal
    for i, k in enumerate(signalTable.keys(), 1):
        # Print("Key = %s" % (k), False)
        minVal = "%.3f" % (signalTable[k]["min"])
        maxVal = "%.3f" % (signalTable[k]["max"])
        msg = align.format(k, minVal, maxVal)
        table.append(msg)
    table.append(hLine)
    for row in table:
        Print(row, False)

    msg = "All results under directory %s" % (
        ShellStyles.SuccessStyle() + opts.dirName + ShellStyles.NormalStyle())
    Print(msg, True)

    return