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
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