def getTreeFromJob(self, job, dilepton, cut="", useNLL=False): if len(self.runRanges) > 1: log.logError("Should only have one runRange when calling getTreeFromJob") runRange = self.runRanges[0] if useNLL: path = locations[runRange.era].dataSetPathNLL else: path = locations[runRange.era].dataSetPath tree = ROOT.TChain() tree.Add(readTrees(path, dilepton)[job]) cut = cut + runRange.runCut if useNLL: cut = cut + " && vetoHEM == 1" if (cut != ""): log.logDebug("Cutting tree down to: %s" % cut) if tree.GetEntries() > 0: tree = tree.CopyTree(cut) log.logError("Tree size: %d entries" % (tree.GetEntries())) if (tree != None): tree.SetDirectory(0) return tree
def __init__(self, histogram): if (histogram == None): log.logWarning("Creating a result from an empty histogram.") # default configuration self.dataName = "None" self.dataVersion = "None" self.taskName = "None" self.flagName = "None" self.dataType = InfoHolder.DataTypes.Unknown self.is2DHistogram = False self.scaled = False self.histogram = histogram #self.histogram.Sumw2() self.unscaledIntegral = -1 self.scalingFactor = -1 self.luminosity = -1 self.xSection = -1 self.kFactor = -1 self.nEvents = -1 self.__scaledAndAdded = False self.currentIntegralError = -1 self.title = None #log.logDebug("%s" % type(histogram)) self.is2DHistogram = False if (type(histogram) == ROOT.TH2F): log.logDebug("2D histogram found: %s" % type(histogram)) self.is2DHistogram = True
def getSignalTreeFromJob(self, job, dilepton, cut="", useNLL=False): if len(self.runRanges) > 1: log.logError("Should only have one runRange when calling getTreeFromJob") runRange = self.runRanges[0] signalType = job.split("_")[0] append = {} append["2016"] = "_Summer16" append["2017"] = "_Fall17" append["2018"] = "_Autumn18" if useNLL: path = locations[runRange.era]["dataSetPathSignalNLL%s"%signalType] else: path = locations[runRange.era]["dataSetPathSignal%s"%signalType] tree = ROOT.TChain() tree.Add(readTrees(path, dilepton)[job+append[runRange.era]]) if (cut != ""): log.logDebug("Cutting tree down to: %s" % cut) if tree.GetEntries() > 0: tree = tree.CopyTree(cut) log.logError("Tree size: %d entries" % (tree.GetEntries())) if (tree != None): tree.SetDirectory(0) return tree
def isHistogramInFile(self, fileName, path): log.logDebug("Checking path '%s'\n in file %s" % (path, fileName)) file = TFile(fileName, 'READ') path = file.Get(path) return (path != None)
def runSoftsusy(parameters): """ parameters: dict holding all information needed to run SOSTUSY for one point result: dict of resulting mass spectrum """ from subprocess import Popen, PIPE #softpoint.x sugra <m0> <m12> <a0> <tanb> <mgut> <sgnMu> template = "%(path)s %(mode)s %(m0)s %(m12)s %(A0)s %(tanb)s %(mgut)s %(sgnMu)s" log.logDebug(template%parameters) proc = Popen(template%parameters, shell=True, stdout=PIPE, stderr=PIPE) slha = proc.communicate()[0] return slha
def getHistogramFromFile(self, fileName, histoPath): log.logDebug("Getting histogram '%s'\n from file %s" % (histoPath, fileName)) file = TFile(fileName, 'READ') histogram = file.Get(histoPath) if (histogram == None): log.logError("Could not get histogram '%s'\n from file %s" % (histoPath, fileName)) file.Close() return None else: histogram.SetDirectory(0) histogram.Sumw2() file.Close() return histogram
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 convertDileptonTree(tree, nMax= -1, weight=1.0, selection="", weightString=""): # TODO: make selection more efficient log.logDebug("Converting DileptonTree") data = MyDileptonTreeFormat() newTree = ROOT.TTree("treeInvM", "Dilepton Tree") newTree.SetDirectory(0) newTree.Branch("inv", ROOT.AddressOf(data, "inv"), "inv/D") newTree.Branch("chargeProduct", ROOT.AddressOf(data, "chargeProduct"), "chargeProduct/D") newTree.Branch("nJets", ROOT.AddressOf(data, "nJets"), "nJets/I") newTree.Branch("ht", ROOT.AddressOf(data, "ht"), "ht/D") newTree.Branch("met", ROOT.AddressOf(data, "met"), "met/D") newTree.Branch("MT2", ROOT.AddressOf(data, "MT2"), "MT2/D") newTree.Branch("pt1", ROOT.AddressOf(data, "pt1"), "pt1/D") newTree.Branch("pt2", ROOT.AddressOf(data, "pt2"), "pt2/D") newTree.Branch("weight", ROOT.AddressOf(data, "weight"), "weight/D") # only part of tree? iMax = tree.GetEntries() if (nMax != -1): iMax = min(nMax, iMax) # Fill tree for i in xrange(iMax): if (tree.GetEntry(i) > 0): ### depending on the sample we have to switch between p4.M() and mll #~ data.inv = tree.p4.M() data.inv = tree.mll data.chargeProduct = tree.chargeProduct data.nJets = tree.nJets data.ht = tree.ht data.met = tree.met data.MT2 = tree.MT2 data.pt1 = tree.pt1 data.pt2 = tree.pt2 if (weightString != ""): eventWeight = eval(weightString) data.weight = eventWeight else: data.weight = weight newTree.Fill() #return newTree return newTree.CopyTree(selection)
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 parseSLHA(slha, pdgIds=[24]): """ parse SUSY Les Houches Accord (SLHA) formated strings (e.g. SOFTSUSY output) """ from re import match result = {} massBlock = "" block = None for line in slha.splitlines(): blockRe = match("Block ([a-zA-Z]+).*", line) if not blockRe == None: block = blockRe.group(1) if block == "MASS": for pdgId in pdgIds: pdgIdRe = match("\s*%s\s*([0-9.e\+-]+)"%pdgId, line) if not pdgIdRe == None: result[pdgId] = float(pdgIdRe.group(1)) for pdgId in pdgIds: if not pdgId in result: log.logError("could not find %s"%pdgId) log.logDebug(slha) return result
def getTreeFromDataset(self, dataset, dilepton, cut="", useNLL=False): tree = ROOT.TChain() baseCut = cut for runRange in self.runRanges: if useNLL: path = locations[runRange.era].dataSetPathNLL else: path = locations[runRange.era].dataSetPath log.logDebug("Adding %s tree from %s"%(dataset, path)) ROOT.TH1.AddDirectory(False) tmpTree = readTrees(path, dilepton)[dataset] ROOT.TH1.AddDirectory(True) tree.Add(tmpTree) runCuts = [] runCut = "" for runRange in self.runRanges: runCuts.append(runRange.runCut[3:]) if useNLL: runCuts.append("vetoHEM == 1") runCut = "&& (%s)"%(" || ".join(runCuts)) cut = cut + runCut print tree.GetEntries() if (cut != ""): log.logDebug("Cutting tree down to: %s" % cut) #tree = tree.CopyTree(cut, "", 1000) tree = tree.CopyTree(cut) #log.logError("Tree size: %d entries" % (tree.GetEntries())) if (tree != None): tree.SetDirectory(0) else: log.logError("Tree invalid") return tree
def provideNCanvas(n=2, title="Same Sign Dilepton SUSY analysis"): if (n < 1): log.logError("'%d' is not a valid number of pads!") return None if (n == 1): [c1, pad1, pad2] = provideDoubleCanvas() return [c1, [pad1]] if (n == 2): [c1, pad1, pad2] = provideDoubleCanvas() return [c1, [pad1, pad2]] if (n == 3): [c1, pad1, pad2, pad3, pad4] = provideQuadCanvas() return [c1, [pad1, pad2, pad3]] if (n == 4): [c1, pad1, pad2, pad3, pad4] = provideQuadCanvas() return [c1, [pad1, pad2, pad3, pad4]] # window settings theCanvasSizeX = 1520 theCanvasSizeY = 920 theScreenSizeX = 1680 theScreenSizeY = 1050 # canvas posX = int(theScreenSizeX * 0.04) posY = int(theScreenSizeY * 0.03) #posX = (theScreenSizeX - theCanvasSizeX) / 2 #posY = (theScreenSizeY - theCanvasSizeY) / 2 c1 = TCanvas('c1', title, posX, posY, theCanvasSizeX, theCanvasSizeY) i = int(math.ceil(-0.5 + 0.5 * math.sqrt(4.0 * n + 1.0))) nRows = i nColumns = i + 1 log.logDebug("no. of columns: %d" % nColumns) log.logDebug("no. of rows: %d" % nRows) c1.Divide(nColumns, nRows, 0.0001, 0.0001) pads = [] iPad = 1 for iRow in range(0, nRows): for iColumn in range(0, nColumns): if (iPad <= n): c1.cd(iPad) pad = TPad('pad%d' % iPad, 'Pad for %dth histogram' % iPad, 0.03, 0.03, 0.97, 0.97, 0) pad.Draw() pads.extend([pad]) iPad += 1 log.logDebug("Pads: %s" % pads) return [c1, pads]
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 createLatexTable(fileName, content, format={}): templateTable = """ \\documentclass[12pt,twoside,a4paper]{article} \\newcommand{\\MET}{\\ensuremath{\\displaystyle{\\not} E_T~}} \\newcommand{\\HT}{\\ensuremath{H_T~}} \\begin{document} \\begin{table} %% \\tiny \\small \\begin{tabular}{%(cellformat)s} \\hline %(header)s %(content)s \\end{tabular} %(caption)s \\end{table} \\end{document} """ tabMap = { 'cellformat': "c", 'header': "", 'content': "test", 'caption': "" } tabContent = None nColumns = 1 noLineBreak = False for row in content: log.logDebug("row: %s" % row) rowContent = None hline = False for column in row: cellContent = str(column) if (cellContent == "X-HLINE"): hline = True # format floats as specified if (format.has_key('floatFormat') and isinstance(column, float)): cellContent = format['floatFormat'] % column if (rowContent == None): rowContent = cellContent else: rowContent += " & " + cellContent if (tabContent == None): tabContent = rowContent else: if (not noLineBreak): tabContent += "\\\\" if (hline): tabContent += "\\hline\n " noLineBreak = True else: tabContent += "\n " + rowContent noLineBreak = False if (len(row) > nColumns): nColumns = len(row) log.logDebug("tabContent: %s" % tabContent) #tabContent = tabContent.replace("_", "\\_") tabMap.update({'content': tabContent}) if (format.has_key('cellformat')): tabMap.update({'cellformat': format['cellformat']}) else: cellformat = "" for i in range(0, nColumns): cellformat += "c" tabMap.update({'cellformat': cellformat}) if (format.has_key('header')): header = None for string in format['header']: if (header == None): header = "\\textbf{" + string + "}" else: header = header + " & " + "\\textbf{" + string + "}" tabMap.update({'header': header + "\\\\\\hline"}) if (format.has_key('caption')): tabMap.update({'caption': "\\caption{" + format['caption'] + "}"}) if (format.has_key("fontsize")): templateTable = templateTable.replace("\\small", "\\%s" % format['fontsize']) file = open(fileName, 'w') file.write(templateTable % tabMap) file.close()
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 logMemoryContent(self): directory = ROOT.gDirectory list = directory.GetList() keyNames = [key.GetName() for key in list] log.logDebug("Memory content:%s" % keyNames)