def getTrees(theConfig, datasets, central=True): import dataInterface #~ theDataInterface = dataInterface.dataInterface(dataVersion=dataVersion) theDataInterface = dataInterface.DataInterface(theConfig.dataSetPath,theConfig.dataVersion) treePathOFOS = "/EMuDileptonTree" treePathEE = "/EEDileptonTree" treePathMM = "/MuMuDileptonTree" treesMCOFOS = ROOT.TList() treesMCEE = ROOT.TList() treesMCMM = ROOT.TList() if central: cut = theConfig.selection.cut + " && abs(eta1) < 1.4 && abs(eta2) < 1.4" else: cut = theConfig.selection.cut + " && 1.6 <= TMath::Max(abs(eta1),abs(eta2)) && !(abs(eta1) > 1.4 && abs(eta1) < 1.6) && !(abs(eta2) > 1.4 && abs(eta2) < 1.6)" for dataset in datasets: scale = 0.0 # dynamic scaling jobs = dataInterface.InfoHolder.theDataSamples[theConfig.dataVersion][dataset] if (len(jobs) > 1): log.logDebug("Scaling and adding more than one job: %s" % (jobs)) for job in jobs: treeMCOFOSraw = theDataInterface.getTreeFromJob(theConfig.flag, theConfig.task, job, treePathOFOS, dataVersion=theConfig.dataVersion, cut=theConfig.selection.cut) treeMCEEraw = theDataInterface.getTreeFromJob(theConfig.flag, theConfig.task, job, treePathEE, dataVersion=theConfig.dataVersion, cut=theConfig.selection.cut) treeMCMMraw = theDataInterface.getTreeFromJob(theConfig.flag, theConfig.task, job, treePathMM, dataVersion=theConfig.dataVersion, cut=theConfig.selection.cut) dynNTotal = theDataInterface.getEventCount(job, theConfig.flag, theConfig.task) dynXsection = theDataInterface.getCrossSection(job) dynScale = dynXsection * theConfig.runRange.lumi / dynNTotal if (dynScale != scale): log.logInfo("dyn scale for %s (%s): n = %d, x = %f => %f" % (job, dataset, dynNTotal, dynXsection, dynScale)) scale = dynScale else: log.logError("No dynamic scale applied. This should never happen!") # convert trees treesMCOFOS.Add(dataInterface.DataInterface.convertDileptonTree(treeMCOFOSraw, weight=scale)) treesMCEE.Add(dataInterface.DataInterface.convertDileptonTree(treeMCEEraw, weight=scale)) treesMCMM.Add(dataInterface.DataInterface.convertDileptonTree(treeMCMMraw, weight=scale)) treeMCOFOStotal = ROOT.TTree.MergeTrees(treesMCOFOS) treeMCEEtotal = ROOT.TTree.MergeTrees(treesMCEE) treeMCMMtotal = ROOT.TTree.MergeTrees(treesMCMM) return (treeMCOFOStotal, treeMCEEtotal, treeMCMMtotal)
def stringJESConversion(string, up=True): JESUncertainty = 0.075 value = "%s" % string if (up): log.logInfo("Scaling up: %s" % JESUncertainty) value = value.replace("ht", "%f * ht" % (1.0 + JESUncertainty)) value = value.replace("met", "%f * met" % (1.0 + JESUncertainty)) value = value.replace("jet1pt", "%f * jet1pt" % (1.0 + JESUncertainty)) value = value.replace("jet2pt", "%f * jet2pt" % (1.0 + JESUncertainty)) value = value.replace("jet3pt", "%f * jet3pt" % (1.0 + JESUncertainty)) value = value.replace("jet4pt", "%f * jet4pt" % (1.0 + JESUncertainty)) else: log.logInfo("Scaling down: %s" % JESUncertainty) value = value.replace("ht", "%f * ht" % (1.0 - JESUncertainty)) value = value.replace("met", "%f * met" % (1.0 - JESUncertainty)) value = value.replace("jet1pt", "%f * jet1pt" % (1.0 - JESUncertainty)) value = value.replace("jet2pt", "%f * jet2pt" % (1.0 - JESUncertainty)) value = value.replace("jet3pt", "%f * jet3pt" % (1.0 - JESUncertainty)) value = value.replace("jet4pt", "%f * jet4pt" % (1.0 - JESUncertainty)) log.logDebug("Converting '%s' into '%s'." % (string, value)) return value
def getSignalTrees(theConfig, signals, useNLL=False): import dataInterface treesMCEM = ROOT.TList() treesMCEE = ROOT.TList() treesMCMM = ROOT.TList() runRanges = theConfig.runRanges cut = theConfig.selection.cut for runRange in runRanges: scale = 0.0 theDataInterface = dataInterface.DataInterface([ runRange, ]) for signal in signals: treeMCEMraw = theDataInterface.getSignalTreeFromJob(signal, "EMu", cut=cut, useNLL=useNLL) treeMCEEraw = theDataInterface.getSignalTreeFromJob(signal, "EE", cut=cut, useNLL=useNLL) treeMCMMraw = theDataInterface.getSignalTreeFromJob(signal, "MuMu", cut=cut, useNLL=useNLL) from helpers import getSignalGenEvents, getSignalXsec dynXsection = getSignalXsec(signal, runRange) dynNTotal = getSignalGenEvents(signal, runRange) dynScale = dynXsection * runRange.lumi / (dynNTotal) if (dynScale != scale): log.logInfo("dyn scale for %s: n = %d, x = %f => %f" % (signal, dynNTotal, dynXsection, dynScale)) scale = dynScale else: log.logError( "No dynamic scale applied. This should never happen!") if not treeMCEMraw == None: treesMCEM.Add( dataInterface.DataInterface.convertDileptonTree( treeMCEMraw, weight=scale)) if not treeMCEEraw == None: treesMCEE.Add( dataInterface.DataInterface.convertDileptonTree( treeMCEEraw, weight=scale)) if not treeMCMMraw == None: treesMCMM.Add( dataInterface.DataInterface.convertDileptonTree( treeMCMMraw, weight=scale)) treeMCEMtotal = ROOT.TTree.MergeTrees(treesMCEM) treeMCEEtotal = ROOT.TTree.MergeTrees(treesMCEE) treeMCMMtotal = ROOT.TTree.MergeTrees(treesMCMM) return (treeMCEMtotal, treeMCEEtotal, treeMCMMtotal)
def getTrees(theConfig, datasets, useNLL=False): import dataInterface treesMCEM = ROOT.TList() treesMCEE = ROOT.TList() treesMCMM = ROOT.TList() runRanges = theConfig.runRanges cut = theConfig.selection.cut for runRange in runRanges: theDataInterface = dataInterface.DataInterface([ runRange, ]) for dataset in datasets: scale = 0.0 # dynamic scaling eventCounts = totalNumberOfGeneratedEvents( locations[runRange.era].dataSetPath) proc = Process(getattr(Backgrounds[runRange.era], dataset), eventCounts) if (len(proc.samples) > 1): log.logDebug("Scaling and adding more than one job: %s" % (proc.samples)) for job, dynNTotal, dynXsection, dynNegWeightFraction in zip( proc.samples, proc.nEvents, proc.xsecs, proc.negWeightFractions): treeMCEMraw = theDataInterface.getTreeFromJob(job, "EMu", cut=cut, useNLL=useNLL) treeMCEEraw = theDataInterface.getTreeFromJob(job, "EE", cut=cut, useNLL=useNLL) treeMCMMraw = theDataInterface.getTreeFromJob(job, "MuMu", cut=cut, useNLL=useNLL) #~ dynScale = dynXsection * theConfig.runRange.lumi / dynNTotal print runRange.lumi dynScale = dynXsection * runRange.lumi / ( dynNTotal * (1 - 2 * dynNegWeightFraction)) if (dynScale != scale): log.logInfo( "dyn scale for %s (%s): n = %d, x = %f => %f" % (job, dataset, dynNTotal, dynXsection, dynScale)) scale = dynScale else: log.logError( "No dynamic scale applied. This should never happen!") # convert trees if not treeMCEMraw == None: treesMCEM.Add( dataInterface.DataInterface.convertDileptonTree( treeMCEMraw, weight=scale)) if not treeMCEEraw == None: treesMCEE.Add( dataInterface.DataInterface.convertDileptonTree( treeMCEEraw, weight=scale)) if not treeMCMMraw == None: treesMCMM.Add( dataInterface.DataInterface.convertDileptonTree( treeMCMMraw, weight=scale)) treeMCEMtotal = ROOT.TTree.MergeTrees(treesMCEM) treeMCEEtotal = ROOT.TTree.MergeTrees(treesMCEE) treeMCMMtotal = ROOT.TTree.MergeTrees(treesMCMM) return (treeMCEMtotal, treeMCEEtotal, treeMCMMtotal)
def getErrorGraphs(self): numErrorGraphs = 0 totalConstantUncertainty = 0 errorGraphs = [] for iError, error in enumerate(self.errors): if (error.size != None): if (error.add): log.logInfo( "Quadractically adding error '%s' with size %f" % (error.name, error.size)) totalConstantUncertainty = (totalConstantUncertainty**2 + error.size**2)**0.5 #~ xCenter = 0.5 * (error.xMin + error.xMax) #~ xWidth = 0.5 * (error.xMax - error.xMin) #~ graph = ROOT.TGraphErrors(1, array("d", [xCenter]), array("d", [1.0]), array("d", [xWidth]), array("d", [error.size])) #~ graph.SetFillColor(error.color) #~ errorGraphsToAdd.Add(graph) else: log.logInfo("Adding error '%s' with size %f" % (error.name, error.size)) xCenter = 0.5 * (error.xMin + error.xMax) xWidth = 0.5 * (error.xMax - error.xMin) graph = ROOT.TGraphErrors(1, array("d", [xCenter]), array("d", [1.0]), array("d", [xWidth]), array("d", [error.size])) graph.SetFillColor(error.color) graph.SetFillStyle(error.fillStyle) errorGraphs.append(graph) elif (error.hasHistograms): log.logInfo("Adding error '%s' given as histograms" % (error.name)) errorsUp = error.errorsUp errorsDown = error.errorsDown xs = [] ys = [] widths = [] upErrors = [] downErrors = [] for (errorUp, errorDown) in zip(errorsUp, errorsDown): if (errorUp.ratio >= 0.0 and errorDown.ratio >= 0.0): xs.append(errorUp.xCenter) ys.append(1.0) widths.append(errorUp.errorX) if (errorUp.ratio > 1.0): if (errorDown.ratio > 1.0): upErrors.append( max(errorUp.ratio - 1.0, errorDown.ratio - 1.0)) downErrors.append(0.0) else: upErrors.append(errorUp.ratio - 1.0) downErrors.append(1.0 - errorDown.ratio) else: if (errorDown.ratio > 1.0): upErrors.append(errorDown.ratio - 1.0) downErrors.append(1.0 - errorUp.ratio) else: upErrors.append(0.0) downErrors.append( max(1.0 - errorUp.ratio, 1.0 - errorDown.ratio)) #~ if (iError + 1 < len(self.errors) and self.errors[iError + 1].add): if (iError - 1 is not -1): #~ print iError #~ if (self.errors[iError + 1].size != None): log.logHighlighted( "Found uncertainty to be added. Will do so, now.") #~ size = self.errors[iError -1].size #~ upErrors = [math.sqrt(prev ** 2 + errorGraphs[numErrorGraphs-1].GetErrorYhigh(index) ** 2 + totalConstantUncertainty**2) for index, prev in enumerate(upErrors)] #~ downErrors = [math.sqrt(prev ** 2 + errorGraphs[numErrorGraphs-1].GetErrorYlow(index) ** 2 + totalConstantUncertainty**2) for index, prev in enumerate(downErrors)] upErrors = [ math.sqrt(prev**2 + errorGraphs[numErrorGraphs - 1].GetErrorYhigh(index)**2 + totalConstantUncertainty**2) for index, prev in enumerate(upErrors) ] downErrors = [ math.sqrt(prev**2 + errorGraphs[numErrorGraphs - 1].GetErrorYlow(index)**2 + totalConstantUncertainty**2) for index, prev in enumerate(downErrors) ] #~ else: #~ log.logError("Uncertainty to be added does not have fixed size. Adding not implemented, yet.") graph = ROOT.TGraphAsymmErrors(len(xs), array("d", xs), array("d", ys), array("d", widths), array("d", widths), array("d", downErrors), array("d", upErrors)) graph.SetFillColor(error.color) graph.SetFillStyle(error.fillStyle) errorGraphs.append(graph) #~ print downErrors #~ print upErrors numErrorGraphs = numErrorGraphs + 1 #~ num = errorGraphs[-1].Merge(errorGraphsToAdd) #~ print num return errorGraphs
def addResult(self, result): if (self.histogram == None): log.logWarning("Adding to empty result!") if (result.histogram == None): log.logWarning("... also adding empty result!") return result if (result.histogram == None): log.logWarning("Adding empty result!") return self if (not self.scaled == result.scaled): log.logError("Cannot add scaled and unscaled results") return None if (self.dataType != result.dataType): log.logError("Cannot add results of different data types (%d, %d)" % (self.dataType, results.dataType)) return None # lumi info if (self.luminosity > 0 and result.luminosity > 0): if (self.dataType == InfoHolder.DataTypes.Data): self.luminosity += result.luminosity # for data else: pass # for MC and Unknown else: log.logWarning("Adding results without complete luminosity information (%f, %f)" % (self.luminosity, result.luminosity)) self.luminosity = -1 # xSection info if (self.xSection > 0 and result.xSection > 0): self.xSection += result.xSection else: if (self.dataType != InfoHolder.DataTypes.Data): log.logWarning("Adding results without complete xSection information (%f, %f)" % (self.xSection, result.xSection)) self.xSection = -1 # xSection info if (self.kFactor > 0 and result.kFactor > 0): if (self.kFactor != result.kFactor): log.logHighlighted("Adding results with different kFactors (%f, %f). Will not be able to track this any more." % (self.kFactor, result.kFactor)) self.kFactor = -1 else: log.logInfo("Adding results without complete kFactor information (%f, %f)" % (self.kFactor, result.kFactor)) self.kFactor = -1 if (not self.scaled): self.histogram.Add(result.histogram) return self if (self.scalingFactor == result.scalingFactor): self.unscaledIntegral += result.unscaledIntegral self.histogram.Add(result.histogram) return self log.logDebug("Combining results: %s, %s" % (str(self), str(result))) # first calculate new error self.currentIntegralError = sqrt(self.integralError() * self.integralError() + result.integralError() * result.integralError()) # then change histogram self.histogram.Add(result.histogram) self.unscaledIntegral += result.unscaledIntegral self.scalingFactor = -1 # finally mark result as scaled and added self.__scaledAndAdded = True log.logDebug("... to: %s" % (str(self))) return self
def getErrorGraphs(self): numErrorGraphs=0 totalConstantUncertainty = 0 errorGraphs = [] for iError, error in enumerate(self.errors): if (error.size != None): if (error.add): log.logInfo("Quadractically adding error '%s' with size %f" % (error.name, error.size)) totalConstantUncertainty = (totalConstantUncertainty**2+error.size**2)**0.5 #~ xCenter = 0.5 * (error.xMin + error.xMax) #~ xWidth = 0.5 * (error.xMax - error.xMin) #~ graph = ROOT.TGraphErrors(1, array("d", [xCenter]), array("d", [1.0]), array("d", [xWidth]), array("d", [error.size])) #~ graph.SetFillColor(error.color) #~ errorGraphsToAdd.Add(graph) else: log.logInfo("Adding error '%s' with size %f" % (error.name, error.size)) xCenter = 0.5 * (error.xMin + error.xMax) xWidth = 0.5 * (error.xMax - error.xMin) graph = ROOT.TGraphErrors(1, array("d", [xCenter]), array("d", [1.0]), array("d", [xWidth]), array("d", [error.size])) graph.SetFillColor(error.color) graph.SetFillStyle(error.fillStyle) errorGraphs.append(graph) elif (error.hasHistograms): log.logInfo("Adding error '%s' given as histograms" % (error.name)) errorsUp = error.errorsUp errorsDown = error.errorsDown xs = [] ys = [] widths = [] upErrors = [] downErrors = [] for (errorUp, errorDown) in zip(errorsUp, errorsDown): if (errorUp.ratio >= 0.0 and errorDown.ratio >= 0.0): xs.append(errorUp.xCenter) ys.append(1.0) widths.append(errorUp.errorX) if (errorUp.ratio > 1.0): if (errorDown.ratio > 1.0): upErrors.append(max(errorUp.ratio - 1.0, errorDown.ratio - 1.0)) downErrors.append(0.0) else: upErrors.append(errorUp.ratio - 1.0) downErrors.append(1.0 - errorDown.ratio) else: if (errorDown.ratio > 1.0): upErrors.append(errorDown.ratio - 1.0) downErrors.append(1.0 - errorUp.ratio) else: upErrors.append(0.0) downErrors.append(max(1.0 - errorUp.ratio, 1.0 - errorDown.ratio)) #~ if (iError + 1 < len(self.errors) and self.errors[iError + 1].add): if (iError -1 is not -1 ): #~ print iError #~ if (self.errors[iError + 1].size != None): log.logHighlighted("Found uncertainty to be added. Will do so, now.") #~ size = self.errors[iError -1].size #~ upErrors = [math.sqrt(prev ** 2 + errorGraphs[numErrorGraphs-1].GetErrorYhigh(index) ** 2 + totalConstantUncertainty**2) for index, prev in enumerate(upErrors)] #~ downErrors = [math.sqrt(prev ** 2 + errorGraphs[numErrorGraphs-1].GetErrorYlow(index) ** 2 + totalConstantUncertainty**2) for index, prev in enumerate(downErrors)] upErrors = [math.sqrt(prev ** 2 + errorGraphs[numErrorGraphs-1].GetErrorYhigh(index) ** 2 + totalConstantUncertainty**2) for index, prev in enumerate(upErrors)] downErrors = [math.sqrt(prev ** 2 + errorGraphs[numErrorGraphs-1].GetErrorYlow(index) ** 2 + totalConstantUncertainty**2) for index, prev in enumerate(downErrors)] #~ else: #~ log.logError("Uncertainty to be added does not have fixed size. Adding not implemented, yet.") graph = ROOT.TGraphAsymmErrors(len(xs), array("d", xs), array("d", ys), array("d", widths), array("d", widths), array("d", downErrors), array("d", upErrors)) graph.SetFillColor(error.color) graph.SetFillStyle(error.fillStyle) errorGraphs.append(graph) #~ print downErrors #~ print upErrors numErrorGraphs = numErrorGraphs+1 #~ num = errorGraphs[-1].Merge(errorGraphsToAdd) #~ print num return errorGraphs