def initPdfPlotCfg(self, p): """ [Name, plotOnOpt, argAliasInDB, LegendName] """ pdfPlotTemplate = ["", plotterCfg_styles['allStyle'], None, None] p = p + pdfPlotTemplate[len(p):] if isinstance(p[0], str): self.logger.logDEBUG("Initialize pdfPlot {0}".format(p[0])) p[0] = self.process.sourcemanager.get(p[0]) if p[0] == None: errorMsg = "pdfPlot not found in source manager." self.logger.logERROR(errorMsg) raise RuntimeError("pdfPlot not found in source manager.") args = p[0].getParameters( ROOT.RooArgSet(Bmass, CosThetaK, CosThetaL, Mumumass, Phimass)) if not self.process.cfg['args'].Function_name in ['submit', 'run']: FitterCore.ArgLooper(args, lambda p: p.Print()) if type( p[2] ) is str: # In case ArgAlias is to be defined with string at the end for all args tag = p[2] p[2] = {} arglist = [] FitterCore.ArgLooper(args, lambda p: arglist.append(p.GetName())) for var in arglist: p[2].update({var: var + tag}) if self.process.cfg['args'].NoFit: self.process.cfg['args'].NoImport = True if (not self.process.cfg['args'].NoImport): FitDBPlayer.initFromDB(self.process.dbplayer.odbfile, args, p[2]) if not self.process.cfg['args'].Function_name in ['submit']: FitterCore.ArgLooper(args, lambda p: p.Print()) return p
def _bookMinimizer(self): """_bookMinimizer from StdFitter""" #----------------------------------------------------------------------------------------- import ctypes def myfunc(iArg): lo = ctypes.c_double(0.) hi = ctypes.c_double(1.) self.data.getRange(iArg, lo, hi) iArg.setRange(lo, hi) FitterCore.ArgLooper(self.data.get(), myfunc) try: FitterCore.ArgLooper(self.pdf.getObservables(self.data), myfunc) except AttributeError: print( "Error: PDF '{}' not found. Please make sure you have generated mentioned pdf in RooWorkspaces stored in './input' folder" .format(self.cfg['pdf'])) exit() #----------------------------------------------------------------------------------------- self.fitter = ROOT.StdFitter() for opt in self.cfg.get("createNLLOpt", []): self.fitter.addNLLOpt(opt) minuit = self.fitter.Init(self.pdf, self.data) #minuit.setLogFile(self.name+'_minimizer.log') minuit.setStrategy(2) self._nll = self.fitter.GetNLL()
def FitMinos(self): """Minos""" if len(self.cfg['FitMinos']) > 1 and self.cfg['FitMinos'][1]: par = ROOT.RooArgSet() FitterCore.ArgLooper(self.args, lambda var: par.add(var), self.cfg['FitMinos'][1]) else: par = self.args minosResult = self.fitter.FitMinos(par) self.fitResult = FitterCore.GetFitResult(self.name, "StdFitter", minosResult)
def initFromDB(dbfile, args, aliasDict=None, exclude=None): print("""Parameter initialization from db file""") if not os.path.exists(dbfile): print("dbfile doesnot exist..") return if aliasDict is None: aliasDict = {} try: db = shelve.open(dbfile, "r") def initFromDBImp(iArg): argName = iArg.GetName() aliasName = aliasDict.get(argName, argName) if aliasName in db: for setter, getter in FitDBPlayer.funcPair: if setter in ["setMax", "setMin"]: continue getattr(iArg, setter)( *{ 'getErrorHi': (db[aliasName]['getErrorLo'], db[aliasName]['getErrorHi']), 'getErrorLo': (db[aliasName]['getErrorLo'], db[aliasName]['getErrorHi']), }.get(getter, (db[aliasName][getter],)) ) else: print("WARNING\t: Unable to initialize {0}, record {1} not found in {2}.".format(argName, aliasName, dbfile)) FitterCore.ArgLooper(args, initFromDBImp, exclude, inverseSel=True) print ("Initialized parameters from `{0}`.".format(dbfile)) finally: db.close()
def _runSetsLoop_SimFit(self): iSet=0 #Total subsamples rSet=0 #Converged subsamples cwd = self.process.work_dir #Avoid using os.getcwd() which gives problems in condor jobs while rSet < max(self.cfg['nSetOfToys'], self.process.cfg['args'].nSetOfToys): print(">>>> Running for sub-sample number:", iSet+1) self._preRunFitSteps(iSet) self.fitter.hookProcess(self.process) self.fitter.customize() self.BookSimData(iSet, self.fitter._bookPdfData)() if self.proceedFlag==False: self.proceedFlag=True print(">> Got negative expected entries. Subsample is Flagged Bad") continue if not self.process.cfg['args'].NoFit: self.fitter._bookMinimizer() self.fitter._preFitSteps() #To keep signal and background yields floating self.fitter.ToggleConstVar(self.fitter.minimizer.getParameters(self.fitter.dataWithCategories), False, self.fitter.cfg['argPattern']) self.fitter._runFitSteps(); #self.fitter.minosResult = self.fitter.fitter.FitMinos(self.fitter.data[-1].get()) self._postRunFitSteps(iSet) #Remove a year tag from parameters for pdf, data, Year in zip(self.fitter.pdf, self.fitter.data, self.fitter.Years): FitterCore.ArgLooper(pdf.getParameters(data), lambda p: p.SetName(p.GetName().split("_{0}".format(Year))[0]), targetArgs=self.fitter.cfg['argPattern'], inverseSel=True) iSet += 1 if (self.treeContent.status==0 and self.treeContent.hesse==0 and self.treeContent.covQual==3) or (self.process.cfg['args'].NoFit): rSet += 1 self.fitter.reset() print(">>>> Successful sub-samples:", rSet, "Failed sub-samples:", iSet-rSet) print("Failed subsamples: ", iSet-rSet)
def UpdateToDB(dbfile, args, aliasDict=None): """Update fit result to a db file""" if aliasDict is None: aliasDict = {} try: db = shelve.open(dbfile, writeback=True) if isinstance(args, dict): modified_args = {} for key, val in args.items(): aliasName = aliasDict.get(key, key) modified_args[aliasName] = val db.update(modified_args) elif args.InheritsFrom("RooArgSet"): def updateToDBImp(iArg): argName = iArg.GetName() aliasName = aliasDict.get(argName, argName) if aliasName not in db: db[aliasName] = {} for setter, getter in FitDBPlayer.funcPair: try: db[aliasName][getter] = getattr(iArg, getter)() except AttributeError: # In case of no getError for RooNLLVar and so on. pass FitterCore.ArgLooper(args, updateToDBImp) else: raise ValueError("Input arguement of type {0} is not supported".format(type(args))) finally: db.close() print("Updated to Database `{0}`.".format(dbfile))
def _runFitSteps(self): """Standard fitting procedure to be overwritten.""" #FitterCore.ArgLooper(self.minimizer.getParameters(self.dataWithCategories), lambda p: p.Print()) #Print all parameters if len(self.cfg['fitToCmds']) == 0: self.minimizer.fitTo(self.dataWithCategories) else: if False: for cmd in self.cfg['fitToCmds']: mresult = self.minimizer.fitTo(self.dataWithCategories, *cmd, ROOT.RooFit.SumW2Error(0), ROOT.RooFit.Save(1)) self.migradResult = mresult.status() self.hesseResult = mresult.status() self._nll = mresult.minNll() else: print(">> Standard Fitter Begin") self.fitter = ROOT.StdFitter() minuit = self.fitter.Init(self.minimizer, self.dataWithCategories) minuit.setStrategy(3) mresult = self.fitter.FitMigrad() hresult = self.fitter.FitHesse() self._nll = self.fitter.GetNLL().getVal() self.fitter.fitResult = FitterCore.GetFitResult( self.name, "StdFitter", hresult)
def fluctuateFromDB(dbfile, args, aliasDict=None): """ Flucturate certain args from db dbfile""" if not os.path.exists(dbfile): return if aliasDict is None: aliasDict = {} try: db = shelve.open(dbfile) gaus = ROOT.TF1("gaus", "exp(-0.5*x**2)", -3, 3) def flucturateFromDBImp(iArg): argName = iArg.GetName() aliasName = aliasDict.get(argName, argName) if aliasName in db: significance = gaus.GetRandom() arg = db[aliasName] if significance > 0: iArg.setVal(min(arg['getMax'], arg['getVal'] + significance * (arg['getErrorHi'] if math.fabs(arg['getErrorHi']) > 1e-5 else arg['getError']))) else: iArg.setVal(max(arg['getMin'], arg['getVal'] + significance * (arg['getErrorLo'] if math.fabs(arg['getErrorLo']) > 1e-5 else arg['getError']))) else: print("ERROR\t: Unable to fluctuate {0}, record not found in {1}.".format(aliasName, dbfile)) FitterCore.ArgLooper(args, flucturateFromDBImp) finally: db.close()
def FitMigrad(self): """Migrad""" migradResult = self.fitter.FitMigrad() migradResult = self.fitter.FitMigrad() self.fitResult = FitterCore.GetFitResult(self.name, "StdFitter", migradResult) print("Migrad Result: ", self.fitResult)
def readAll(iArgs): def bookOne(arg): argName = arg.GetName() if argName in self.process.sourcemanager: self.cfg['source'][argName] = self.process.sourcemanager.get(argName) else: self.cfg['source'][argName+".{0}".format(str(self.process.cfg['args'].Year))] = arg FitterCore.ArgLooper(iArgs, bookOne)
def readAll(iArgs): def bookOne(arg): argName = arg.GetName() if argName in self.process.sourcemanager: self.cfg['source'][argName] = self.process.sourcemanager.get(argName) else: self.cfg['source'][argName] = arg FitterCore.ArgLooper(iArgs, bookOne)
def wrapped_f(self): func(self) targetParams = ROOT.RooArgSet() def setParamsToFluc(arg): if arg.GetName() in parList: targetParams.add(arg) FitterCore.ArgLooper(self.params, setParamsToFluc) FitDBPlayer.fluctuateFromDB(self.cfg['db'].format(binLabel=q2bins[self.process.cfg['binKey']]['label']), targetParams, self.cfg.get('argAliasInDB', []))
def preFitSteps_randEffi(self): self.args = self.pdf.getParameters(self.data) self._preFitSteps_initFromDB() # Fluctuate cross-term correction effiArgs = ROOT.RooArgSet() FitterCore.ArgLooper(self.args, lambda iArg: effiArgs.add(iArg), targetArgs=[r"x\d{1,2}"]) FitDBPlayer.fluctuateFromDB(self.process.dbplayer.odbfile, effiArgs, self.cfg['argAliasInDB']) self._preFitSteps_vetoSmallFs() self._preFitSteps_preFit()
def templateConfig(cls): cfg = FitterCore.templateConfig() cfg.update({ 'name': "EfficiencyFitter", 'data': "effiHistReader.accXrec", 'dataX': "effiHistReader.h_accXrec_fine_ProjectionX", 'dataY': "effiHistReader.h_accXrec_fine_ProjectionY", 'pdf': "effi_sigA", 'pdfX': "effi_cosl", 'pdfY': "effi_cosK", 'updateArgs': True, }) del cfg['createNLLOpt'] return cfg
def _runFitSteps(self): if False: RooList = [ROOT.RooFit.Minimizer("Minuit2"), ROOT.RooFit.Save(1)] for opt in self.cfg.get("createNLLOpt", []): RooList.append(opt) FitResult = self.pdf.fitTo(self.data, *RooList) self.fitResult = FitterCore.GetFitResult(self.name, "StdFitter", FitResult) else: self.FitMigrad() if self.cfg.get('FitHesse', False): self.FitHesse() if self.cfg.get('FitMinos', [False, ()])[0]: self.FitMinos()
def FitMinos(self): """Minos""" if len(self.cfg['FitMinos']) > 1 and self.cfg['FitMinos'][1]: par = ROOT.RooArgSet() FitterCore.ArgLooper(self.args, lambda var: par.add(var), self.cfg['FitMinos'][1]) else: par = self.args minosResult = self.fitter.FitMinos(par) self.fitResult.update({ "{0}.{1}".format(self.name, self.cfg['argAliasInDB'].get('minos', 'minos')): { 'status': minosResult.status(), 'nll': minosResult.minNll(), } })
def templateConfig(cls): cfg = FitterCore.templateConfig() cfg.update({ 'name': "StdFitter", 'data': "dataReader.Fit", 'pdf': "f", 'FitHesse': True, 'FitMinos': [True, ()], 'createNLLOpt': [ROOT.RooFit.Extended(1), ], 'argPattern': [r'^.+$', ], 'argAliasInDB': {}, 'saveToDB': True, 'argAliasSaveToDB': True, }) return cfg
def _preFitSteps(self): """Rename parameter names and import values from database""" for pdf, data, Year in zip(self.pdf, self.data, self.Years): args = pdf.getParameters( ROOT.RooArgSet(CosThetaK, CosThetaL, Bmass)) odbfile = os.path.join(self.process.cwd, "plots_{0}".format(Year), self.process.dbplayer.odbfile) if not self.process.cfg['args'].NoImport: FitDBPlayer.initFromDB(odbfile, args, aliasDict=self.cfg['argAliasInDB']) self.ToggleConstVar(args, True) self.ToggleConstVar(args, False, self.cfg['argPattern']) # Rename parameter names FitterCore.ArgLooper( args, lambda p: p.SetName(p.GetName() + "_{0}".format(Year)), targetArgs=self.cfg['argPattern'], inverseSel=True)
def FitHesse(self): """Hesse""" hesseResult = self.fitter.FitHesse() self.fitResult = FitterCore.GetFitResult(self.name, "StdFitter", hesseResult)
def plotPostfitBLK(self, pltName, dataReader, pdfPlots): """Specification of plotSimpleBLK for post-fit plots""" for pIdx, plt in enumerate(pdfPlots): pdfPlots[pIdx] = self.initPdfPlotCfg(plt) # Calculate normalization and then draw args = pdfPlots[0][0].getParameters( ROOT.RooArgSet(Bmass, CosThetaK, CosThetaL)) nSigDB = args.find('nSig').getVal() nSigErrorDB = args.find('nSig').getError() nBkgCombDB = args.find('nBkgComb').getVal() nBkgCombErrorDB = args.find('nBkgComb').getError() flDB = unboundFlToFl(args.find('unboundFl').getVal()) afbDB = unboundAfbToAfb(args.find('unboundAfb').getVal(), flDB) sigFrac = {} bkgCombFrac = {} for regionName in ["Fit", "SR", "LSB", "USB", "SB", "innerSB", "outerSB"]: dataPlots = [ [ "{0}.{1}".format(dataReader, regionName), plotterCfg_dataStyle, "Data" ], ] for pIdx, p in enumerate(dataPlots): dataPlots[pIdx] = self.initDataPlotCfg(p) # Bind the 'Bmass' defined in PDF with 'getObservables' to createIntegral obs = pdfPlots[1][0].getObservables(dataPlots[0][0]) FitterCore.ArgLooper( obs, lambda p: p.setRange(regionName, *bMassRegions[regionName][ 'range']), ["Bmass"]) sigFrac[regionName] = pdfPlots[1][0].createIntegral( obs, ROOT.RooFit.NormSet(obs), ROOT.RooFit.Range(regionName)).getVal() obs = pdfPlots[2][0].getObservables(dataPlots[0][0]) FitterCore.ArgLooper( obs, lambda p: p.setRange(regionName, *bMassRegions[regionName][ 'range']), ["Bmass"]) bkgCombFrac[regionName] = pdfPlots[2][0].createIntegral( obs, ROOT.RooFit.NormSet(obs), ROOT.RooFit.Range(regionName)).getVal() if regionName in ["SB", "innerSB"]: sigFrac[regionName] -= sigFrac['SR'] bkgCombFrac[regionName] -= bkgCombFrac['SR'] elif regionName == "outerSB": sigFrac[regionName] -= sigFrac['SR'] sigFrac[regionName] -= sigFrac['innerSB'] bkgCombFrac[regionName] -= bkgCombFrac['SR'] bkgCombFrac[regionName] -= bkgCombFrac['innerSB'] nTotal_local = nSigDB * sigFrac[regionName] + nBkgCombDB * bkgCombFrac[ regionName] # print(regionName, sigFrac[regionName], bkgCombFrac[regionName], nTotal_local) # Correct the shape of f_final args.find("nSig").setVal(nSigDB * sigFrac[regionName]) args.find("nBkgComb").setVal(nBkgCombDB * bkgCombFrac[regionName]) modified_pdfPlots = [ [ pdfPlots[0][0], pdfPlots[0][1] + (ROOT.RooFit.Normalization( nTotal_local, ROOT.RooAbsReal.NumEvent), ), None, "Total fit" ], [ pdfPlots[0][0], pdfPlots[1][1] + (ROOT.RooFit.Normalization(nTotal_local, ROOT.RooAbsReal.NumEvent), ROOT.RooFit.Components(pdfPlots[1][0].GetName())), None, "Sigal" ], [ pdfPlots[0][0], pdfPlots[2][1] + (ROOT.RooFit.Normalization(nTotal_local, ROOT.RooAbsReal.NumEvent), ROOT.RooFit.Components(pdfPlots[2][0].GetName())), None, "Background" ], ] plotFuncs = { 'B': { 'func': Plotter.plotFrameB, 'tag': "" }, 'L': { 'func': Plotter.plotFrameL, 'tag': "_cosl" }, 'K': { 'func': Plotter.plotFrameK, 'tag': "_cosK" }, } drawLatexFitResults = False for frame in 'BLK': plotFuncs[frame]['func'](dataPlots=dataPlots, pdfPlots=modified_pdfPlots) if drawLatexFitResults: if frame == 'B': Plotter.latex.DrawLatexNDC(.19, .77, "Y_{Signal}") Plotter.latex.DrawLatexNDC( .35, .77, "= {0:.2f}".format(nSigDB * sigFrac[regionName])) Plotter.latex.DrawLatexNDC( .50, .77, "#pm {0:.2f}".format(nSigErrorDB * sigFrac[regionName])) Plotter.latex.DrawLatexNDC(.19, .70, "Y_{Background}") Plotter.latex.DrawLatexNDC( .35, .70, "= {0:.2f}".format(nBkgCombDB * bkgCombFrac[regionName])) Plotter.latex.DrawLatexNDC( .50, .70, "#pm {0:.2f}".format( nBkgCombErrorDB * bkgCombFrac[regionName])) elif frame == 'L': Plotter.latex.DrawLatexNDC( .19, .77, "A_{{FB}} = {0:.2f}".format(afbDB)) elif frame == 'K': Plotter.latex.DrawLatexNDC( .19, .77, "F_{{L}} = {0:.2f}".format(flDB)) Plotter.latexQ2(self.process.cfg['binKey']) self.canvasPrint(pltName + '_' + regionName + plotFuncs[frame]['tag'])
def _preFitSteps(self): """Prefit uncorrelated term""" args = self.pdf.getParameters(self.data) if not self.process.cfg['args'].NoImport: FitDBPlayer.initFromDB(self.process.dbplayer.odbfile, args) self.ToggleConstVar(args, isConst=True) # Disable xTerm correction and fit to 1-D args.find('hasXTerm{}'.format(self.cfg['label'])).setVal(0) h_accXrec_fine_ProjectionX = self.process.sourcemanager.get( self.cfg['dataX']) h_accXrec_fine_ProjectionY = self.process.sourcemanager.get( self.cfg['dataY']) effi_cosl = self.process.sourcemanager.get(self.cfg['pdfX']) effi_cosK = self.process.sourcemanager.get(self.cfg['pdfY']) for proj, pdf, var, argPats in [ (h_accXrec_fine_ProjectionX, effi_cosl, CosThetaL, [r"^l\d+\w*"]), (h_accXrec_fine_ProjectionY, effi_cosK, CosThetaK, [r"^k\d+\w*"]) ]: hdata = ROOT.RooDataHist("hdata", "", ROOT.RooArgList(var), ROOT.RooFit.Import(proj)) self.ToggleConstVar(args, isConst=False, targetArgs=argPats) theList = ROOT.RooLinkedList() Err = ROOT.RooFit.Minos(True) theSave = ROOT.RooFit.Save() #Python discards temporary objects Verbose = ROOT.RooFit.Verbose(0) Strategy = ROOT.RooFit.Strategy(2) PrintLevel = ROOT.RooFit.PrintLevel(-1) theList.Add(theSave) theList.Add(Verbose) theList.Add(PrintLevel) theList.Add(Err) theList.Add(Strategy) Res = pdf.chi2FitTo(hdata, theList) Res = pdf.chi2FitTo(hdata, theList) Res.Print("v") FitDBPlayer.UpdateToDB( self.process.dbplayer.odbfile, FitterCore.GetFitResult(self.name, var.GetName(), Res)) ################## AlTernatively ####################### #chi2 = pdf.createChi2(hdata, ROOT.RooFit.Save(1)) #m=ROOT.RooMinuit(chi2) #m.setPrintLevel(3) #m.migrad() #m.hesse() #m.minos() #RooRes=m.save() self.ToggleConstVar(args, isConst=True, targetArgs=argPats) effi_norm = 'effi_norm{}'.format(self.cfg['label']) args.find('hasXTerm{}'.format(self.cfg['label'])).setVal(1) args.find(effi_norm).setConstant(False) Res2D = self.pdf.chi2FitTo(self.data, ROOT.RooFit.Minos(True), ROOT.RooFit.Save(), ROOT.RooFit.Strategy(2), ROOT.RooFit.PrintLevel(-1)) Res2D.Print() #args.find(effi_norm).setVal(args.find(effi_norm).getVal() / 4.) args.find(effi_norm).setConstant(True) # Fix uncorrelated term and for later update with xTerms in main fit step self.ToggleConstVar(args, isConst=False, targetArgs=[r"^x\d+\w*"])
def _runFitSteps(self): h2_accXrec = self.process.sourcemanager.get(self.cfg['datahist']) args = self.pdf.getParameters(self.data) nPar = 0 floaters = {} #Saving indices for cross terms def GetTFunction(): nonlocal nPar args_it = args.createIterator() arg = args_it.Next() effi_sigA_formula = self.pdf.formula().formulaString() paramDict = {} for p in range(self.pdf.formula().actualDependents().getSize()): paramDict[self.pdf.formula().getParameter(p).GetName()] = p effi_sigA_formula = effi_sigA_formula.replace( "x[{0}]".format(paramDict['CosThetaL']), "x") effi_sigA_formula = effi_sigA_formula.replace( "x[{0}]".format(paramDict['CosThetaK']), "y") while arg: if any( re.match(pat, arg.GetName()) for pat in ["effi_norm", "hasXTerm", r"^l\d+\w*", r"^k\d+\w*"]): effi_sigA_formula = effi_sigA_formula.replace( 'x[{0}]'.format(paramDict[arg.GetName()]), "({0})".format(arg.getVal())) elif re.match(r"^x\d+\w*$", arg.GetName()): effi_sigA_formula = effi_sigA_formula.replace( 'x[{0}]'.format(paramDict[arg.GetName()]), "[{0}]".format(nPar)) floaters[nPar] = arg.GetName() nPar = nPar + 1 arg = args_it.Next() f2_effi_sigA = ROOT.TF2("f2_effi_sigA", effi_sigA_formula, -1, 1, -1, 1) return f2_effi_sigA if True: #Using RooMinuit if False: #Using {} optimization fitter = ROOT.StdFitter() minuit = fitter.Init(self.pdf, self.data) minuit.setStrategy(2) minuit.optimizeConst(1) minuit.setPrintLevel(0) self._nll = fitter.GetNLL() self.fitter = fitter.FitMigrad() self.fitter = fitter.FitHesse() self.fitter = fitter.FitMinos( self.pdf.getParameters(self.data).selectByAttrib( "Constant", 0)) else: #Using chi2 optimization self.fitter = self.pdf.chi2FitTo(self.data, ROOT.RooFit.Minos(1), ROOT.RooFit.Strategy(2), ROOT.RooFit.Save(1), ROOT.RooFit.PrintLevel(-1)) self.fitter = self.pdf.chi2FitTo(self.data, ROOT.RooFit.Minos(1), ROOT.RooFit.Strategy(2), ROOT.RooFit.Save(1), ROOT.RooFit.PrintLevel(-1)) self.fitter.Print("v") FitDBPlayer.UpdateToDB( self.process.dbplayer.odbfile, FitterCore.GetFitResult(self.name, "XTerm", self.fitter)) setStyle() canvas = ROOT.TCanvas() latex = ROOT.TLatex() h2_effi_2D_comp = h2_accXrec.Clone("h2_effi_2D_comp") h2_effi_2D_comp.Reset("ICESM") pdfhist = h2_accXrec.Clone("pdfhist") pdfhist.Reset("ICESM") self.pdf.fillHistogram(pdfhist, ROOT.RooArgList(CosThetaL, CosThetaK)) #Text plot comparison canvas2 = ROOT.TCanvas() for lBin, KBin in itertools.product( list(range(1, h2_effi_2D_comp.GetNbinsX() + 1)), list(range(1, h2_effi_2D_comp.GetNbinsY() + 1))): if h2_accXrec.GetBinContent(lBin, KBin) == 0: h2_effi_2D_comp.SetBinContent(lBin, KBin, 0) print(">> ** Warning ** Empty bins: (l, k)", lBin, KBin) else: h2_effi_2D_comp.SetBinContent( lBin, KBin, pdfhist.GetBinContent(lBin, KBin) / h2_accXrec.GetBinContent(lBin, KBin)) ROOT.gStyle.SetPalette( ROOT.kLightTemperature) #kColorPrintableOnGrey) h2_effi_2D_text = h2_effi_2D_comp.Clone( "h2_effi_2D_text") #; h2_effi_2D_text.Reset("ICESM") h2_effi_2D_text.Draw("COLZ") h2_effi_2D_text.GetYaxis().SetTitleOffset(1) ROOT.gStyle.SetPaintTextFormat("6.4g") pdfhist.SetBarOffset(0.25) pdfhist.Draw("TEXT SAME") canvas2.SetRightMargin(0.115) canvas2.SetLeftMargin(0.1) h2_accXrec.SetBarOffset(0.) h2_accXrec.Draw("TEXT SAME") h2_effi_2D_comp.SetBarOffset(-0.25) h2_effi_2D_comp.Draw("TEXT SAME") ROOT.TLatex().DrawLatexNDC( 0.12, 0.96, r"#scale[0.8]{{{latexLabel}}}".format(latexLabel=q2bins[ self.process.cfg['binKey']]['latexLabel'])) canvas.cd() h2_effi_2D_comp.SetMinimum(0) h2_effi_2D_comp.SetMaximum(1.5) h2_effi_2D_comp.SetTitleOffset(1.6, "X") h2_effi_2D_comp.SetTitleOffset(1.8, "Y") h2_effi_2D_comp.SetTitleOffset(1.5, "Z") h2_effi_2D_comp.SetZTitle( "#varepsilon_{fit}/#varepsilon_{measured}") h2_effi_2D_comp.Draw("LEGO2") latex.DrawLatexNDC( .08, .93, "#font[61]{CMS} #font[52]{#scale[0.8]{Simulation}}") chi2ndf = self.fitter.minNll() / ( h2_effi_2D_comp.GetNbinsX() * h2_effi_2D_comp.GetNbinsY() - self.pdf.getParameters(self.data).selectByAttrib( "Constant", 0).getSize()) latex.DrawLatexNDC(.08, .89, "#chi^{{2}}/ndf={0:.2f}".format(chi2ndf)) print("2D Efficiency Chi^2/ndf: ", chi2ndf) else: #Using TMinuit (This section can be used only if pdf is defined in terms of expression (e.g. RooFormulaVar). Does not work for RooProdPdf or RooProduct) f2_effi_sigA = GetTFunction() fitter = ROOT.EfficiencyFitter() self.minimizer = fitter.Init(nPar, h2_accXrec, f2_effi_sigA) self.minimizer.SetPrintLevel(0) #Pritam self.minimizer.mnexcm("SET STR", ctypes.c_double(2.), 1, ctypes.c_int(0)) for xIdx in range(nPar): self.minimizer.DefineParameter(xIdx, floaters[xIdx], 0., 1E-4, -1E+2, 1E+2) MigStatus = self.minimizer.Migrad() MigStatus = self.minimizer.Migrad() MinosStatus = self.minimizer.Command("MINOS") # Check if efficiency is positive definite f2_max_x, f2_max_y = ctypes.c_double(0.), ctypes.c_double(.0) f2_min_x, f2_min_y = ctypes.c_double(0.), ctypes.c_double(.0) f2_effi_sigA.GetMaximumXY(f2_max_x, f2_max_y) f2_effi_sigA.GetMinimumXY(f2_min_x, f2_min_y) print("Sanitary check: Efficiency ranges from {0:.2e} to {1:.2e}". format(f2_effi_sigA.Eval(f2_min_x, f2_min_y), f2_effi_sigA.Eval(f2_max_x, f2_max_y))) EfficiencyFitter.isPosiDef(f2_effi_sigA) #Update parameter values parVal, parErr = ctypes.c_double(.0), ctypes.c_double(.0) eplus, eminus, eparab, gcc = ctypes.c_double(0.), ctypes.c_double( 0.), ctypes.c_double(.0), ctypes.c_double(0.) for xIdx in range(nPar): self.minimizer.GetParameter(xIdx, parVal, parErr) self.minimizer.mnerrs(xIdx, eplus, eminus, eparab, gcc) arg = args.find(floaters[xIdx]) arg.setVal(parVal.value) arg.setError(parErr.value) arg.setAsymError(eplus.value, eminus.value) # Plot comparison between fitting result to data setStyle() canvas = ROOT.TCanvas() latex = ROOT.TLatex() h2_effi_2D_comp = h2_accXrec.Clone("h2_effi_2D_comp") h2_effi_2D_comp.Reset("ICESM") pdfhist = h2_accXrec.Clone("pdfhist") pdfhist.Reset("ICESM") self.pdf.fillHistogram(pdfhist, ROOT.RooArgList(CosThetaL, CosThetaK)) print( "2D Efficiency Chi^2/ndf: ", fitter.GetChi2() / (h2_effi_2D_comp.GetNbinsX() * h2_effi_2D_comp.GetNbinsY() - nPar)) print("TMinuit Status: ", self.minimizer.GetStatus(), MigStatus, MinosStatus) #Text plot comparison canvas2 = ROOT.TCanvas() for lBin, KBin in itertools.product( list(range(1, h2_effi_2D_comp.GetNbinsX() + 1)), list(range(1, h2_effi_2D_comp.GetNbinsY() + 1))): if h2_accXrec.GetBinContent(lBin, KBin) == 0: h2_effi_2D_comp.SetBinContent(lBin, KBin, 0) print(">> ** Warning ** Empty bins: (l, k)", lBin, KBin) else: h2_effi_2D_comp.SetBinContent( lBin, KBin, f2_effi_sigA.Eval( h2_accXrec.GetXaxis().GetBinCenter(lBin), h2_accXrec.GetYaxis().GetBinCenter(KBin)) / h2_accXrec.GetBinContent(lBin, KBin)) ROOT.gStyle.SetPalette( ROOT.kLightTemperature) #kColorPrintableOnGrey) h2_effi_2D_text = h2_effi_2D_comp.Clone( "h2_effi_2D_text") #; h2_effi_2D_text.Reset("ICESM") h2_effi_2D_text.Draw("COLZ") h2_effi_2D_text.GetYaxis().SetTitleOffset(1) ROOT.gStyle.SetPaintTextFormat("6.4g") pdfhist.SetBarOffset(0.25) pdfhist.Draw("TEXT SAME") canvas2.SetRightMargin(0.115) canvas2.SetLeftMargin(0.1) h2_accXrec.SetBarOffset(0.) h2_accXrec.Draw("TEXT SAME") h2_effi_2D_comp.SetBarOffset(-0.25) h2_effi_2D_comp.Draw("TEXT SAME") ROOT.TLatex().DrawLatexNDC( 0.12, 0.96, r"#scale[0.8]{{{latexLabel}}}".format(latexLabel=q2bins[ self.process.cfg['binKey']]['latexLabel'])) canvas.cd() h2_effi_2D_comp.SetMinimum(0) h2_effi_2D_comp.SetMaximum(1.5) h2_effi_2D_comp.SetTitleOffset(1.6, "X") h2_effi_2D_comp.SetTitleOffset(1.8, "Y") h2_effi_2D_comp.SetTitleOffset(1.5, "Z") h2_effi_2D_comp.SetZTitle( "#varepsilon_{fit}/#varepsilon_{measured}") h2_effi_2D_comp.Draw("LEGO2") latex.DrawLatexNDC( .08, .93, "#font[61]{CMS} #font[52]{#scale[0.8]{Simulation}}") latex.DrawLatexNDC( .08, .89, "#chi^{{2}}/ndf={0:.2f}".format( fitter.GetChi2() / (h2_effi_2D_comp.GetNbinsX() * h2_effi_2D_comp.GetNbinsY() - nPar))) FitterCore.ArgLooper(args, lambda p: p.Print()) #################################### path = os.path.join(modulePath, self.process.work_dir, "Efficiency") if not os.path.exists(path): os.mkdir(path) os.chdir(path) #################################### canvas.Print("effi_2D_comp{}_{}.pdf".format( self.cfg['label'], q2bins[self.process.cfg['binKey']]['label'])) canvas2.cd() canvas2.Print("effi_2D_TEXT{}_{}.pdf".format( self.cfg['label'], q2bins[self.process.cfg['binKey']]['label'])) os.chdir(os.path.join(modulePath, self.process.work_dir))