示例#1
0
    def __init__(
            self,
            dataPath,
            ewkPath,
            dsetMgr,
            luminosity,
            moduleInfoString,
            normFactors,
            #dataDrivenFakeTaus=False,
            #shapeOnly=False,
            #displayPurityBreakdown=False,
            #optionUseInclusiveNorm=False,
            optionCalculateQCDNormalizationSyst=True,
            normDataSrc=None,
            normEWKSrc=None,
            optionUseInclusiveNorm=False):
        self._shapePlots = []
        self._shapePlotLabels = []
        self._QCDNormalizationSystPlots = []
        self._QCDNormalizationSystPlotLabels = []
        self._moduleInfoString = moduleInfoString

        self._useInclusiveNorm = optionUseInclusiveNorm
        if len(normFactors.keys()) == 1 and normFactors.keys(
        )[0] == "Inclusive":
            self._useInclusiveNorm = True

        print ShellStyles.HighlightStyle(
        ) + "...Obtaining final shape" + ShellStyles.NormalStyle()
        # Determine list of plots to consider
        myObjects = dsetMgr.getDataset("Data").getDirectoryContent(dataPath)
        # Loop over plots to consider
        i = 0
        for plotName in myObjects:
            i += 1
            print ShellStyles.HighlightStyle(
            ) + "...Obtaining ctrl plot %d/%d: %s%s" % (
                i, len(myObjects), plotName, ShellStyles.NormalStyle())
            # Check that histograms exist
            mySkipStatus = self._sanityChecks(dsetMgr, dataPath,
                                              plotName) and self._sanityChecks(
                                                  dsetMgr, ewkPath, plotName)
            if not mySkipStatus:
                continue
            # Obtain shape plots (the returned object is not owned)

#	    print "DEBUG: ewkPath: ", ewkPath

            myShapeHisto = self._obtainShapeHistograms(i, dataPath, ewkPath,
                                                       dsetMgr, plotName,
                                                       luminosity, normFactors)
            # Obtain plots for systematics coming from met shape difference for control plots
            if optionCalculateQCDNormalizationSyst:
                if isinstance(myShapeHisto, ROOT.TH2):
                    print ShellStyles.WarningLabel(
                    ) + "Skipping met shape uncertainty because histogram has more than 1 dimensions!"
                else:
                    self._obtainQCDNormalizationSystHistograms(
                        myShapeHisto, dsetMgr, plotName, luminosity,
                        normDataSrc, normEWKSrc)
    def _sanityChecks(self, dsetMgr, dirName, plotName):
        '''
        Check existence of histograms
        '''
        # Definitions
        myStatus      = True
        myFoundStatus = True
        
        # For-loop: All EWK datasets
        for d in dsetMgr.getDataset("EWK").datasets:
            if not d.hasRootHisto("%s/%s" % (dirName,plotName) ):
                myFoundStatus = False

        # If something is wrong
        if not myFoundStatus:
            myStatus = False
            msg = "Skipping '%s', because it does not exist for all EWK datasets (you probably forgot to set histo level to Vital when producing the multicrab)!" % (plotName)
            Print(ShellStyles.WarningLabel() + msg + ShellStyles.NormalStyle(), True)
        else:
            (myRootObject, myRootObjectName) = dsetMgr.getDataset("EWK").getFirstRootHisto("%s/%s" % (dirName,plotName) )
            if isinstance(myRootObject, ROOT.TH2):
                msg ="Skipping '%s', because it is not a TH1 object" % (plotName)
                Print(ShellStyles.WarningLabel() + msg + ShellStyles.NormalStyle(), True)
                myStatus = False
            myRootObject.Delete()
        return myStatus
 def check(a, b):
     if abs(a - b) < 0.00001:
         return TestPassedStyle() + "PASSED" + ShellStyles.NormalStyle()
     else:
         print ErrorStyle() + "FAILED (%f != %f)" % (
             a, b) + ShellStyles.NormalStyle()
         raise Exception("Error: validation test failed!")
    def selectLatest(self, dirs):
        if len(dirs) == 0:
            return ""
        if len(dirs) > 1:
            self.Print(
                "More than 1 path found! Will take the most recent one:")
            latest = dirs[0]
            for dir in dirs:
                if os.path.getmtime(dir) > os.path.getmtime(latest):
                    latest = dir

            # Print all paths found and highlight the latest one
            for d in dirs:
                if d == latest:
                    #self.Print(ShellStyles.NoteStyle() + latest + ShellStyles.NormalStyle(), False)
                    self.Print(
                        ShellStyles.SuccessStyle() + latest +
                        ShellStyles.NormalStyle(), False)
                else:
                    self.Print(d, False)
            return latest
        else:
            self.Verbose(
                ShellStyles.SuccessStyle() + "Selecting dir %s" % (dirs[0]) +
                ShellStyles.NormalStyle(), False)
            return dirs[0]
    def __init__(self,
                 binLabels,
                 resultDirName,
                 moduleInfoString,
                 verbose=False):
        self._verbose = verbose
        self._templates = {}
        self._binLabels = binLabels
        self._sources = {}
        self._commentLines = []
        self._NEvtsCR1 = {}
        self._NEvtsCR1_Error = {}
        self._NEvtsCR2 = {}
        self._NEvtsCR2_Error = {}
        self._NEvtsCR3 = {}
        self._NEvtsCR3_Error = {}
        self._NEvtsCR4 = {}
        self._NEvtsCR4_Error = {}
        self._TF = {}  # Transfer Factor (TF)
        self._TF_Error = {}
        self._TF_Up = {}
        self._TF_Down = {}
        self._dqmKeys = OrderedDict()
        self._myPath = os.path.join(resultDirName, "normalisationPlots")
        self._BinLabelMap = {}
        self._FakeBNormalization = {}  # for the time being same as TF
        self._FakeBNormalizationError = {
        }  # for the time being same as TF_Error
        self._FakeBNormalizationUp = {}  # for the time being same as TF_Up
        self._FakeBNormalizationDown = {}  # for the time being same as TF_Down
        if not isinstance(binLabels, list):
            raise Exception("Error: binLabels needs to be a list of strings")
        self.Verbose("__init__")

        # No optimisation mode
        if moduleInfoString == "":
            moduleInfoString = "Default"

        if not os.path.exists(self._myPath):
            self.Print("Creating new directory %s" % (self._myPath), True)
            os.mkdir(self._myPath)
        self._plotDirName = os.path.join(resultDirName, "normalisationPlots",
                                         moduleInfoString)

        # If already exists, Delete an entire directory tree
        if os.path.exists(self._plotDirName):
            msg = "Removing directory tree %s" % (self._plotDirName)
            self.Verbose(
                ShellStyles.NoteStyle() + msg + ShellStyles.NormalStyle(),
                True)
            shutil.rmtree(self._plotDirName)
        msg = "Creating directory %s" % (self._plotDirName)
        self.Verbose(
            ShellStyles.SuccessStyle() + msg + ShellStyles.NormalStyle(),
            False)
        os.mkdir(self._plotDirName)
        return
示例#6
0
    def __init__(self, dataPath, ewkPath, dsetMgr, luminosity, moduleInfoString, normFactors,
                 optionDoFakeBNormalisationSyst=True, normDataSrc=None, normEWKSrc=None,
                 optionUseInclusiveNorm=False, keyList=[], verbose=False):
        self._verbose = verbose
        self._shapePlots = []
        self._shapePlotLabels = []
        self._QCDNormalizationSystPlots = []
        self._QCDNormalizationSystPlotLabels = []
        self._moduleInfoString = moduleInfoString
        self._useInclusiveNorm = optionUseInclusiveNorm
        if len(normFactors.keys()) == 1 and normFactors.keys()[0] == "Inclusive":
            self._useInclusiveNorm = True
        self._histoPathsData= self._GetHistoPaths(dsetMgr, "Data", dataPath, keyList)
        if ewkPath == dataPath:
            self._histoPathsEWK = self._histoPathsData
        else:
            self._histoPathsEWK  = self._GetHistoPaths(dsetMgr, "EWK" , ewkPath , keyList)
        
        # Sanity check
        if len(self._histoPathsEWK) != len(self._histoPathsData):
            msg = "List of histograms for EWK does not match in size that of Data"
            raise Exception(ShellStyles.ErrorLabel() + msg + ShellStyles.NormalStyle())
            
        # For-Loop: All plots to consider
        for i, plotName in enumerate(self._histoPathsData, 1):

            # Inform user of progress
            msg = "{:<9} {:>3} {:<1} {:<3} {:<80}".format("Histogram", "%i" % i, "/", "%s:" % (len(self._histoPathsData)), os.path.join(dataPath, plotName) )
            self.PrintFlushed(ShellStyles.SuccessStyle() + msg + ShellStyles.NormalStyle(), False)

            if "JetEtaPhi_AfterAllSelections" in plotName:
                continue 

            # Ensure that histograms exist && pass other sanity checks
            dataOk = self._sanityChecks(dsetMgr, dataPath, plotName) 
            ewkOk  = self._sanityChecks(dsetMgr, ewkPath , plotName)

            if dataOk*ewkOk == False:
                self.Print(ShellStyles.ErrorStyle() + msg + ShellStyles.NormalStyle(), i==1)
                continue
            
            self.Verbose("Obtaining shape plots (the returned object is not owned)", True)
            myShapeHisto = self._obtainShapeHistograms(i, dataPath, ewkPath, dsetMgr, plotName, luminosity, normFactors)

            # Obtain plots for systematics coming from invariant mass shape difference
            if optionDoFakeBNormalisationSyst:
                if isinstance(myShapeHisto, ROOT.TH2):
                    msg = "Skipping invariant mass shape uncertainty because histogram has more than 1 dimensions!"
                    self.Print(ShellStyles.WarningLabel() + msg, True)
                else:
                    self._obtainQCDNormalizationSystHistograms(myShapeHisto, dsetMgr, plotName, luminosity, normDataSrc, normEWKSrc) #iro: fixme (missing plots)
            
        msg = "Obtaining final shape from data path %s" % (ShellStyles.NoteStyle() + dataPath + ShellStyles.NormalStyle())
        self.Verbose(msg, True)
        return
def getTransferFactorsSrcFilename(dirName, fileName):
    src = os.path.join(dirName, fileName)
    if not os.path.exists(src):
        msg = "Normalisation factors ('%s') not found!\nRun script \"./getABCD_TF.py\" to auto-generate the transfer factors (TFs) file." % src
        raise Exception(ShellStyles.ErrorStyle() + msg +
                        ShellStyles.NormalStyle())
    else:
        Print(
            "Importing transfer factors (TFs) from file %s" %
            (ShellStyles.NoteStyle() + os.path.basename(src) +
             ShellStyles.NormalStyle()), True)
    return src
    def getDataDrivenQCDHistoForSplittedBin(self, binIndex):
        '''
        Return the sum of data-ewk in a given phase space split bin
        
        at bin-index 0 you have the inclusive histogram!
        '''
        if binIndex >= len(self._dataList):
            # FIXME: New addition to fix "optionUseInclusiveNorm" functionality (24-Mar-2018). Should not affect binned result!
            if self._optionUseInclusiveNorm:  #new
                h = aux.Clone(self._dataList[0])  #new
                newName = h.GetName() + "_DataDriven"  #new
                h.SetName(newName)  #new
                return h  #new
            msg = "Requested bin index %d out of range (0-%d)!" % (
                binIndex, len(self._dataList))
            raise Exception(ShellStyles.ErrorStyle() + msg,
                            ShellStyles.NormalStyle())

        # Clone the Data histos
        h = aux.Clone(self._dataList[binIndex])
        newName = h.GetName() + "_DataDriven"
        h.SetName(newName)
        self.Verbose(
            "Cloned histo %s from histo %s" %
            (h.GetName(), self._dataList[0].GetName()), True)

        # Subtract the EWK histos
        self.Verbose(
            "Subtracting histo %s from histo %s (bin=%i)" %
            (self._ewkList[binIndex].GetName(), h.GetName(), binIndex), False)
        h.Add(self._ewkList[binIndex], -1.0)
        return h
示例#9
0
    def __init__(self, opts, basedir):
        self._opts = opts
        self._basedir = basedir
        self._allRetrieved = False
        self._limitCalculated = False
        self._output = ""
        self._findJobDir(basedir)
        if self._jobDir == None:
            if self._opts.printonly:
                msg = "Need to create and submit jobs first! Skipping ..."
                Print(ShellStyles.ErrorLabel() + msg, True)
            else:
                msg = "Creating and submitting " + basedir
                Verbose(msg, True)
                self._createAndSubmit()
        else:
            msg = "Check if limits have already been calculated ..."
            Verbose(msg, True)

            lumiPath = "%s/%s/limits.json" % (self._basedir, self._jobDir)
            if os.path.exists(lumiPath):
                msg = "File \"%s\" already exists!\n\tThe limit has already been calculated.\n\tSkipping ..." % (
                    lumiPath)
                Print(
                    ShellStyles.NoteStyle() + msg + ShellStyles.NormalStyle(),
                    True)
                self._limitCalculated = True
            else:
                msg = "Creating and submitting " + basedir
                Verbose(msg, True)
                self._createAndSubmit()
                #if not self._opts.printonly and not self._opts.lhcTypeAsymptotic:
                #    self._getOutput()
        return
示例#10
0
def main(opts):

    # Apply TDR style
    style = tdrstyle.TDRStyle()
    ROOT.gErrorIgnoreLevel = ROOT.kFatal  # [Options: Print, kInfo, kWarning, kError, kBreak, kSysError, kFatal]
    ROOT.gROOT.SetBatch()
    ROOT.gStyle.SetOptStat(0)
    ROOT.gStyle.SetOptTitle(0)
    ROOT.gStyle.SetNdivisions(5, "X")

    # Find GoF directories (generated by GoF.sh script)
    myDirs = []
    for d in os.listdir('.'):
        if not os.path.isdir(d):
            continue
        if "GoF_" in d:
            myDirs.append(d)

    if len(myDirs) < 1:
        raise Exception(
            "No goodness-of-fit directories found. Did your run the GoF.sh script to create them?"
        )
    else:
        Verbose(
            "Found %d GoF directories: %s" % (len(myDirs), ", ".join(myDirs)),
            True)

    # For-loop: All GoF directories
    myAlgos = []
    allowedAlgos = ["saturated", "KS",
                    "AD"]  # KS = Kolmogorov-Smirnov, AD = Anderson-Darling
    for d in myDirs:
        algo = d.split("_")[-1]
        if algo not in allowedAlgos:
            raise Exception(
                "The algorithm \"%s\" is invalid. Expected one of the following: %s"
                % (opts.algorithm, ", ".join(allowedAlgos)))
        else:
            myAlgos.append(algo)

    # For-loop: All GoF algorithms ran
    Print(
        "Found %d GoF algorithm results: %s" %
        (len(myDirs), ", ".join(myAlgos)), True)
    for i, algo in enumerate(myAlgos, 1):

        # Definitions
        opts.algorithm = algo
        opts.inputDir = "%s/GoF_%s" % (os.getcwd(), algo)
        opts.inputfile = "GoF_%s/higgsCombinetoys*.GoodnessOfFit.mH%s.*.root" % (
            algo, opts.mass)
        opts.outputfile = "GoF_%s/GoF_%s_mH%s.root" % (algo, algo, opts.mass)
        doPlots(i, opts)

    Verbose(
        "All plots saved under directory %s" %
        (ShellStyles.NoteStyle() + aux.convertToURL(opts.saveDir, opts.url) +
         ShellStyles.NormalStyle()), True)

    return
示例#11
0
def GetBinText(bin):
    #if bin == "Inclusive":
    #    return "combined"
    #else:
    #    return "bin-" + str(bin)
    if bin == "0":
        return "p_{T} < 80 GeV/c, |#eta| < 0.8"
    elif bin == "1":
        return "p_{T} = 80-200 GeV/c, |#eta| < 0.8"
    elif bin == "2":
        return "p_{T} > 200 GeV/c, |#eta| < 0.8"
    elif bin == "3":
        return "p_{T} < 80 GeV/c, |#eta| = 0.8-1.6"
    elif bin == "4":
        return "p_{T} = 80-200 GeV/c, |#eta| = 0.8-1.6"
    elif bin == "5":
        return "p_{T} > 200 GeV/c, |#eta| = 0.8-1.6"
    elif bin == "6":
        return "p_{T} < 80 GeV/c, |#eta| > 1.6"
    elif bin == "7":
        return "p_{T} = 80-200 GeV/c, |#eta| > 1.6"
    elif bin == "8":
        return "p_{T} > 200 GeV/c, |#eta| > 1.6"
    elif bin == "Inclusive":
        return "combined"
    else:
        raise Exception(ShellStyles.ErrorStyle() + "Unexpected bin %s" %
                        (bin) + ShellStyles.NormalStyle())
示例#12
0
 def save(self,dirname):
     myFilename = dirname+"/signalAreaEvaluation.txt"
     myFile = open(myFilename, "w")
     myFile.write(self._output)
     myFile.close()
     print ShellStyles.HighlightStyle()+"Signal area evaluation written to: "+ShellStyles.NormalStyle()+myFilename
     self._output = ""
def getNormFactorFileList(dirName, fileBaseName):
    scriptList = []

    # For-loop: All items (files/dir) in directory
    for item in os.listdir(dirName):
        fullPath = os.path.join(dirName, item)

        # Skip directories
        if os.path.isdir(fullPath):
            continue

        # Find files matching the script "Base" name (without moduleInfoStrings)
        if item.startswith((fileBaseName).replace("%s.py", "")):
            if item.endswith(".py"):
                scriptList.append(item)

    if len(scriptList) < 1:
        msg = "ERROR! Found no normalization info files under dir %s. Did you generate them?" % dirName
        raise Exception(ShellStyles.ErrorStyle() + msg +
                        ShellStyles.NormalStyle())
    else:
        msg = "Found %s norm-factor file(s):\n\t%s" % (
            len(scriptList), "\n\t".join(
                os.path.join([os.path.join(dirName, s) for s in scriptList])))
        Verbose(ShellStyles.NoteLabel() + msg, True)
    return scriptList
    def __init__(self,
                 dsetMgr,
                 dsetLabelData,
                 dsetLabelEwk,
                 histoName,
                 dataPath,
                 ewkPath,
                 luminosity,
                 optionUseInclusiveNorm,
                 verbose=False):
        self._verbose = verbose
        self._uniqueN = 0
        self._splittedHistoReader = splittedHistoReader.SplittedHistoReader(
            dsetMgr, dsetLabelData)
        self._histoName = histoName
        self._optionUseInclusiveNorm = optionUseInclusiveNorm
        dataFullName = os.path.join(dataPath, histoName)
        ewkFullName = os.path.join(ewkPath, histoName)

        if (self._optionUseInclusiveNorm):
            msg = "Will create \"Inclusive\"-histogram results"
            self.Verbose(
                ShellStyles.NoteStyle() + msg + ShellStyles.NormalStyle(),
                False)
            self._dataList = list(
                self._getInclusiveHistogramsFromSingleSource(
                    dsetMgr, dsetLabelData, dataFullName,
                    luminosity))  # was called by default
            self._ewkList = list(
                self._getInclusiveHistogramsFromSingleSource(
                    dsetMgr, dsetLabelEwk, ewkFullName,
                    luminosity))  # was called by default
        else:
            msg = "Will create \"Splitted\"-histogram results"
            self.Verbose(
                ShellStyles.NoteStyle() + msg + ShellStyles.NormalStyle(),
                False)
            self._dataList = list(
                self._splittedHistoReader.getSplittedBinHistograms(
                    dsetMgr, dsetLabelData, dataFullName,
                    luminosity))  #FIXME: Does this work for Inclusive?
            self._ewkList = list(
                self._splittedHistoReader.getSplittedBinHistograms(
                    dsetMgr, dsetLabelEwk, ewkFullName,
                    luminosity))  #FIXME: Does this work for Inclusive?
        return
示例#15
0
 def _getAnalysisType(self, analysis):
     myAnalyses = ["HToTauNu", "HToTB"]
     if analysis not in myAnalyses:
         msg = "Unsupported analysis \"%s\". Please select one of the following: %s" % (analysis, ", ".join(myAnalyses))
         raise Exception(ShellStyles.ErrorStyle() + msg + ShellStyles.NormalStyle() )
     else:
         self.Print("Analysis type set to %s" % (sh_Note + analysis + sh_Normal), True)
         return analysis
示例#16
0
def IsTH1(h, raiseExcept=False):
    if not isinstance(h, ROOT.TH1):
        msg = "Expected object of type ROOT.TH1, got \"%s\" instead" % (type(h))
        if raiseExcept:
            raise Exception(ShellStyles.ErrorStyle() + msg + ShellStyles.NormalStyle())
        return False
    else:
        return True
    def writeModuleToRootFile(self, rootfile):

        # Create module directory
        rootfile.cd("/")
        myModuleDir = rootfile.mkdir(self._moduleName)
        # Save shape information
        for h in self._shapes:
            h.SetDirectory(myModuleDir)
        # Save data-driven control plots
        myDDPlotsDirName = "ForDataDrivenCtrlPlots"
        myDDPlotsDir = myModuleDir.mkdir(myDDPlotsDirName)
        for h in self._dataDrivenControlPlots:
            h.SetDirectory(myDDPlotsDir)

        # Save counter histogram
        myCounterDir = myModuleDir.mkdir("counters")
        myWeightedCounterDir = myCounterDir.mkdir("weighted")
        self._hCounters = ROOT.TH1F("counter", "counter", len(self._counters),
                                    0, len(self._counters))
        i = 1
        for key in self._counters.keys():
            self._hCounters.GetXaxis().SetBinLabel(i, key)
            i += 1
            self._hCounters.SetBinContent(i, self._counters[key])
            self._hCounters.SetBinError(i, self._counterUncertainties[key])
        self._hCounters.SetDirectory(myWeightedCounterDir)

        # Save splittedBinInfo
        hType = str(type(self._hSplittedBinInfo)).lower()
        if "none" not in hType:
            self._hSplittedBinInfo.SetDirectory(myModuleDir)
        else:
            msg = "WARNING! Unexpected problem with splitted bin info histogram. Type is %s" % (
                hType)
            self.Print(
                ShellStyles.ErrorStyle() + msg + ShellStyles.NormalStyle(),
                True)

        # Save parameter set, code version and data version
        #myModuleDir.Add(self._psetInfo)

        # Create config info for the module
        myConfigInfoDir = myModuleDir.mkdir("configInfo")
        self._hConfigInfo = ROOT.TH1F(
            "configinfo", "configinfo", 2, 0, 2
        )  # Have to store the histogram to keep it alive for writing        self._hConfigInfo.GetXaxis().SetBinLabel(1,"control")
        self._hConfigInfo.GetXaxis().SetBinLabel(1, "control")
        self._hConfigInfo.SetBinContent(1, 1)
        #self._hConfigInfo.GetXaxis().SetBinLabel(2,"energy")
        #self._hConfigInfo.SetBinContent(2, self._energy)
        self._hConfigInfo.GetXaxis().SetBinLabel(2, "luminosity")
        self._hConfigInfo.SetBinContent(2, self._luminosity)
        self._hConfigInfo.SetDirectory(myConfigInfoDir)
        myConfigInfoDir.Add(self._dataVersion)
        #myConfigInfoDir.Add(self._codeVersion)
        #.SetDirectory(rootfile)
        #self._codeVersion.SetDirectory(rootfile)
        return
示例#18
0
    def _GetHistoPaths(self, dsetMgr, dataset, folderPath, keyList):
        '''
        Determine list of histograms to consider (full paths)
        The keyList contains strings that if ALL 2are contained in 
        a histogram name the histogram will be added to the list of
        objects to be returned.
        '''
        # Get all objects inside the ROOT file under specific directory 
        msg = "Obtaining all ROOT file contents for dataset %s from folder %s (these must be filled in the Verification Region (VR))" % (dataset, ShellStyles.NoteStyle() + folderPath + ShellStyles.NormalStyle())
        self.Verbose(msg, True)
        allObjects  = dsetMgr.getDataset(dataset).getDirectoryContent(folderPath)
        keepObjects = []
        skipObjects = []

        # Remove anything which does not contain any string from the keyList
        for o in allObjects:
            if all(k in o for k in keyList):
                keepObjects.append(o)
                #print o
            elif any(k in o for k in keyList):
                pass
            else:
                skipObjects.append(o)

        # Count histograms in lists
        nAll  = len(allObjects)
        nKeep = len(keepObjects)
        nSkip = len(skipObjects)

        if nKeep == 0:
            msg = "Did not find any compatible object under dir %s. Check the \"keyList\" provided" % (folderPath)
            raise Exception(ShellStyles.ErrorLabel() + msg + ShellStyles.NormalStyle())

        # Now remove anything which does not contain any string from the keyList
        msg = "Skipping %i histograms for dataset %s. Did not match all keys %s" % (nSkip, dataset, ", ".join(keyList) )
        self.Verbose(ShellStyles.NoteStyle() + msg + ShellStyles.NormalStyle(), True)
        for hName in skipObjects:
            self.Verbose(os.path.join(folderPath, hName), False)

        # Now remove anything which does not contain any string from the keyList
        msg = "Found %i histograms for dataset %s. Matched all keys %s" % (nKeep, dataset, ", ".join(keyList) )
        self.Verbose(ShellStyles.NoteStyle() + msg + ShellStyles.NormalStyle(), True)
        for hName in keepObjects:
            self.Verbose(os.path.join(folderPath, hName), False)
        return keepObjects
示例#19
0
 def _getAnalysisType(self, analysis):
     myAnalyses = ["HToTauNu", "HToTB", "HToHW", "HToHW_background"]
     if analysis not in myAnalyses:
         msg = "Unsupported analysis \"%s\". Please select one of the following: %s" % (
             analysis, ", ".join(myAnalyses))
         raise Exception(ShellStyles.ErrorStyle() + msg +
                         ShellStyles.NormalStyle())
     else:
         return analysis
    def _validateDatacard(self, config):
        if config.ControlPlots == None:
            return

        if config.OptionSqrtS == None:
            raise Exception(
                ShellStyles.ErrorLabel() +
                "Please set the parameter OptionSqrtS = <integer_value_in_TeV> in the config file!"
                + ShellStyles.NormalStyle())
        return
 def _obtainQCDNormalizationSystHistograms(self, shapeHisto, dsetMgr,
                                           plotName, luminosity,
                                           normDataSrc, normEWKSrc):
     print ShellStyles.HighlightStyle(
     ) + "...Obtaining region transition systematics" + ShellStyles.NormalStyle(
     )
     myPlotSignalRegionShape = dataDrivenQCDCount.DataDrivenQCDShape(
         dsetMgr=dsetMgr,
         dsetLabelData="Data",
         dsetLabelEwk="EWK",
         histoName=plotName,
         dataPath=normDataSrc + "QCDNormalizationSignal",
         ewkPath=normEWKSrc + "QCDNormalizationSignal",
         luminosity=luminosity)
     myPlotControlRegionShape = dataDrivenQCDCount.DataDrivenQCDShape(
         dsetMgr=dsetMgr,
         dsetLabelData="Data",
         dsetLabelEwk="EWK",
         histoName=plotName,
         dataPath=normDataSrc + "QCDNormalizationControl",
         ewkPath=normEWKSrc + "QCDNormalizationControl",
         luminosity=luminosity)
     myPlotRegionTransitionSyst = metSyst.SystematicsForMetShapeDifference(
         myPlotSignalRegionShape,
         myPlotControlRegionShape,
         shapeHisto,
         moduleInfoString=self._moduleInfoString,
         quietMode=True)
     myPlotSignalRegionShape.delete()
     myPlotControlRegionShape.delete()
     # Store up and down variations
     #hUp = aux.Clone(myPlotRegionTransitionSyst.getUpHistogram(), "QCDfactMgrSystQCDSystUp%d"%i)
     #hUp.SetTitle(plotName+"systQCDUp")
     #self._QCDNormalizationSystPlots.append(hUp)
     #self._QCDNormalizationSystPlotLabels.append(hUp.GetTitle())
     #hDown = aux.Clone(myPlotRegionTransitionSyst.getDownHistogram(), "QCDfactMgrSystQCDSystDown%d"%i)
     #hDown.SetTitle(plotName+"systQCDDown")
     #self._QCDNormalizationSystPlots.append(hDown)
     #self._QCDNormalizationSystPlotLabels.append(hDown.GetTitle())
     # Store source histograms
     hNum = aux.Clone(
         myPlotRegionTransitionSyst.getCombinedSignalRegionHistogram(),
         "QCDfactMgrSystQCDSystNumerator")
     hNum.SetTitle(plotName + "systQCDNumerator")
     self._QCDNormalizationSystPlots.append(hNum)
     self._QCDNormalizationSystPlotLabels.append(hNum.GetTitle())
     hDenom = aux.Clone(
         myPlotRegionTransitionSyst.getCombinedCtrlRegionHistogram(),
         "QCDfactMgrSystQCDSystDenominator")
     hDenom.SetTitle(plotName + "systQCDDenominator")
     self._QCDNormalizationSystPlots.append(hDenom)
     self._QCDNormalizationSystPlotLabels.append(hDenom.GetTitle())
     # Free memory
     myPlotRegionTransitionSyst.delete()
示例#22
0
    def _printSelection(self):
        # Define style here
        myNotSelectedStr = "      "
        mySelectedStr = "  %s--> " % (ShellStyles.HighlightStyle())
        mySelectedSuffix = " <--%s" % (ShellStyles.NormalStyle())

        print "\nSelected data eras:"
        for i in range(0, len(self._availableEras)):
            myStr = myNotSelectedStr
            mySuffix = ""
            if self._availableEras[i] in self._selectedEras:
                myStr = mySelectedStr
                mySuffix = mySelectedSuffix
            print "%s%2d: %s%s" % (myStr, i, self._availableEras[i].replace(
                "Run", ""), mySuffix)
        print "\nSelected search modes:"
        for i in range(0, len(self._availableSearchModes)):
            myStr = myNotSelectedStr
            mySuffix = ""
            if self._availableSearchModes[i] in self._selectedSearchModes:
                myStr = mySelectedStr
                mySuffix = mySelectedSuffix
            print "%s%2d: %s%s" % (myStr, i, self._availableSearchModes[i],
                                   mySuffix)
        print "\nSelected optimization modes:"
        for i in range(0, len(self._availableOptimizationModes)):
            myStr = myNotSelectedStr
            mySuffix = ""
            if self._availableOptimizationModes[
                    i] in self._selectedOptimizationModes:
                myStr = mySelectedStr
                mySuffix = mySelectedSuffix
            if self._availableOptimizationModes[i] == "":
                print "%s%2d: (nominal)%s" % (myStr, i, mySuffix)
            else:
                print "%s%2d: %s%s" % (
                    myStr, i, self._availableOptimizationModes[i].replace(
                        "Opt", ""), mySuffix)
        if not self._disableSystematicsList:
            print "\nSelected systematic variations:"
            for i, systVar in enumerate(self._availableSystematicVariations):
                myStr = myNotSelectedStr
                mySuffix = ""
                if systVar in self._selectedSystematicVariations:
                    myStr = mySelectedStr
                    mySuffix = mySelectedSuffix
                if systVar == "":
                    print "%s%2d: (nominal)%s" % (myStr, i, mySuffix)
                else:
                    print "%s%2d: %s%s" % (
                        myStr, i, systVar.replace("SystVar", ""), mySuffix)
        print ""
 def _sanityChecks(self, dsetMgr, dirName, plotName):
     myStatus = True
     myFoundStatus = True
     for d in dsetMgr.getDataset("EWK").datasets:
         if not d.hasRootHisto("%s/%s" % (dirName, plotName)):
             myFoundStatus = False
     if not myFoundStatus:
         myStatus = False
         print ShellStyles.WarningLabel(
         ) + "Skipping '%s', because it does not exist for all EWK datasets (you probably forgot to set histo level to Vital when producing the multicrab)!" % (
             plotName) + ShellStyles.NormalStyle()
     else:
         (myRootObject,
          myRootObjectName) = dsetMgr.getDataset("EWK").getFirstRootHisto(
              "%s/%s" % (dirName, plotName))
         if isinstance(myRootObject, ROOT.TH2):
             print ShellStyles.WarningLabel(
             ) + "Skipping '%s', because it is not a TH1 object!" % (
                 plotName) + ShellStyles.NormalStyle()
             myStatus = False
         myRootObject.Delete()
     return myStatus
示例#24
0
 def GetEnergy(self, dsetMgr):
     '''
     Obtain luminosity information 
     from the dataset manager
     '''
     if isinstance(dsetMgr.getDataset("Data"), dataset.Dataset):
         myEnergy = dsetMgr.getDataset("Data").getEnergy()
     else:
         myEnergy = dsetMgr.getDataset("Data").datasets[0].getEnergy()
     msg = "Centre-of-Mass energy is %s TeV" % (
         ShellStyles.NoteStyle() + myEnergy + ShellStyles.NormalStyle())
     self.Verbose(msg, True)
     return float(myEnergy)
示例#25
0
 def getListOfSystematics(self):
     if self._analysisType == "HToTauNu":
         return self.getSystematicsForHToTauNu()
     elif self._analysisType == "HToTB":
         return self.getSystematicsForHToTB()
     elif self._analysisType == "HToHW":
         return self.getSystematicsForHToHW()
     elif self._analysisType == "HToHW_background":
         return self.getSystematicsForHToHW_background()
     else:
         raise Exception(ShellStyles.ErrorStyle() +
                         "This should never be reached" +
                         ShellStyles.NormalStyle())
示例#26
0
    def __init__(self, resultDirName, moduleInfoString, verbose=False):
        self._verbose = verbose
        self._templates = {}
        self._sources = {}
        self._commentLines = []
        self._BinLabelMap = {}
        self._TF = {}  # Transfer Factor (TF)
        self._TF_Error = {}
        self._TF_Up = {}
        self._TF_Down = {}
        self._dqmKeys = OrderedDict()
        self._myPath = os.path.join(resultDirName, "normalisationPlots")
        self.Verbose("__init__")

        # No optimisation mode
        if moduleInfoString == "":
            moduleInfoString = "Default"

        if not os.path.exists(self._myPath):
            self.Print("Creating new directory %s" % (self._myPath), True)
            os.mkdir(self._myPath)
        self._plotDirName = os.path.join(resultDirName, "normalisationPlots",
                                         moduleInfoString)

        # If already exists, Delete an entire directory tree
        if os.path.exists(self._plotDirName):
            msg = "Removing directory tree %s" % (self._plotDirName)
            self.Verbose(
                ShellStyles.NoteStyle() + msg + ShellStyles.NormalStyle(),
                True)
            shutil.rmtree(self._plotDirName)
        msg = "Creating directory %s" % (self._plotDirName)
        self.Verbose(
            ShellStyles.SuccessStyle() + msg + ShellStyles.NormalStyle(),
            False)
        os.mkdir(self._plotDirName)
        return
示例#27
0
def ApplyBlinding(myObject, blindedRange = []):
    '''
    myObject must be an instance of:
    h=histograms.Histo(rootHisto, "Label")
    and the rooHistos is an instance of:
    rootHisto = p.histoMgr.getHisto("HistoName").getRootHisto()
    '''

    if len(blindedRange) != 2:
        msg = "Blinded range list requires exactly 2 values (got %s)" % len(blindedRange) 
        raise Exception(ShellStyles.ErrorStyle() + msg + ShellStyles.NormalStyle())

    # Definitions
    myMin = None
    myMax = None
    myHisto = myObject.getRootHisto()

    # For-loop: All histogram bins
    for i in range (1, myHisto.GetNbinsX()+1):
        myUpEdge  = myHisto.GetXaxis().GetBinUpEdge(i)
        myLowEdge = myHisto.GetXaxis().GetBinLowEdge(i)
        
        # Define conditions
        c1 = (myLowEdge >= blindedRange[0] and myLowEdge <= blindedRange[1]) 
        c2 = (myUpEdge  >= blindedRange[0] and myUpEdge  <= blindedRange[1])
        c3 = (myLowEdge <= blindedRange[0] and myUpEdge  >= blindedRange[1])

        # Blind if any edge of the current bin is inside the blinded range or if bin spans over the blinded range
        if ( c1 or c2 or c3):
            if myMin == None or myLowEdge < myMin:
                myMin = myLowEdge
            if myMax == None or myUpEdge > myMax:
                myMax = myUpEdge
            #  Blind data by setting bin content to -1.0
            myHisto.SetBinContent(i, -1.0)
            myHisto.SetBinError(i, 0.0)

    if myMin == None:
        return None
    
    # Prepare blinding string for printing on canvas
    myMinFormat = "%" + "d"
    myMaxFormat = "%" + "d"
    if abs(myMin) < 1.0 and abs(myMin) > 0.00000001:
        myMinFormat = "%%.%df" % (abs(int(log10(myMin)))+1)
    if abs(myMax) < 1.0  and abs(myMax) > 0.00000001:
        myMaxFormat = "%%.%df" % (abs(int(log10(myMax)))+1)
    bString = myMinFormat%myMin+"-"+myMaxFormat%myMax
    return bString
示例#28
0
    def GetLuminosity(self, dsetMgr):
        '''
        Obtain luminosity information from the
        dataset manager by looping over all data 
        datasets
        '''
        myLuminosity = 0.0
        myDataDatasets = dsetMgr.getDataDatasets()
        for d in myDataDatasets:
            myLuminosity += d.getLuminosity()

        msg = "Integrated luminosity is %s%.3f%s" % (
            ShellStyles.NoteStyle(), myLuminosity, ShellStyles.NormalStyle())
        self.Verbose(msg, True)
        return myLuminosity
    def GetTotalUncertainyTable(self, hRate, hSystUp, hSystDown, hLine, align):
        table = []

        # Calculate total uncertainty
        rateNominalSum = hRate.Integral()
        rateSystUpSum = hSystUp.Integral()
        rateSystDownSum = hSystDown.Integral()
        signalUncert = 0.0
        ctrlUncert = 0.0
        ratio = 1.0
        ratioSigma = 0.0
        nBinsX = hRate.GetNbinsX()

        # For-loop: All bins in histo (up)
        for i in range(1, nBinsX + 1):
            signalUncert += hSystUp.GetBinError(i)**2
            ctrlUncert += hSystDown.GetBinError(i)**2

        # Sanity check
        if rateSystUpSum > 0.0 and rateSystDownSum > 0.0:
            # Calculate ratio and its error with error propagation
            ratio = rateSystUpSum / rateSystDownSum
            # Calculate ratio error with error propagation
            ratioSigma = errorPropagationForDivision(rateSystUpSum,
                                                     sqrt(signalUncert),
                                                     rateSystDownSum,
                                                     sqrt(ctrlUncert))

        # Calculate % errors up/down
        table.append(hLine)
        sigmaUp = (ratio + ratioSigma - 1.0) * 100
        sigmaDown = (ratio - ratioSigma - 1.0) * 100
        rangeX = "%s to %s" % (hRate.GetBinCenter(1),
                               hRate.GetBinCenter(nBinsX))
        rangeBins = "1 to %d" % (nBinsX)
        table.append(
            align.format(rangeBins, rangeX, "%.1f" % rateNominalSum,
                         "%.1f" % rateSystUpSum, "%.1f" % rateSystDownSum,
                         "%.1f" % (sigmaUp), "%.1f" % (sigmaDown)))
        evtYield = "{:^85}".format(
            "Events +/- stat. +/- syst. = %.1f +/- %.1f +/- %.1f" %
            (rateNominalSum, abs(rateNominalSum - rateSystUpSum),
             abs(rateNominalSum - rateSystDownSum)))
        table.append(ShellStyles.HighlightAltStyle() + evtYield +
                     ShellStyles.NormalStyle())
        table.append(hLine)
        return table
 def getDataHistoForSplittedBin(self, binIndex):
     '''
     Return the data in a given phase space split bin
     '''
     if binIndex >= len(self._dataList):
         # FIXME: New addition to fix "optionUseInclusiveNorm" functionality (24-Mar-2018). Should not affect binned result!
         if self._optionUseInclusiveNorm:  #new
             h = aux.Clone(self._dataList[0])  #new
             h.SetName(h.GetName() + "_")  #new
             return h  #new
         msg = "Requested bin index %d out of range (0-%d)!" % (
             binIndex, len(self._dataList))
         raise Exception(ShellStyles.ErrorLabel() + msg +
                         ShellStyles.NormalStyle())
     h = aux.Clone(self._dataList[binIndex])
     h.SetName(h.GetName() + "_")
     return h