def drawTemplateFitter(tf, canvas = None, trueVal = None) : if not canvas : canvas = r.TCanvas() else: canvas.Clear() canvas.cd(0) canvas.Divide(2,2) #------1 LL = r.TGraph(len(tf.pars), np.array(tf.pars), tf.templatesN2LL) fit = r.TF1("fit","pol3",min(tf.pars),max(tf.pars)) for i,c in enumerate(tf.coefficients) : fit.SetParameter(i,c) xMaxLL = [r.TGraph(2,np.array([val,val]),np.array([min(tf.templatesN2LL),max(tf.templatesN2LL)])) for val in [tf.value,tf.value+tf.error,tf.value-tf.error]] for h in xMaxLL : h.SetLineColor(r.kBlue) if trueVal != None : xMaxLL.append(r.TGraph(2,np.array([trueVal,trueVal]),np.array([min(tf.templatesN2LL),max(tf.templatesN2LL)]))) xMaxLL[-1].SetLineColor(r.kRed) xMaxLL[-1].SetLineWidth(2) xMaxLL[1].SetLineStyle(r.kDashed) xMaxLL[2].SetLineStyle(r.kDashed) LL.SetTitle("best fit: %s | corrected: %s"%(utils.roundString(tf.value,tf.error, noSci=True), utils.roundString(tf.value-tf.bias, tf.error*tf.pull,noSci=True)) + (" | %0.3f"%trueVal if trueVal is not None else "")) canvas.cd(1) LL.Draw('A*') for h in reversed(xMaxLL) : h.Draw('') fit.Draw('same') #------2 n2lls = utils.rHist("-2logLs", *np.histogram([toy.n2LL for toy in tf.ensemble], 100) ) n2ll = n2lls.Clone('-2logL') ; n2ll.Reset(); n2ll.SetBinContent(n2ll.FindFixBin(tf.n2LL), n2lls.GetMaximum()); n2ll.SetFillColor(r.kBlue); n2lls.SetTitle("p-value: %0.4f"%tf.p_value) canvas.cd(2) n2lls.Draw() n2ll.Draw('same') #------3 edges = range(len(tf.observed)+1) observed = utils.rHist("observed", tf.observed, edges, True) spars,stemplates = zip(*sorted(zip(tf.pars,tf.templates))) templates = [utils.rHist("template%d"%i, templ, edges) for i,templ in enumerate(stemplates) if i in [0,len(spars)-1,len(spars)/2]] observed.SetTitle("observed") observed.SetMarkerStyle(20) for i,templ in enumerate(templates) : templ.SetLineColor([r.kRed,r.kGreen,r.kBlue][i]) maxHeight = max(h.GetMaximum() for h in [observed]+templates) for h in [observed]+templates : h.SetMaximum(1.1*maxHeight) canvas.cd(3) observed.Draw() for t in templates : t.Draw("same") #------4 relMean = np.mean(tf.relResiduals) pull = utils.rHist("relative residuals", *np.histogram(tf.relResiduals,100,(relMean-5,relMean+5))) canvas.cd(4) pull.Draw() canvas.Update() return canvas,observed,templates,LL,fit,xMaxLL,n2lls,n2ll,pull
def printSteps(self, steps, printAll=False) : if printAll and len(steps)>self.nLinesMax : self.printSteps(steps[:1-self.nLinesMax],printAll) self.canvas.cd(0) self.canvas.Clear() text = r.TText() text.SetNDC() text.SetTextFont(102) text.SetTextSize(0.45*text.GetTextSize()) pageWidth = 111 nSamples = len(self.someOrganizer.samples) if self.printRatios : nSamples += 1 colWidth = min(25, pageWidth/nSamples) space = 1 nametitle = "{0}: {1:<%d} {2}" % (3+max([len(s.name) for s in steps])) for i,step in enumerate(steps[-self.nLinesMax:]) : absI = i + (0 if len(steps) <= self.nLinesMax else len(steps)-self.nLinesMax) text.SetTextColor(self.rowColors[absI%len(self.rowColors)]) letter = string.ascii_letters[absI] x = 0.01 y = 0.98 - 0.33*(i+0.5+(absI/5) - ((absI-i)/5) )/self.nLinesMax text.DrawTextNDC(x, y, nametitle.format(letter, step.name, step.title )) self.cutDict[letter] = (step.name, step.title) nums = [] ratios = [None]*len(self.samplesForRatios) for k,sample in zip(step.yields,self.someOrganizer.samples) : special = "lumi" in sample and not self.showErrorsOnDataYields s = utils.roundString(*k, width=(colWidth-space), noSci = self.noSci or special, noErr = special) if k else "- " if sample["name"] in self.samplesForRatios : ratios[self.samplesForRatios.index(sample["name"])] = k nums.append(s.rjust(colWidth)) if self.printRatios and len(ratios)==2 : s = "- " if ratios[0] and ratios[1] and ratios[0][0] and ratios[1][0] : value = ratios[0][0]/float(ratios[1][0]) error = value*math.sqrt((ratios[0][1]/float(ratios[0][0]))**2 + (ratios[1][1]/float(ratios[1][0]))**2) ratio = (value, error) s = utils.roundString(*ratio, width=(colWidth-space)) nums.append(s.rjust(colWidth)) text.DrawTextNDC(x, y-0.51, "%s: %s"%(letter, "".join(nums))) self.yieldDict[letter] = nums self.sampleList = [s["name"][:(colWidth-space)].rjust(colWidth) for s in self.someOrganizer.samples] if self.printRatios and len(self.samplesForRatios)==2 : self.sampleList += ("%s/%s"%self.sampleLabelsForRatios)[:(colWidth-space)].rjust(colWidth) text.SetTextColor(r.kBlack) text.DrawTextNDC(x, 0.5, " "+"".join(self.sampleList)) text.SetTextAlign(13) text.DrawTextNDC(0.05, 0.03, "events / %.3f pb^{-1}"% self.someOrganizer.lumi ) self.flushPage()
def drawComponentSolver(cs, canvas = None) : if not canvas : canvas = r.TCanvas() canvas.cd(0) canvas.Divide(2,2) rTemplates = [utils.rHist("template%d"%i,d,range(len(d)+1)) for i,d in enumerate(cs.components)] rObs = utils.rHist("observed",cs.observed,range(len(d)+1),True) rObs.SetTitle("ML fractions: "+", ".join(utils.roundString(f,e,noSci=True) for f,e in zip(cs.fractions,cs.errors) )) nlls = utils.rHist("-logLs", *np.histogram([-toy.logL for toy in cs.ensemble], 100) ) nll = nlls.Clone('-logL') ; nll.Reset(); nll.SetBinContent(nll.FindFixBin(-cs.logL), nlls.GetMaximum()); nll.SetFillColor(r.kBlue); nll.SetTitle("p-value: %0.4f"%cs.p_value) pulls = [ utils.rHist("relative residuals %d"%i, *np.histogram(pull,100,(-5,5))) for i,pull in enumerate(cs.relResiduals.transpose())] corr = cs.correlation corrH = r.TH2D("correlations","correlations", len(corr), -0.5, len(corr)-0.5, len(corr), -0.5, len(corr)-0.5) for i,j in itertools.product(range(len(corr)), repeat = 2) : corrH.SetBinContent(i+1,j+1,round(corr[i][j],3)) corrH.SetMaximum(1) corrH.SetMinimum(-1) canvas.cd(3) corrH.Draw("colztext") stats = [] for i,a,t in zip(range(len(cs.fractions)),pulls,rTemplates) : t.SetFillColor(i+2) t.SetLineColor(i+2) a.SetLineColor(i+2) a.SetMaximum(1.1*max(h.GetMaximum() for h in pulls)) canvas.cd(4); a.Draw("sames" if i else "") canvas.Update() st = a.GetListOfFunctions().FindObject("stats") st.SetOptStat(1101) st.SetLineColor(i+2) st.SetY1NDC(0.85-0.16*i) st.SetY2NDC(1.0-0.16*i) stats.append( st.Clone("stats%d"%i) ) for s in stats : s.Draw() canvas.cd(2) ; nll.Draw(); nlls.Draw("histsame") rObs.SetMarkerStyle(20) def draw(i,logY = False) : canvas.cd(i).SetLogy(logY) rObs.Draw("e") for t in rTemplates : t.Draw("histsame") rObs.Draw("esame") base = utils.rHist("base",cs.base,range(len(cs.base)+1)) ; base.SetFillColor(r.kGray) rTemplates = sorted(rTemplates,key=lambda t: -t.Integral()) + [base] for t,h in reversed(zip(rTemplates[:-1],rTemplates[1:])) : t.Add(h) draw(1, logY = False) #draw(3, logY = True) canvas.Update() return [canvas,rObs,rTemplates,stats,pulls,nlls,nll,corrH]
def printSteps(self, steps, printAll=False) : if printAll and len(steps)>self.nLinesMax : self.printSteps(steps[:1-self.nLinesMax],printAll) self.canvas.cd(0) self.canvas.Clear() text = r.TText() text.SetNDC() text.SetTextFont(102) text.SetTextSize(0.45*text.GetTextSize()) pageWidth = 111 colWidth = min(25, pageWidth/len(self.someOrganizer.samples)) space = 1 nametitle = "{0}: {1:<%d} {2}" % (3+max([len(s.name) for s in steps])) for i,step in enumerate(steps[-self.nLinesMax:]) : absI = i + (0 if len(steps) <= self.nLinesMax else len(steps)-self.nLinesMax) letter = string.ascii_letters[absI] x = 0.01 y = 0.98 - 0.33*(i+0.5+absI/5)/self.nLinesMax text.DrawTextNDC(x, y, nametitle.format(letter, step.name, step.title )) self.cutDict[letter] = (step.name, step.title) nums = [] for k,sample in zip(step.yields,self.someOrganizer.samples) : special = "lumi" in sample and not self.showErrorsOnDataYields s = utils.roundString(*k, width=(colWidth-space), noSci = self.noSci or special, noErr = special) if k else "- " nums.append(s.rjust(colWidth)) text.DrawTextNDC(x, y-0.49, "%s: %s"%(letter, "".join(nums))) self.yieldDict[letter] = nums self.sampleList = [s["name"][:(colWidth-space)].rjust(colWidth) for s in self.someOrganizer.samples] text.DrawTextNDC(x, 0.5, " "+"".join(self.sampleList)) text.SetTextAlign(13) text.DrawTextNDC(0.05, 0.03, "events / %.3f pb^{-1}"% self.someOrganizer.lumi ) self.flushPage()
def printSteps(self, steps, printAll=False) : if printAll and len(steps)>self.nLinesMax : self.printSteps(steps[:1-self.nLinesMax],printAll) self.canvas.cd(0) self.canvas.Clear() text = r.TText() text.SetNDC() text.SetTextFont(102) text.SetTextSize(0.40*text.GetTextSize()) pageWidth = 120 nSamples = len(self.someOrganizer.samples) + len(self.foms) colWidth = min(25, pageWidth/nSamples) space = 1 nametitle = "{0}: {1:<%d} {2}" % (3+max([len(s.name) for s in steps])) for i,step in enumerate(steps[-self.nLinesMax:]) : absI = i + (0 if len(steps) <= self.nLinesMax else len(steps)-self.nLinesMax) text.SetTextColor(self.rowColors[absI%len(self.rowColors)]) letter = string.ascii_letters[absI] x = 0.02 y = 0.98 - 0.34*(i+0.5+(absI/self.rowCycle) - ((absI-i)/self.rowCycle) )/self.nLinesMax nums = [] ratios = [None]*len(self.samplesForRatios) for k,sample in zip(step.yields,self.someOrganizer.samples) : special = "lumi" in sample and not self.showErrorsOnDataYields s = utils.roundString(*k, width=(colWidth-space), noSci = self.noSci or special, noErr = special) if k else "- " if sample["name"] in self.samplesForRatios : ratios[self.samplesForRatios.index(sample["name"])] = k nums.append(s.rjust(colWidth)) if len(ratios)==2 and ratios[0] and ratios[1]: num = float(ratios[0][0]) den = float(ratios[1][0]) numUnc = float(ratios[0][1]) denUnc = float(ratios[1][1]) for fom in self.foms: s = "- " if num and den: value = fom["value"](num, den) error = value*fom["uncRel"](num, den, numUnc, denUnc) s = utils.roundString(value, error, width=(colWidth-space)) nums.append(s.rjust(colWidth)) if step.name in ['master','label']: self.pdfOptions = step.title if step.name=='label' : text.SetTextColor(r.kBlack) font = text.GetTextFont() text.SetTextFont(62) label = "[ %s ]"%step.title text.DrawTextNDC(0.01, y, label) text.DrawTextNDC(0.01, y-0.51, label ) text.SetTextFont(font) else: text.DrawTextNDC(x, y-0.00, nametitle.format(letter, step.name, step.title )) text.DrawTextNDC(x, y-0.51, "%s: %s"%(letter, "".join(nums))) self.cutDict[letter] = (step.name, step.title) self.yieldDict[letter] = nums if absI > self.formerMaxAbsI : text.SetTextColor(r.kBlack) text.DrawTextNDC(0.008,y-0.00,'|') text.DrawTextNDC(0.008,y-0.51,'|') self.formerMaxAbsI = absI self.sampleList = [s["name"][:(colWidth-space)].rjust(colWidth) for s in self.someOrganizer.samples] if len(self.samplesForRatios)==2: for fom in self.foms: self.sampleList += (fom["label"](*self.sampleLabelsForRatios))[:(colWidth-space)].rjust(colWidth) text.SetTextColor(r.kBlack) text.DrawTextNDC(x, 0.5, " "+"".join(self.sampleList)) text.SetTextAlign(13) text.DrawTextNDC(0.05, 0.03, "events / %.0f fb^{-1}" % (self.someOrganizer.lumi/1.0e3) ) self.flushPage()
'''Test the template fitter.''' r.gStyle.SetPalette(1) r.gROOT.SetStyle("Plain") if len(sys.argv)<2 : print "Usage: templateFit [trueParValue=0] [ScaleFactor=100]" truePar = float(sys.argv[1]) if len(sys.argv)>1 else 0 norm = int(sys.argv[2]) if len(sys.argv)>2 else 100 def template(p) : return np.array([100+norm*math.exp(-0.5*(x-p)**2) for x in range(-5,5)]) templates = [(p,template(p)) for p in np.arange(-1.0,1.1,0.1)] observed = np.array([np.random.poisson(mu) for mu in template(truePar)]) TF = templateFitter(observed, *templates) print "true value: ", truePar print "measured : ", utils.roundString(TF.value,TF.error) canvas = drawTemplateFitter(TF) print "p-value :", TF.p_value print "bias : ", TF.bias print "pull : ", TF.pull raw_input() def format(d) : return "[ %s ]"%', '.join("%.3f"%f for f in d) ensembles = templateEnsembles(500, *templates ) print "pars : ".rjust(20), format(ensembles.pars) print "biases : ".rjust(20), format(ensembles.biases) print "pulls : ".rjust(20), format(ensembles.pulls) print "meanErrors : ".rjust(20), format(ensembles.meanError)