def __init__(self, value, uncertaintyList, uncertaintyLabelList): # Make sure the values are of floating point type self._value = float(value) self._uncertaintyList = [] for v in uncertaintyList: self._uncertaintyList.append(float(v)) # Note: without the list(), one would copy the pointers instead of the values self._uncertaintyLabelList = list(uncertaintyLabelList) # check that list lengths match if len(uncertaintyList) != len(uncertaintyLabelList): raise Exception( ShellStyles.ErrorLabel() + "ExtendedCount::__init__(): please provide equal amount of entries for uncertaintyList and uncertaintyLabelList! (%d vs. %d)" % (len(uncertaintyList), len(uncertaintyLabelList))) # check that labels contain word 'stat' or 'syst' for item in self._uncertaintyLabelList: myFoundStatus = False if "stat" in item: myFoundStatus = True elif "syst" in item: myFoundStatus = True if not myFoundStatus: raise Exception( ShellStyles.ErrorLabel() + "ExtendedCount::__init__(): uncertainty labels must contain 'stat' or 'syst' in them!" )
def _makePseudoMulticrabDirectory(self, rootFile): # Make module directory mySplit = self._moduleInfoString.split("_") myEra = mySplit[0] mySearchMode = mySplit[1] myVariation = mySplit[2] if len(mySplit) > 2: raise Exception(ShellStyles.ErrorLabel()+"Assert len(moduleInfoString.split('_') == 3 failed! (mod = %s)"%self._moduleInfoString) myModuleDir = "signalAnalysisInvertedTau%s%s%s"%(mySearchMode, myEra, myVariation) rootFile.cd("/") rootFile.mkdir(myModuleDir) rootFile.cd(myModuleDir) # Loop over directory names for i in range(0, len(self._directoryNames)): # Handle final shapes if "shape" in self._directoryNames[i]: # Write shape histogram self._histograms[i].Clone(self._directoryNames[i]).Write() else: # Create first directory mySplit = self._directoryNames[i].split("/") mySubDir = mySplit[0] myHistoName = mySplit[1] if len(mySplit) > 1: raise Exception(ShellStyles.ErrorLabel()+"Assert len(directoryNames.split('/') == 2 failed! (mod = %s)"%self._directoryNames[i]) rootFile.mkdir(mySubDir) rootFile.cd(mySubDir) self._histograms[i].Clone(myHistoName).Write() rootFile.cd(myModuleDir) rootFile.Write() print "Written module %s to the pseudo-multicrab output"%self._moduleInfoString
def _applySelectionOnModules(self, itemLabel, optionsList, availableList, defaultList=None): if optionsList == None: # No specific items selected in options, use all possibilities if defaultList is not None: return defaultList return availableList # Loop over desired modules (either digit or string) selectList = [] for item in optionsList: if item.isdigit(): if int(item) >= len(availableList) or int(item) < 0: raise Exception( ShellStyles.ErrorLabel() + " %s selection: requested for index %s, but only options 0-%d are available!" % (itemLabel, item, len(availableList) - 1)) selectList.append(availableList[int(item)]) else: if not item in availableList: raise Exception( ShellStyles.ErrorLabel() + " %s selection: requested for %s, but only options (%s) are available!" % (itemLabel, item, (', '.join(map(str, availableList))))) else: selectList.append(item) return selectList
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
def getPhaseSpaceBinTitle(self, binIndex): if binIndex >= len(self._dataList): raise Exception( ShellStyles.ErrorLabel() + "DataDrivenQCDShape::getPhaseSpaceBinTitle: requested bin index %d out of range (0-%d)!" % (binIndex, len(self._dataList))) return self._dataList[binIndex].GetTitle()
def getDataDrivenQCDHistoForSplittedBin(self, binIndex): if binIndex >= len(self._dataList): raise Exception(ShellStyles.ErrorLabel()+"DataDrivenQCDShape::getDataDrivenQCDForSplittedBin: requested bin index %d out of range (0-%d)!"%(binIndex,len(self._dataList))) h = aux.Clone(self._dataList[binIndex]) h.SetName(h.GetName()+"dataDriven") h.Add(self._ewkList[binIndex], -1.0) return h
def uncertainty(self, label): for i in range(0, len(self._uncertaintyLabelList)): if label == self._uncertaintyLabelList[i]: return self._uncertaintyList[i] raise Exception( ShellStyles.ErrorLabel() + "ExtendedCount::uncertainty(): Cannot find asked label '%s'! options are: %s" % (label, ', '.join(map(str, self._uncertaintyLabelList))))
def _obtainFinalShapeHistogram(self, histoName): if histoName == None: raise Exception(ShellStyles.ErrorLabel()+"You forgot to give final shape histo name or to cache the final shape histogram!") print ShellStyles.WarningLabel()+"Final shape histo was not cached to QCDInvertedSystematics. Obtaining final shape from '%s'."%histoName # Obtain final result myFinalShape = DataDrivenQCDShape(self._dsetMgr, "Data", "EWK", histoName, self._luminosity, rebinList=self._myRebinList) myFinalShapeResult = QCDInvertedShape(myFinalShape, self._moduleInfoString, self._normFactors, optionPrintPurityByBins=False) self._hFinalShape = myFinalShapeResult.getResultShape().Clone()
def getGetNormFactorsSrcFilename(dirName, fileName): src = os.path.join(dirName, fileName) if not os.path.exists(src): msg = "Normalisation factors ('%s') not found!\nRun script \"plotQCD_Fit.py\" to auto-generate the normalization factors python file." % src raise Exception(ShellStyles.ErrorLabel() + msg) else: Verbose("Found src file for normalization factors:\n\t%s" % (src), True) return src
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 __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 getEwkHistoForSplittedBin(self, binIndex): ''' Return the EWK MC in a given phase space split bin ''' if binIndex >= len(self._dataList): raise Exception( ShellStyles.ErrorLabel() + "DataDrivenQCDShape::getEwkHistoForSplittedBin: requested bin index %d out of range (0-%d)!" % (binIndex, len(self._ewkList))) h = aux.Clone(self._ewkList[binIndex]) h.SetName(h.GetName() + "_") return h
def getPhaseSpaceBinFileFriendlyTitle(self, binIndex): if binIndex >= len(self._dataList): raise Exception( ShellStyles.ErrorLabel() + "DataDrivenQCDShape::getPhaseSpaceBinTitle: requested bin index %d out of range (0-%d)!" % (binIndex, len(self._dataList))) return self._dataList[binIndex].GetTitle().replace(">", "gt").replace( "<", "lt").replace("=", "eq").replace("{", "").replace("}", "").replace( " ", "").replace("#", "").replace("..", "to").replace("(", "").replace( ")", "").replace(",", "").replace("/", "_").replace(".", "p")
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
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
def _retrieveHistoSpecsFromHisto(self, histo, specs): if histo == None and specs == None: raise Exception(ShellStyles.ErrorLabel()+"Need to supply either a histogram or dictionary with bin specification for the histograms!") mySpecs = None if specs == None: mySpecs = {} specs = {} else: # Obtain specs from dictionary mySpecs = dict(specs) if histo != None: # Obtain specs from histogram if not "bins" in specs: mySpecs["bins"] = histo.GetXaxis().GetNbins() if not "rangeMin" in specs: mySpecs["rangeMin"] = histo.GetXaxis().GetXmin() if not "rangeMax" in specs: mySpecs["rangeMax"] = histo.GetXaxis().GetXmax() if not "xtitle" in specs: mySpecs["xtitle"] = histo.GetXaxis().GetTitle() if not "ytitle" in specs: mySpecs["ytitle"] = histo.GetYaxis().GetTitle() if not "variableBinSizeLowEdges" in specs: # Check if constant interval binning is used if histo.GetXaxis().GetXbins().GetSize() == 0: mySpecs["variableBinSizeLowEdges"] = [] else: myArray = histo.GetXaxis().GetXbins() myBinEdges = [] for i in range(0,myArray.GetSize()-1): # Ignore last bin since it is the right edge of the last bin myBinEdges.append(myArray.GetAt(i)) mySpecs["variableBinSizeLowEdges"] = list(myBinEdges) mySpecs["bins"] = len(myBinEdges) else: # No histogram provided if not "xtitle" in specs: mySpecs["xtitle"] = "" if not "ytitle" in specs: mySpecs["ytitle"] = "" if "variableBinSizeLowEdges" in mySpecs: if len(mySpecs["variableBinSizeLowEdges"]) > 0: mySpecs["bins"] = len(mySpecs["variableBinSizeLowEdges"]) else: mySpecs["variableBinSizeLowEdges"] = [] return mySpecs
def __init__(self, histoSpecs, histoObjectForSpecs=None, debugMode=False): if isinstance(histoSpecs,list): raise Exception(ShellStyles.ErrorLabel()+"ShapeHistoModifier: Requested a %d-dimensional histogram, but code currently supports only 1 dimension!"%len(histoSpecs)) mySpecs = self._retrieveHistoSpecsFromHisto(histoObjectForSpecs, histoSpecs) self._nbins = mySpecs["bins"] self._min = mySpecs["rangeMin"] self._max = mySpecs["rangeMax"] self._binLowEdges = list(mySpecs["variableBinSizeLowEdges"]) self._xtitle = mySpecs["xtitle"] self._ytitle = mySpecs["ytitle"] # Variable bin widths support if len(self._binLowEdges) == 0: # Create bins with uniform width binwidth = (self._max-self._min) / self._nbins for i in range(0,self._nbins): self._binLowEdges.append(i*binwidth+self._min) if debugMode: print "ShapeHistoModifier: nbins=%d, range=%f-%f"%(self._nbins,self._min,self._max) print" bin low edges:",self._binLowEdges
def importNormFactors(era, searchMode, optimizationMode, multicrabDirName): # Obtain suffix suffix = "" s = multicrabDirName.split("_") if s[len(s) - 1].endswith("pr") or s[len(s) - 1].endswith("prong"): suffix = "_" + s[len(s) - 1] # Find candidates for normalisation scripts fileList = os.listdir(multicrabDirName) scriptList = [] for item in fileList: if item.startswith( (_generalOptions["normalizationFactorSource"] % "").replace( ".py", "")): scriptList.append(item) moduleInfoString = "_%s_%s" % (era, searchMode) if len(optimizationMode) > 0: moduleInfoString += "_%s" % (optimizationMode) # Construct source file name src = os.path.join( multicrabDirName, _generalOptions["normalizationFactorSource"] % moduleInfoString) if not os.path.exists(src): if len(scriptList): print "Found following normalization info files:" for item in scriptList: print " ", item else: print "Found no normalization info files!" raise Exception( ShellStyles.ErrorLabel() + "Normalisation factors ('%s') not found!\nRun script QCDMeasurementNormalization.py to generate the normalization factors." % src) print "Reading normalisation factors from:", src # Check if normalization coefficients are suitable for era s = src.replace(".py", "").split("/") if len(s) > 1: # Insert the directory where the norm.coeff. files reside into the path so that they are found sys.path.insert( 0, os.path.join(os.getenv("PWD"), "/".join(map(str, s[:(len(s) - 1)])))) normFactorsImport = __import__(s[len(s) - 1]) myNormFactorsSafetyCheck = getattr(normFactorsImport, "QCDInvertedNormalizationSafetyCheck") # Check that the era, searchMode, optimizationMode info matches myNormFactorsSafetyCheck(era, searchMode, optimizationMode) # Obtain normalization factors myNormFactorsImport = getattr(normFactorsImport, "QCDNormalization") myNormFactorsImportSystVarFakeWeightingDown = getattr( normFactorsImport, "QCDPlusEWKFakeTausNormalizationSystFakeWeightingVarDown") myNormFactorsImportSystVarFakeWeightingUp = getattr( normFactorsImport, "QCDPlusEWKFakeTausNormalizationSystFakeWeightingVarUp") myNormFactors = {} myNormFactors["nominal"] = myNormFactorsImport myNormFactors[ "FakeWeightingDown"] = myNormFactorsImportSystVarFakeWeightingDown myNormFactors[ "FakeWeightingUp"] = myNormFactorsImportSystVarFakeWeightingUp return myNormFactors
def IsTH1(h): if not isinstance(h, ROOT.TH1): msg = "ERROR! Expected object of type ROOT.TH1, got \"%s\" instead" % (type(h)) raise Exception(ShellStyles.ErrorLabel() + msg + ShellStyles.NormalStyle()) else: return
action="store_true", default=False, help="Make short test by limiting number of syst. variations") # Add here parser options, if necessary, following line is an example #parser.add_option("--showcard", dest="showDatacard", action="store_true", default=False, help="Print datacards also to screen") # Parse options (opts, args) = parser.parse_args() # Obtain multicrab directory myMulticrabDir = "." if opts.multicrabDir != None: myMulticrabDir = opts.multicrabDir if not os.path.exists("%s/multicrab.cfg" % myMulticrabDir): raise Exception( ShellStyles.ErrorLabel() + "No multicrab directory found at path '%s'! Please check path or specify it with --mdir!" % (myMulticrabDir) + ShellStyles.NormalStyle()) if len(opts.shape) == 0: raise Exception( ShellStyles.ErrorLabel() + "Provide a shape identifierwith --shape (for example MT)!" + ShellStyles.NormalStyle()) # Set EWK source depending on calculation mode if opts.qcdonly: _generalOptions["EWKsource"] = _generalOptions["ewkSourceForQCDOnly"] else: _generalOptions["EWKsource"] = _generalOptions[ "ewkSourceForQCDPlusFakeTaus"]
def _initialize(self, h): if len(self._binLabels) > 0: return myTitle = h.GetTitle() myList = myTitle.split(self._separator) myFactorisationBins = int( len(myList) / 2 ) # allows for the title of the histogram to be placed after the last separator myOutput = "" for i in range(0, myFactorisationBins): self._binLabels.append(myList[i * 2]) if myList[i * 2 + 1].isdigit(): self._binCount.append(int(myList[i * 2 + 1])) else: # try a bug fix by taking first character only if myList[i * 2 + 1][0].isdigit(): print ShellStyles.WarningLabel( ) + "UnfoldedHistogramReader::_initialize(): tried naive bug fix for last factorisation bin dimension (guessed dimension: %s, histo: %s)" % ( myList[i * 2 + 1][0], myList[i * 2 + 1][1:]) self._binCount.append(int(myList[i * 2 + 1][0])) else: raise Exception( ShellStyles.ErrorLabel() + "UnfoldedHistogramReader: failed to decompose histogram title (it should contain the bin label and nbins information for n bins separated with '%s'\nHistogram title was: %s" % (self._separator, myTitle)) myOutput += "%s nbins=%d " % (self._binLabels[i], self._binCount[i]) if self._debugStatus: print "UnfoldedHistogramReader: Histogram binning determined as : %s" % myOutput if len(self._binLabels) == 0: raise Exception( ShellStyles.ErrorLabel() + "UnfoldedHistogramReader: failed to decompose histogram title (it should contain the bin label and nbins information for n bins separated with '%s'\nHistogram title was: %s" % (self._separator, myTitle)) self._unfoldedBinCount = h.GetNbinsY() # Loop over y axis to find axis values myBinCaptions = [] myBinRanges = [] for i in range(1, h.GetNbinsY() + 1): mySplitBin = h.GetYaxis().GetBinLabel(i).split("/") # Obtain bin captions if len(self._factorisationCaptions) == 0: for s in mySplitBin: myCaption = "" if "=" in s: myCaption = s.split("=")[0] elif ">" in s: myCaption = s.split(">")[0] elif "<" in s: myCaption = s.split("<")[0] self._factorisationFullBinLabels.append([]) self._factorisationCaptions.append(myCaption) self._factorisationRanges.append([]) # Obtain range information for k in range(0, len(mySplitBin)): if not mySplitBin[k] in self._factorisationFullBinLabels[k]: self._factorisationFullBinLabels[k].append(mySplitBin[k]) # Remove label and equal signs s = mySplitBin[k].replace(self._factorisationCaptions[k], "").replace("=", "") if not s in self._factorisationRanges[k]: self._factorisationRanges[k].append(s)
def __init__(self, opts, config, dirname, luminosity, observation, datasetGroups): plots._legendLabels["MCStatError"] = "Bkg. stat." plots._legendLabels["MCStatSystError"] = "Bkg. stat.#oplussyst." plots._legendLabels["BackgroundStatError"] = "Bkg. stat. unc" plots._legendLabels["BackgroundStatSystError"] = "Bkg. stat.#oplussyst. unc." if config.ControlPlots == None: return myStyle = tdrstyle.TDRStyle() myStyle.setOptStat(False) self._opts = opts self._config = config if config.OptionSqrtS == None: raise Exception(ShellStyles.ErrorLabel()+"Please set the parameter OptionSqrtS = <integer_value_in_TeV> in the config file!"+ShellStyles.NormalStyle()) self._dirname = dirname self._luminosity = luminosity self._observation = observation self._datasetGroups = datasetGroups #myEvaluator = SignalAreaEvaluator() # Make control plots print "\n"+ShellStyles.HighlightStyle()+"Generating control plots"+ShellStyles.NormalStyle() # Loop over mass points massPoints = [] massPoints.extend(self._config.MassPoints) massPoints.append(-1) # for plotting with no signal for m in massPoints: print "... mass = %d GeV"%m # Initialize flow plot selectionFlow = SelectionFlowPlotMaker(self._opts, self._config, m) myBlindedStatus = False for i in range(0,len(self._config.ControlPlots)): if observation.getControlPlotByIndex(i) != None: myCtrlPlot = self._config.ControlPlots[i] print "......", myCtrlPlot.title myMassSuffix = "_M%d"%m # Initialize histograms hSignal = None hQCD = None hQCDdata = None hEmbedded = None hEWKfake = None hData = None # Loop over dataset columns to find histograms myStackList = [] for c in self._datasetGroups: if (m < 0 or c.isActiveForMass(m,self._config)) and not c.typeIsEmptyColumn() and not c.getControlPlotByIndex(i) == None: h = c.getControlPlotByIndex(i)["shape"].Clone() if c.typeIsSignal(): #print "signal:",c.getLabel() # Scale light H+ signal if m < 179: if c.getLabel()[:2] == "HH": h.Scale(self._config.OptionBr**2) elif c.getLabel()[:2] == "HW": h.Scale(2.0*self._config.OptionBr*(1.0-self._config.OptionBr)) if hSignal == None: hSignal = h.Clone() else: hSignal.Add(h) elif c.typeIsQCDinverted(): print "------------" print "ollaanko nyt vaarassa paikassa" if hQCDdata == None: hQCDdata = h.Clone() else: hQCDdata.Add(h) elif c.typeIsQCD(): if hQCD == None: print "hQCD add kai onnistuu" hQCD = h.Clone() else: print "hQCD add onnistuu" hQCD.Add(h) elif c.typeIsEWK(): #print "EWK genuine:",c.getLabel(),h.getRootHisto().Integral(0,h.GetNbinsX()+2) if not self._config.OptionGenuineTauBackgroundSource == "DataDriven": myHisto = histograms.Histo(h,c._datasetMgrColumn) myHisto.setIsDataMC(isData=False, isMC=True) myStackList.append(myHisto) else: if hEmbedded == None: hEmbedded = h.Clone() else: hEmbedded.Add(h) elif c.typeIsEWKfake(): #print "EWK fake:",c.getLabel(),h.getRootHisto().Integral(0,h.GetNbinsX()+2) if hEWKfake == None: hEWKfake = h.Clone() else: hEWKfake.Add(h) if len(myStackList) > 0 or self._config.OptionGenuineTauBackgroundSource == "DataDriven": if hQCDdata != None: myHisto = histograms.Histo(hQCDdata,"QCDdata",legendLabel=_legendLabelQCDdata) myHisto.setIsDataMC(isData=False, isMC=True) myStackList.insert(0, myHisto) elif hQCD != None: myHisto = histograms.Histo(hQCD,"QCDdata",legendLabel=_legendLabelQCD) myHisto.setIsDataMC(isData=False, isMC=True) myStackList.insert(0, myHisto) if hEmbedded != None: myHisto = histograms.Histo(hEmbedded,"Embedding",legendLabel=_legendLabelEmbedding) myHisto.setIsDataMC(isData=False, isMC=True) myStackList.append(myHisto) if hEWKfake != None: myHisto = histograms.Histo(hEWKfake,"EWKfakes",legendLabel=_legendLabelEWKFakes) myHisto.setIsDataMC(isData=False, isMC=True) myStackList.append(myHisto) hData = observation.getControlPlotByIndex(i)["shape"].Clone() hDataUnblinded = hData.Clone() # Apply blinding myBlindingString = None if self._config.BlindAnalysis: if len(myCtrlPlot.blindedRange) > 0: myBlindingString = self._applyBlinding(hData,myCtrlPlot.blindedRange) if self._config.OptionBlindThreshold != None: for k in xrange(1, hData.GetNbinsX()+1): myExpValue = 0.0 for item in myStackList: myExpValue += item.getRootHisto().GetBinContent(k) if hSignal.getRootHisto().GetBinContent(k) >= myExpValue * self._config.OptionBlindThreshold: hData.getRootHisto().SetBinContent(k, -1.0) hData.getRootHisto().SetBinError(k, 0.0) # Data myDataHisto = histograms.Histo(hData,"Data") myDataHisto.setIsDataMC(isData=True, isMC=False) myStackList.insert(0, myDataHisto) # Add signal if m > 0: mySignalLabel = "TTToHplus_M%d"%m if m > 179: mySignalLabel = "HplusTB_M%d"%m myHisto = histograms.Histo(hSignal,mySignalLabel) myHisto.setIsDataMC(isData=False, isMC=True) myStackList.insert(1, myHisto) # Add data to selection flow plot #if myBlindedStatus: # selectionFlow.addColumn(myCtrlPlot.flowPlotCaption,None,myStackList[1:]) #else: selectionFlow.addColumn(myCtrlPlot.flowPlotCaption,hDataUnblinded,myStackList[1:]) if len(myCtrlPlot.blindedRange) > 0: myBlindedStatus = True else: myBlindedStatus = False # Make plot myStackPlot = None myParams = myCtrlPlot.details.copy() #if not isinstance(hData, ROOT.TH2): #for j in range(1,myStackList[0].getRootHisto().GetNbinsY()+1): #for i in range(1,myStackList[0].getRootHisto().GetNbinsX()+1): #mySum = 0.0 #for h in range(2, len(myStackList)): #mySum += myStackList[h].getRootHisto().GetBinContent(i,j) #if mySum > 0.0: #myStackList[0].getRootHisto().SetBinContent(i,j,myStackList[0].getRootHisto().GetBinContent(i,j) / mySum) #else: #myStackList[0].getRootHisto().SetBinContent(i,j,-10.0) #myStackList[0].getRootHisto().SetMinimum(-1.0) #myStackList[0].getRootHisto().SetMaximum(1.0) #myStackList = [myStackList[0]] #myStackPlot = plots.PlotBase(myStackList) #if "ylabelBinInfo" in myParams: #del myParams["ylabelBinInfo"] #del myParams["unit"] #drawPlot2D(myStackPlot, "%s/DataDrivenCtrlPlot_M%d_%02d_%s"%(self._dirname,m,i,myCtrlPlot.title), **myParams) myStackPlot = plots.DataMCPlot2(myStackList) myStackPlot.setLuminosity(self._luminosity) myStackPlot.setEnergy("%d"%self._config.OptionSqrtS) myStackPlot.setDefaultStyles() # Tweak paramaters if not "unit" in myParams.keys(): myParams["unit"] = "" if myParams["unit"] != "": myParams["xlabel"] = "%s (%s)"%(myParams["xlabel"],myParams["unit"]) ylabelBinInfo = True if "ylabelBinInfo" in myParams: ylabelBinInfo = myParams["ylabelBinInfo"] del myParams["ylabelBinInfo"] if ylabelBinInfo: myMinWidth = 10000.0 myMaxWidth = 0.0 for j in range(1,hData.getRootHisto().GetNbinsX()+1): w = hData.getRootHisto().GetBinWidth(j) if w < myMinWidth: myMinWidth = w if w > myMaxWidth: myMaxWidth = w myWidthSuffix = "" myMinWidthString = "%d"%myMinWidth myMaxWidthString = "%d"%myMaxWidth if myMinWidth < 1.0: myFormat = "%%.%df"%(abs(int(log10(myMinWidth)))+1) myMinWidthString = myFormat%myMinWidth if myMaxWidth < 1.0: myFormat = "%%.%df"%(abs(int(log10(myMaxWidth)))+1) myMaxWidthString = myFormat%myMaxWidth myWidthSuffix = "%s-%s"%(myMinWidthString,myMaxWidthString) if abs(myMinWidth-myMaxWidth) < 0.001: myWidthSuffix = "%s"%(myMinWidthString) if not (myParams["unit"] == "" and myWidthSuffix == "1"): myParams["ylabel"] = "%s / %s %s"%(myParams["ylabel"],myWidthSuffix,myParams["unit"]) if myBlindingString != None: if myParams["unit"] != "" and myParams["unit"][0] == "^": myParams["blindingRangeString"] = "%s%s"%(myBlindingString, myParams["unit"]) else: myParams["blindingRangeString"] = "%s %s"%(myBlindingString, myParams["unit"]) if "legendPosition" in myParams.keys(): if myParams["legendPosition"] == "NE": myParams["moveLegend"] = {"dx": -0.10, "dy": -0.02} elif myParams["legendPosition"] == "SE": myParams["moveLegend"] = {"dx": -0.10, "dy": -0.56} elif myParams["legendPosition"] == "SW": myParams["moveLegend"] = {"dx": -0.53, "dy": -0.56} elif myParams["legendPosition"] == "NW": myParams["moveLegend"] = {"dx": -0.53, "dy": -0.02} else: raise Exception("Unknown value for option legendPosition: %s!", myParams["legendPosition"]) del myParams["legendPosition"] elif not "moveLegend" in myParams: myParams["moveLegend"] = {"dx": -0.10, "dy": -0.02} # default: NE if "ratioLegendPosition" in myParams.keys(): if myParams["ratioLegendPosition"] == "left": myParams["ratioMoveLegend"] = {"dx": -0.51, "dy": 0.03} elif myParams["ratioLegendPosition"] == "right": myParams["ratioMoveLegend"] = {"dx": -0.08, "dy": 0.03} elif myParams["ratioLegendPosition"] == "SE": myParams["ratioMoveLegend"] = {"dx": -0.08, "dy": -0.33} else: raise Exception("Unknown value for option ratioLegendPosition: %s!", myParams["ratioLegendPosition"]) del myParams["ratioLegendPosition"] else: if not "ratioMoveLegend" in myParams: myParams["ratioMoveLegend"] = {"dx": -0.51, "dy": 0.03} # default: left # Remove non-dientified keywords del myParams["unit"] # Ratio axis if not "opts2" in myParams.keys(): myParams["opts2"] = {"ymin": 0.3, "ymax": 1.7} # Do plotting if m > 0: drawPlot(myStackPlot, "%s/DataDrivenCtrlPlot_M%d_%02d_%s"%(self._dirname,m,i,myCtrlPlot.title), **myParams) else: drawPlot(myStackPlot, "%s/DataDrivenCtrlPlot_%02d_%s"%(self._dirname,i,myCtrlPlot.title), **myParams) # Do selection flow plot selectionFlow.makePlot(self._dirname,m,len(self._config.ControlPlots),self._luminosity) #myEvaluator.save(dirname) print "Control plots done"
def main(): # Object for selecting data eras, search modes, and optimization modes myModuleSelector = analysisModuleSelector.AnalysisModuleSelector() # Obtain multicrab directory myMulticrabDir = "." if opts.mcrab != None: myMulticrabDir = opts.mcrab if not os.path.exists("%s/multicrab.cfg" % myMulticrabDir): msg = "No multicrab directory found at path '%s'! Please check path or specify it with --mcrab!" % ( myMulticrabDir) raise Exception(ShellStyles.ErrorLabel() + msg + ShellStyles.NormalStyle()) if len(opts.shape) == 0: raise Exception( ShellStyles.ErrorLabel() + "Provide a shape identifierwith --shape (for example MT)!" + ShellStyles.NormalStyle()) # Obtain dsetMgrCreator and register it to module selector dsetMgrCreator = dataset.readFromMulticrabCfg(directory=myMulticrabDir) # Obtain systematics names mySystematicsNamesRaw = dsetMgrCreator.getSystematicVariationSources() mySystematicsNames = [] for item in mySystematicsNamesRaw: mySystematicsNames.append("%sPlus" % item) mySystematicsNames.append("%sMinus" % item) if opts.test: mySystematicsNames = [] #[mySystematicsNames[0]] #FIXME # Set the primary source myModuleSelector.setPrimarySource(label=opts.analysisName, dsetMgrCreator=dsetMgrCreator) # Select modules myModuleSelector.doSelect(opts=None) #FIXME: (opts=opts) # Loop over era/searchMode/optimizationMode combos myDisplayStatus = True myTotalModules = myModuleSelector.getSelectedCombinationCount() * ( len(mySystematicsNames) + 1) * len(opts.shape) Verbose("Found %s modules in total" % (myTotalModules), True) count, nEras, nSearchModes, nOptModes, nSysVars = myModuleSelector.getSelectedCombinationCountIndividually( ) if nSysVars > 0: msg = "Will run over %d modules (%d eras x %d searchModes x %d optimizationModes x %d systematic variations)" % ( count, nEras, nSearchModes, nOptModes, nSysVars) else: msg = "Will run over %d modules (%d eras x %d searchModes x %d optimizationModes)" % ( count, nEras, nSearchModes, nOptModes) Print(msg, True) # Create pseudo-multicrab creator myOutputCreator = pseudoMultiCrabCreator.PseudoMultiCrabCreator( opts.analysisName, myMulticrabDir) # Make time stamp for start time myGlobalStartTime = time.time() iModule = 0 # For-loop: All Shapes for shapeType in opts.shape: # Initialize myOutputCreator.initialize(shapeType, prefix="") msg = "Creating dataset for shape \"%s\"%s" % ( shapeType, ShellStyles.NormalStyle()) Verbose(ShellStyles.HighlightStyle() + msg, True) # Get lists of settings erasList = myModuleSelector.getSelectedEras() modesList = myModuleSelector.getSelectedSearchModes() optList = myModuleSelector.getSelectedOptimizationModes() optList.append("") #append the default opt mode! # For-Loop over era, searchMode, and optimizationMode options for era in erasList: for searchMode in modesList: for optimizationMode in optList: Verbose( "era = %s, searchMode = %s, optMode = %s" % (era, searchMode, optimizationMode), True) # If an optimization mode is defined in options skip the rest if opts.optMode != None: if optimizationMode != opts.optMode: continue # Obtain normalization factors myNormFactors = importNormFactors(era, searchMode, optimizationMode, opts.mcrab) # Nominal module myModuleInfoString = getModuleInfoString( era, searchMode, optimizationMode) iModule += 1 # Inform user of what is being processes msg = "Module %d/%d:%s %s/%s" % ( iModule, myTotalModules, ShellStyles.NormalStyle(), myModuleInfoString, shapeType) Print(ShellStyles.CaptionStyle() + msg, True) # Keep time myStartTime = time.time() Verbose("Create dataset manager with given settings", True) nominalModule = ModuleBuilder(opts, myOutputCreator) nominalModule.createDsetMgr(myMulticrabDir, era, searchMode, optimizationMode) if (iModule == 1): if opts.verbose: nominalModule.debug() doQCDNormalizationSyst = False #FIXME if not doQCDNormalizationSyst: msg = "Disabling systematics" Print(ShellStyles.WarningLabel() + msg, True) nominalModule.buildModule(opts.dataSrc, opts.ewkSrc, myNormFactors["nominal"], doQCDNormalizationSyst, opts.normDataSrc, opts.normEwkSrc) if len(mySystematicsNames) > 0: Print( "Adding QCD normalization systematics (iff also other systematics present) ", True) nominalModule.buildQCDNormalizationSystModule( opts.dataSrc, opts.ewkSrc) # FIXME: add quark gluon weighting systematics! if 0: Print("Adding Quark/Gluon weighting systematics", True) nominalModule.buildQCDQuarkGluonWeightingSystModule( opts.dataSrc, opts.ewkSrc, myNormFactors["FakeWeightingUp"], myNormFactors["FakeWeightingDown"], False, opts.normDataSrc, opts.normEwkSrc) Verbose("Deleting nominal module", True) nominalModule.delete() Verbose("Printing time estimate", True) printTimeEstimate(myGlobalStartTime, myStartTime, iModule, myTotalModules) Verbose("Now do the rest of systematics variations", True) for syst in mySystematicsNames: iModule += 1 msg = "Analyzing systematics variations %d/%d: %s/%s/%s" % ( iModule, myTotalModules, myModuleInfoString, syst, shapeType) Print( ShellStyles.CaptionStyle() + msg + ShellStyles.NormalStyle(), True) myStartTime = time.time() systModule = ModuleBuilder(opts, myOutputCreator) # Create dataset manager with given settings systModule.createDsetMgr(myMulticrabDir, era, searchMode, optimizationMode, systematicVariation=syst) # Build asystematics module systModule.buildModule(opts.dataSrc, opts.ewkSrc, myNormFactors["nominal"], False, opts.normDataSrc, opts.normEwkSrc) printTimeEstimate(myGlobalStartTime, myStartTime, iModule, myTotalModules) systModule.delete() Verbose("Pseudo-multicrab ready for %s" % shapeType, True) # Create rest of pseudo multicrab directory myOutputCreator.silentFinalize() # Print some timing statistics Print( "Average processing time per module was %.1f s" % getAvgProcessTimeForOneModule(myGlobalStartTime, myTotalModules), True) Print( "Total elapsed time was %.1f s" % getTotalElapsedTime(myGlobalStartTime), False) msg = "Created pseudo-multicrab %s for shape type \"%s\"" % ( myOutputCreator.getDirName(), shapeType) Print(ShellStyles.SuccessLabel() + msg, True) return
if len(sys.argv) < 2: parser.print_help() sys.exit(1) if opts.mcrab == None: Print( "Not enough arguments passed to script execution. Printing docstring & EXIT." ) parser.print_help() #print __doc__ sys.exit(1) else: if not os.path.exists("%s/multicrab.cfg" % opts.mcrab): msg = "No pseudo-multicrab directory found at path '%s'! Please check path or specify it with --mcrab!" % ( opts.mcrab) raise Exception(ShellStyles.ErrorLabel() + msg + ShellStyles.NormalStyle()) else: msg = "Using pseudo-multicrab directory %s" % ( ShellStyles.NoteStyle() + opts.mcrab + ShellStyles.NormalStyle()) Verbose(msg, True) # Sanity check: At least one histogram to merge (in that case rename!) if len(opts.dsetsToMerge) < 1: msg = "List of datasets to merge is empty! At least one dataset is required!" raise Exception(ShellStyles.ErrorLabel() + msg + ShellStyles.NormalStyle()) # Sanity check if opts.analysisName == "GenuineB":