def _doCalculate(self, shape, moduleInfoString, normFactors, optionPrintPurityByBins, optionDoNQCDByBinHistograms):
        '''
        Calculates the result
        '''
        Verbose("Calculate final shape in signal region (shape * w_QCD) & initialize result containers", True)
        nSplitBins = shape.getNumberOfPhaseSpaceSplitBins()

        Verbose("Create Shape", True)
        self._resultShape = aux.Clone(shape.getDataDrivenQCDHistoForSplittedBin(0))
        self._resultShape.Reset()
        self._resultShape.SetTitle("NQCDFinal_Total_%s"%moduleInfoString)
        self._resultShape.SetName("NQCDFinal_Total_%s"%moduleInfoString)

        Verbose("Create EWK shape", True)
        self._resultShapeEWK = aux.Clone(shape.getDataDrivenQCDHistoForSplittedBin(0))
        self._resultShapeEWK.Reset()
        self._resultShapeEWK.SetTitle("NQCDFinal_EWK_%s"%moduleInfoString)
        self._resultShapeEWK.SetName("NQCDFinal_EWK_%s"%moduleInfoString)

        Verbose("Create Purity shape", True)
        self._resultShapePurity = aux.Clone(shape.getDataDrivenQCDHistoForSplittedBin(0))
        self._resultShapePurity.Reset()
        self._resultShapePurity.SetTitle("NQCDFinal_Purity_%s"%moduleInfoString)
        self._resultShapePurity.SetName("NQCDFinal_Purity_%s"%moduleInfoString)

        self._histogramsList = []
        myUncertaintyLabels  = ["statData", "statEWK"]
        self._resultCountObject = extendedCount.ExtendedCount(0.0, [0.0, 0.0], myUncertaintyLabels)

        if optionDoNQCDByBinHistograms:
            for i in range(0, nSplitBins):
                hBin = aux.Clone(self._resultShape)
                hBin.SetTitle("NQCDFinal_%s_%s"%(shape.getPhaseSpaceBinFileFriendlyTitle(i).replace(" ",""), moduleInfoString))
                hBin.SetName("NQCDFinal_%s_%s"%(shape.getPhaseSpaceBinFileFriendlyTitle(i).replace(" ",""), moduleInfoString))
                self._histogramsList.append(hBin)

        if isinstance(self._resultShape, ROOT.TH2):
            self._doCalculate2D(nSplitBins, shape, normFactors, optionPrintPurityByBins, optionDoNQCDByBinHistograms, myUncertaintyLabels)
            return

        # Intialize counters for purity calculation in final shape binning
        myShapeDataSum       = []
        myShapeDataSumUncert = []
        myShapeEwkSum        = []
        myShapeEwkSumUncert  = []

        # For-loop: All Bins
        for j in range(1,self._resultShape.GetNbinsX()+1):
            myShapeDataSum.append(0.0)
            myShapeDataSumUncert.append(0.0)
            myShapeEwkSum.append(0.0)
            myShapeEwkSumUncert.append(0.0)

        Verbose("Calculate results separately for each phase-space bin and then combine", True)
        # For-loop: All measurement bins (e.g. tau pT bins for HToTauNu)
        for i in range(0, nSplitBins):
            # N.B: The \"Inclusive\" value is in the zeroth bin

            Verbose("Get data-driven QCD, data, and MC EWK shape histogram for the phase-space bin", True)
            h     = shape.getDataDrivenQCDHistoForSplittedBin(i)
            hData = shape.getDataHistoForSplittedBin(i)
            hEwk  = shape.getEwkHistoForSplittedBin(i)
            
            Verbose("Get normalization factor", True)
            wQCDLabel = shape.getPhaseSpaceBinFileFriendlyTitle(i)
            if self._optionUseInclusiveNorm:
                wQCDLabel = "Inclusive"
            wQCD = 0.0
            
            if not wQCDLabel in normFactors.keys():
                msg = "No normalization factors available for bin '%s' when accessing histogram %s! Ignoring this bin..." % (wQCDLabel,shape.getHistoName())
                Print(ShellStyles.WarningLabel() + msg, True)
            else:
                wQCD = normFactors[wQCDLabel]                
            msg = "Weighting bin \"%i\" (label=\"%s\")  with normFactor \"%s\"" % (i, wQCDLabel, wQCD)
            Verbose(ShellStyles.NoteLabel() + msg, True)

            # Construct info table (debugging)
            table  = []
            align  = "{:>6} {:^10} {:^15} {:>10} {:>10} {:>10} {:^3} {:^8} {:^3} {:^8}"
            header = align.format("Bin", "Width", "Range", "Content", "NormFactor", "QCD", "+/-", "Data", "+/-", "EWK")
            hLine  = "="*90
            table.append("{:^90}".format(shape.getHistoName()))
            table.append(hLine)
            table.append(header)
            table.append(hLine)

            binSum    = 0.0
            nBins     = h.GetNbinsX()
            binWidth  = hData.GetBinWidth(0)
            xMin      = hData.GetXaxis().GetBinCenter(0)
            xMax      = hData.GetXaxis().GetBinCenter(nBins+1)

            # For-Loop (nested): All bins in the shape histogram 
            for j in range(1, nBins+1):

                # Initialise values
                myResult         = 0.0
                myStatDataUncert = 0.0
                myStatEwkUncert  = 0.0

                # Ignore zero bins
                if abs(h.GetBinContent(j)) > 0.00001:
                    Verbose("Calculating the result")
                    binContent = h.GetBinContent(j)
                    binRange   = "%.1f -> %.1f" % (h.GetXaxis().GetBinLowEdge(j), h.GetXaxis().GetBinUpEdge(j) )
                    binWidth   = GetTH1BinWidthString(h, j)
                    binSum    += binContent
                    myResult   = binContent * wQCD #apply  normalisation factor (transfer from CR to SR))

                    Verbose("Calculate abs. stat. uncert. for data and for MC EWK (Do not calculate here MC EWK syst.)", True)
                    myStatDataUncert = hData.GetBinError(j) * wQCD
                    myStatEwkUncert  = hEwk.GetBinError(j)  * wQCD
                    table.append(align.format(j, binWidth, binRange, "%0.1f" % binContent, wQCD, "%.1f" % myResult, "+/-", "%.1f" % myStatDataUncert, "+/-", "%.1f" % myStatEwkUncert))

                # Get count object
                myCountObject = extendedCount.ExtendedCount(myResult, [myStatDataUncert, myStatEwkUncert], myUncertaintyLabels)
                self._resultCountObject.add(myCountObject)

                if optionDoNQCDByBinHistograms:
                    Verbose("Setting bin content \"%i\"" % (j), True)
                    self._histogramsList[i].SetBinContent(j, myCountObject.value())
                    self._histogramsList[i].SetBinError(j, myCountObject.statUncertainty())

                binContent = self._resultShape.GetBinContent(j) + myCountObject.value()
                binError   = self._resultShape.GetBinError(j) + myCountObject.statUncertainty()**2
                Verbose("Setting bin %i to content %0.1f +/- %0.1f" % (j, binContent, binError), j==0)
                self._resultShape.SetBinContent(j, binContent)
                self._resultShape.SetBinError(j, binError) # Sum squared (take sqrt outside loop on final squared sum)
                
                Verbose("Sum items for purity calculation", True)
                myShapeDataSum[j-1]       += hData.GetBinContent(j)*wQCD
                myShapeDataSumUncert[j-1] += (hData.GetBinError(j)*wQCD)**2
                myShapeEwkSum[j-1]        += hEwk.GetBinContent(j)*wQCD
                myShapeEwkSumUncert[j-1]  += (hEwk.GetBinError(j)*wQCD)**2

            # Delete the shape histograms
            h.Delete()
            hData.Delete()
            hEwk.Delete()

        # For-loop: All shape bins
        for j in range(1,self._resultShape.GetNbinsX()+1):
            # Take square root of uncertainties
            self._resultShape.SetBinError(j, math.sqrt(self._resultShape.GetBinError(j)))

        # Print detailed results in a formatted table
        qcdResults = self._resultCountObject.getResultAndStatErrorsDict()
        bins       = "%0.f-%.0f" % (1, nBins)
        binRange   = "%.1f -> %.1f" % (xMin, xMax)
        binSum     = "%.1f" % binSum
        nQCD       = "%.1f" % qcdResults["value"]
        dataStat   = "%.1f" % qcdResults["statData"]
        ewkStat    = "%.1f" % qcdResults["statEWK"]
        table.append(align.format(bins, binWidth, binRange, binSum, wQCD, nQCD, "+/-", dataStat, "+/-", ewkStat))
        table.append(hLine)
        for i, line in enumerate(table):
            if i == len(table)-2:
                Verbose(ShellStyles.TestPassedStyle()+line+ShellStyles.NormalStyle(), i==0)
            else:
                Verbose(line, i==0)

        if optionPrintPurityByBins:
            Verbose("Printing Shape Purity bin-by-bin.", True)
            self.PrintPurityByBins(nBins, shape, myShapeDataSum, myShapeDataSumUncert, myShapeEwkSum, myShapeEwkSumUncert)
        return
 def _doCalculate(self, shape, moduleInfoString, normFactors,
                  optionPrintPurityByBins, optionDoNQCDByBinHistograms):
     # Calculate final shape in signal region (shape * w_QCD)
     nSplitBins = shape.getNumberOfPhaseSpaceSplitBins()
     # Initialize result containers
     self._resultShape = aux.Clone(
         shape.getDataDrivenQCDHistoForSplittedBin(0))
     self._resultShape.Reset()
     self._resultShape.SetTitle("NQCDFinal_Total_%s" % moduleInfoString)
     self._resultShape.SetName("NQCDFinal_Total_%s" % moduleInfoString)
     self._resultShapeEWK = aux.Clone(
         shape.getDataDrivenQCDHistoForSplittedBin(0))
     self._resultShapeEWK.Reset()
     self._resultShapeEWK.SetTitle("NQCDFinal_EWK_%s" % moduleInfoString)
     self._resultShapeEWK.SetName("NQCDFinal_EWK_%s" % moduleInfoString)
     self._resultShapePurity = aux.Clone(
         shape.getDataDrivenQCDHistoForSplittedBin(0))
     self._resultShapePurity.Reset()
     self._resultShapePurity.SetTitle("NQCDFinal_Purity_%s" %
                                      moduleInfoString)
     self._resultShapePurity.SetName("NQCDFinal_Purity_%s" %
                                     moduleInfoString)
     self._histogramsList = []
     myUncertaintyLabels = ["statData", "statEWK"]
     self._resultCountObject = extendedCount.ExtendedCount(
         0.0, [0.0, 0.0], myUncertaintyLabels)
     if optionDoNQCDByBinHistograms:
         for i in range(0, nSplitBins):
             hBin = aux.Clone(self._resultShape)
             hBin.SetTitle(
                 "NQCDFinal_%s_%s" %
                 (shape.getPhaseSpaceBinFileFriendlyTitle(i).replace(
                     " ", ""), moduleInfoString))
             hBin.SetName(
                 "NQCDFinal_%s_%s" %
                 (shape.getPhaseSpaceBinFileFriendlyTitle(i).replace(
                     " ", ""), moduleInfoString))
             self._histogramsList.append(hBin)
     if isinstance(self._resultShape, ROOT.TH2):
         self._doCalculate2D(nSplitBins, shape, normFactors,
                             optionPrintPurityByBins,
                             optionDoNQCDByBinHistograms,
                             myUncertaintyLabels)
         return
     # Intialize counters for purity calculation in final shape binning
     myShapeDataSum = []
     myShapeDataSumUncert = []
     myShapeEwkSum = []
     myShapeEwkSumUncert = []
     for j in range(1, self._resultShape.GetNbinsX() + 1):
         myShapeDataSum.append(0.0)
         myShapeDataSumUncert.append(0.0)
         myShapeEwkSum.append(0.0)
         myShapeEwkSumUncert.append(0.0)
     # Calculate results separately for each phase space bin and then combine
     for i in range(0, nSplitBins):
         # Get data-driven QCD, data, and MC EWK shape histogram for the phase space bin
         h = shape.getDataDrivenQCDHistoForSplittedBin(i)
         hData = shape.getDataHistoForSplittedBin(i)
         hEwk = shape.getEwkHistoForSplittedBin(i)
         # Get normalization factor
         wQCDLabel = shape.getPhaseSpaceBinFileFriendlyTitle(i)
         if self._optionUseInclusiveNorm:
             wQCDLabel = "Inclusive"
         wQCD = 0.0
         if not wQCDLabel in normFactors.keys():
             print ShellStyles.WarningLabel(
             ) + "No normalization factors available for bin '%s' when accessing histogram %s! Ignoring this bin..." % (
                 wQCDLabel, shape.getHistoName())
         else:
             wQCD = normFactors[wQCDLabel]
         # Loop over bins in the shape histogram
         for j in range(1, h.GetNbinsX() + 1):
             myResult = 0.0
             myStatDataUncert = 0.0
             myStatEwkUncert = 0.0
             if abs(h.GetBinContent(j)) > 0.00001:  # Ignore zero bins
                 # Calculate result
                 myResult = h.GetBinContent(j) * wQCD
                 # Calculate abs. stat. uncert. for data and for MC EWK
                 myStatDataUncert = hData.GetBinError(j) * wQCD
                 myStatEwkUncert = hEwk.GetBinError(j) * wQCD
                 #errorPropagation.errorPropagationForProduct(hLeg1.GetBinContent(j), hLeg1Data.GetBinError(j), myEffObject.value(), myEffObject.uncertainty("statData"))
                 # Do not calculate here MC EWK syst.
             myCountObject = extendedCount.ExtendedCount(
                 myResult, [myStatDataUncert, myStatEwkUncert],
                 myUncertaintyLabels)
             self._resultCountObject.add(myCountObject)
             if optionDoNQCDByBinHistograms:
                 self._histogramsList[i].SetBinContent(
                     j, myCountObject.value())
                 self._histogramsList[i].SetBinError(
                     j, myCountObject.statUncertainty())
             self._resultShape.SetBinContent(
                 j,
                 self._resultShape.GetBinContent(j) + myCountObject.value())
             self._resultShape.SetBinError(
                 j,
                 self._resultShape.GetBinError(j) +
                 myCountObject.statUncertainty()**2)  # Sum squared
             # Sum items for purity calculation
             myShapeDataSum[j - 1] += hData.GetBinContent(j) * wQCD
             myShapeDataSumUncert[j - 1] += (hData.GetBinError(j) * wQCD)**2
             myShapeEwkSum[j - 1] += hEwk.GetBinContent(j) * wQCD
             myShapeEwkSumUncert[j - 1] += (hEwk.GetBinError(j) * wQCD)**2
         h.Delete()
         hData.Delete()
         hEwk.Delete()
     # Take square root of uncertainties
     for j in range(1, self._resultShape.GetNbinsX() + 1):
         self._resultShape.SetBinError(
             j, math.sqrt(self._resultShape.GetBinError(j)))
     # Print result
     print "NQCD Integral(%s) = %s " % (
         shape.getHistoName(),
         self._resultCountObject.getResultStringFull("%.1f"))
     # Print purity as function of final shape bins
     if optionPrintPurityByBins:
         print "Purity of shape %s" % shape.getHistoName()
         print "shapeBin purity purityUncert"
     for j in range(1, self._resultShape.GetNbinsX() + 1):
         myPurity = 0.0
         myPurityUncert = 0.0
         if abs(myShapeDataSum[j - 1]) > 0.000001:
             myPurity = 1.0 - myShapeEwkSum[j - 1] / myShapeDataSum[j - 1]
             myPurityUncert = errorPropagation.errorPropagationForDivision(
                 myShapeEwkSum[j - 1],
                 math.sqrt(myShapeEwkSumUncert[j - 1]),
                 myShapeDataSum[j - 1],
                 math.sqrt(myShapeDataSumUncert[j - 1]))
         # Store MC EWK content
         self._resultShapeEWK.SetBinContent(j, myShapeEwkSum[j - 1])
         self._resultShapeEWK.SetBinError(
             j, math.sqrt(myShapeEwkSumUncert[j - 1]))
         self._resultShapePurity.SetBinContent(j, myPurity)
         self._resultShapePurity.SetBinError(j, myPurityUncert)
         # Print purity info of final shape
         if optionPrintPurityByBins:
             myString = ""
             if j < self._resultShape.GetNbinsX():
                 myString = "%d..%d" % (
                     self._resultShape.GetXaxis().GetBinLowEdge(j),
                     self._resultShape.GetXaxis().GetBinUpEdge(j))
             else:
                 myString = ">%d" % (
                     self._resultShape.GetXaxis().GetBinLowEdge(j))
             myString += " %.3f %.3f" % (myPurity, myPurityUncert)
             print myString
Exemplo n.º 3
0
    def _doCalculate2D(self, nSplitBins, shape, normFactors, optionPrintPurityByBins, optionDoNQCDByBinHistograms, myUncertaintyLabels):
        '''
        Calculates the result for 2D histograms
        '''
        # Intialize counters for purity calculation in final shape binning
        myShapeDataSum = []
        myShapeDataSumUncert = []
        myShapeEwkSum = []
        myShapeEwkSumUncert = []
        myList = []
        for k in range(1,self._resultShape.GetNbinsY()+1):
            myList.append(0.0)
        for j in range(1,self._resultShape.GetNbinsX()+1):
            myShapeDataSum.append(myList[:])
            myShapeDataSumUncert.append(myList[:])
            myShapeEwkSum.append(myList[:])
            myShapeEwkSumUncert.append(myList[:])

        # Calculate results separately for each phase-space bin, and then combine them to get inclusive result
        for i in range(0, nSplitBins):
            # Get data-driven QCD, data, and MC EWK shape histogram for the phase space bin
            h     = shape.getDataDrivenQCDHistoForSplittedBin(i)
            hData = shape.getDataHistoForSplittedBin(i)
            hEwk  = shape.getEwkHistoForSplittedBin(i)

            # Get normalization factor
            wQCDLabel = shape.getPhaseSpaceBinFileFriendlyTitle(i)
            if self._optionUseInclusiveNorm:
                wQCDLabel = "Inclusive"
            wQCD = 0.0
            if not wQCDLabel in normFactors.keys():
                msg = "No normalization factors available for bin '%s' when accessing histogram %s! Ignoring this bin..." % (wQCDLabel, shape.getHistoName())
                print ShellStyles.WarningLabel() + msg
            else:
                wQCD = normFactors[wQCDLabel]
            # Loop over bins in the shape histogram
            for j in range(1,h.GetNbinsX()+1):
                for k in range(1,h.GetNbinsY()+1):
                    myResult = 0.0
                    myStatDataUncert = 0.0
                    myStatEwkUncert = 0.0
                    if abs(h.GetBinContent(j,k)) > 0.00001: # Ignore zero bins
                        # Calculate result
                        myResult = h.GetBinContent(j,k) * wQCD
                        # Calculate abs. stat. uncert. for data and for MC EWK
                        myStatDataUncert = hData.GetBinError(j,k) * wQCD
                        myStatEwkUncert = hEwk.GetBinError(j,k) * wQCD
                        #errorPropagation.errorPropagationForProduct(hLeg1.GetBinContent(j), hLeg1Data.GetBinError(j), myEffObject.value(), myEffObject.uncertainty("statData"))
                        # Do not calculate here MC EWK syst.
                    myCountObject = extendedCount.ExtendedCount(myResult, [myStatDataUncert, myStatEwkUncert], myUncertaintyLabels)
                    self._resultCountObject.add(myCountObject)
                    if optionDoNQCDByBinHistograms:
                        self._histogramsList[i].SetBinContent(j, k, myCountObject.value())
                        self._histogramsList[i].SetBinError(j, k, myCountObject.statUncertainty())
                    self._resultShape.SetBinContent(j, k, self._resultShape.GetBinContent(j, k) + myCountObject.value())
                    self._resultShape.SetBinError(j, k, self._resultShape.GetBinError(j, k) + myCountObject.statUncertainty()**2) # Sum squared
                    # Sum items for purity calculation
                    myShapeDataSum[j-1][k-1] += hData.GetBinContent(j,k)*wQCD
                    myShapeDataSumUncert[j-1][k-1] += (hData.GetBinError(j,k)*wQCD)**2
                    myShapeEwkSum[j-1][k-1] += hEwk.GetBinContent(j,k)*wQCD
                    myShapeEwkSumUncert[j-1][k-1] += (hEwk.GetBinError(j,k)*wQCD)**2
            h.Delete()
            hData.Delete()
            hEwk.Delete()
        # Take square root of uncertainties
        for j in range(1,self._resultShape.GetNbinsX()+1):
            for k in range(1,self._resultShape.GetNbinsY()+1):
                self._resultShape.SetBinError(j, k, math.sqrt(self._resultShape.GetBinError(j, k)))

        # Print result
        print "NQCD Integral(%s) = %s "%(shape.getHistoName(), self._resultCountObject.getResultStringFull("%.1f"))

        # Print purity as function of final shape bins
        if optionPrintPurityByBins:
            print "Purity of shape %s"%shape.getHistoName()
            print "shapeBin purity purityUncert"
        for j in range (1,self._resultShape.GetNbinsX()+1):
            for k in range(1,self._resultShape.GetNbinsY()+1):
                myPurity = 0.0
                myPurityUncert = 0.0
                if abs(myShapeDataSum[j-1][k-1]) > 0.000001:
                    myPurity = 1.0 - myShapeEwkSum[j-1][k-1] / myShapeDataSum[j-1][k-1]
                    myPurityUncert = errorPropagation.errorPropagationForDivision(myShapeEwkSum[j-1][k-1], math.sqrt(myShapeEwkSumUncert[j-1][k-1]), myShapeDataSum[j-1][k-1], math.sqrt(myShapeDataSumUncert[j-1][k-1]))
                # Store MC EWK content
                self._resultShapeEWK.SetBinContent(j, k, myShapeEwkSum[j-1][k-1])
                self._resultShapeEWK.SetBinError(j, k, math.sqrt(myShapeEwkSumUncert[j-1][k-1]))
                self._resultShapePurity.SetBinContent(j, k, myPurity)
                self._resultShapePurity.SetBinError(j, k, myPurityUncert)
                # Print purity info of final shape
                if optionPrintPurityByBins:
                    myString = ""
                    if j < self._resultShape.GetNbinsX():
                        myString = "%d..%d, "%(self._resultShape.GetXaxis().GetBinLowEdge(j),self._resultShape.GetXaxis().GetBinUpEdge(j))
                    else:
                        myString = ">%d, "%(self._resultShape.GetXaxis().GetBinLowEdge(j))
                    if k < self._resultShape.GetNbinsY():
                        myString = "%d..%d"%(self._resultShape.GetYaxis().GetBinLowEdge(k),self._resultShape.GetYaxis().GetBinUpEdge(k))
                    else:
                        myString = ">%d"%(self._resultShape.GetYaxis().GetBinLowEdge(k))
                    myString += " %.3f %.3f"%(myPurity, myPurityUncert)
                    print myString
        return