Example #1
0
File: plot.py Project: lwezenbe/HNL
    def drawHist(self, output_dir = None, normalize_signal = False, draw_option = 'EHist', bkgr_draw_option = 'Stack', draw_cuts = None, 
        custom_labels = None, draw_lines = None, message = None, min_cutoff = None):

        #
        # Some default settings
        #
        setDefault()

        #
        # Create Canvas and pads
        #
        self.canvas = ROOT.TCanvas("Canv"+self.name, "Canv"+self.name, 1000, 1000)
        self.setPads()
        self.plotpad.Draw()
        self.plotpad.cd()

        #
        # Throw some errors in case of faulty input
        #
        if isinstance(self.x_name, list):
            raise RuntimeError('invalid x_names')

        if custom_labels is not None and len(custom_labels) != self.s[0].GetNbinsX():
            raise RuntimeError("Inconsistent number of bins ("+str(self.s[0].GetNbinsX())+") compared to number of labels given ("+len(custom_labels)+")")

        if draw_option == 'Stack' and len(self.b) > 0:
            raise RuntimeError('The "Stack" option for signal is meant to be used when there is no background. In case of background, input the hist to stack as background.')
        
        #
        # Set Signal Histogram Styles
        #
        for h, n in zip(self.s, self.tex_names):

            # Prepare for stacked signal
            if draw_option == "Stack":
                # Order signals from lowest to highest
                self.s, self.s_tex_names = pt.orderHist(self.s, self.s_tex_names, lowest_first=True)       

                self.hs = ROOT.THStack("hs", "hs")
                for i, (h, n) in enumerate(zip(self.s, self.s_tex_names)):
                    color_index = ps.getPaletteIndex(self.color_palette, self.s.index(h), n)
                    h.SetFillColor(ps.getColor(self.color_palette, color_index))
                    h.SetLineColor(ps.getColor(self.color_palette, color_index))
                    self.hs.Add(h)
            
            # Prepare for very basic signal
            elif draw_option == "HNL":
                # Order signals so those with 0 sum of weights come last and arent skipped (which causes the axis to not be updated)
                self.s, self.s_tex_names = pt.orderHist(self.s, self.s_tex_names)       

                h.SetLineColor(ps.getHNLColor(n))
                h.SetLineWidth(4)

            # Otherwise generic settings
            else:
                # Order signals so those with 0 sum of weights come last and arent skipped (which causes the axis to not be updated)
                self.s, self.s_tex_names = pt.orderHist(self.s, self.s_tex_names)       

                color_index = ps.getPaletteIndex(self.color_palette, self.s.index(h), n)
                h.SetLineColor(ps.getColor(self.color_palette, color_index))
                h.SetLineWidth(4)
                h.SetMarkerStyle(0)
                h.SetMarkerColor(ps.getColor(self.color_palette, color_index))

        #
        # Set Bkgr Histogram Styles
        #
        if len(self.b) > 0:
            self.total_b = self.b[0].Clone('total_bkgr')

            # Generic settings
            for i, (h, n) in enumerate(zip(self.b, self.b_tex_names)):
                color_index = ps.getPaletteIndex(self.color_palette_bkgr, i, n)
                h.SetLineColor(ps.getColor(self.color_palette_bkgr, color_index))
                h.SetLineWidth(3)
                if i != 0:      self.total_b.Add(h)
            
            # Prepare for stacking (Can not conflict with signal stacks due to runtimeError raise at the beginning)
            if bkgr_draw_option == 'Stack':
                self.b, self.b_tex_names = pt.orderHist(self.b, self.b_tex_names, lowest_first = True)
                self.hs = ROOT.THStack("hs", "hs")
                for i, (h, n) in enumerate(zip(self.b, self.b_tex_names)):
                    color_index = ps.getPaletteIndex(self.color_palette_bkgr, i, n)
                    h.SetFillColor(ps.getColor(self.color_palette_bkgr, color_index))
                    self.hs.Add(h)

        self.tex_names = self.s_tex_names + self.b_tex_names

        #
        # Set title (background is drawn first so it gets dibs)
        #
        if self.draw_ratio is not None or self.draw_significance:
            title = " ; ; "+self.y_name
        else:
            title = " ;" +self.x_name+ " ; "+self.y_name   

        if len(self.b) > 0:
            if bkgr_draw_option == 'Stack':
                self.hs.SetTitle(title)
            else:
                self.b[0].SetTitle(title)
        else:
            if draw_option == "Stack":
                self.hs.SetTitle(title)
            else:
                self.s[0].SetTitle(title)


        #
        # Draw background first
        #
        tmp_bkgr_draw_option = bkgr_draw_option.split('E')[-1]
        if len(self.b) > 0:
            if bkgr_draw_option == 'Stack':
                self.hs.Draw("Hist")                                     #Draw before using GetHistogram, see https://root-forum.cern.ch/t/thstack-gethistogram-null-pointer-error/12892/4
                if self.draw_ratio is not None or self.draw_significance: 
                    self.hs.GetHistogram().GetXaxis().SetLabelOffset(9999999)
            else:
                for i, b in enumerate(self.b):
                    if i == 0:
                        b.Draw(tmp_bkgr_draw_option)
                        if self.draw_ratio is not None or self.draw_significance: 
                            b.GetXaxis().SetLabelOffset(9999999)
                    else:
                        b.Draw(tmp_bkgr_draw_option + 'Same')


        #
        # Draw signal
        #
        tmp_draw_option = draw_option.split('E')[-1]

        if draw_option == "Stack":
            self.hs.Draw("Hist")                                           #Draw before using GetHistogram, see https://root-forum.cern.ch/t/thstack-gethistogram-null-pointer-error/12892/4
            if self.draw_ratio is not None or self.draw_significance: 
                self.hs.GetHistogram().GetXaxis().SetLabelOffset(9999999)
        else:
            for ih, h in enumerate(self.s):
                if h.GetSumOfWeights() == 0: continue
                if normalize_signal:
                    if len(self.b) == 0:
                        # raise RuntimeError("Trying to normalize a signal to a nonexisting background in drawHist")
                        #Normalize everything to the first histogram
                        if ih > 0:
                            h.Scale(self.s[0].GetSumOfWeights()/h.GetSumOfWeights())
                    else:
                        h.Scale(self.total_b.GetSumOfWeights()/h.GetSumOfWeights())

                if(self.s.index(h) == 0 and self.b is None):
                    h.Draw(tmp_draw_option)
                else:
                    h.Draw(tmp_draw_option+'Same')

        self.drawErrors(draw_option, bkgr_draw_option)

        #Draw observed
        if self.observed is not None:
            self.observed.SetLineColor(ROOT.kBlack)
            self.observed.SetMarkerColor(ROOT.kBlack)
            self.observed.SetMarkerStyle(8)
            self.observed.SetMarkerSize(1)
            self.observed.Draw("EPSame")


        tdr.setTDRStyle()                       #TODO: Find out why we need a setTDRStyle after drawing the stack

        #
        # Calculate ranges of axis and set to log if requested
        #
        self.setAxisLog(stacked = (len(self.b) > 0 and 'Stack' in bkgr_draw_option) or 'Stack' in draw_option, min_cutoff = min_cutoff)

        #
        # Set custom labels if needed
        #
        if custom_labels is not None and not self.draw_ratio and not self.draw_significance:
            if len(self.b) > 0:
                if bkgr_draw_option == 'Stack':
                    for i, n in enumerate(custom_labels):
                        self.hs.GetHistogram().GetXaxis().SetBinLabel(i+1, n)
                else:
                    for i, n in enumerate(custom_labels):
                        self.b[0].GetXaxis().SetBinLabel(i+1, n)
            else:
                if draw_option == "Stack": 
                    for i, n in enumerate(custom_labels):
                        self.hs.GetHistogram().GetXaxis().SetBinLabel(i+1, n)
                else:
                    for i, n in enumerate(custom_labels):
                        self.s[0].GetXaxis().SetBinLabel(i+1, n)

        #
        # Option only used in plotVariables.py
        #
        if draw_cuts is not None:
            if self.extra_text is None: self.extra_text = []
            lines = []
            i = 0 #Cant use enumerate because of if statement, first filled value might be at i=2 but lines[2] doesnt exist then
            for j, (h, l) in enumerate(zip(self.s, draw_cuts[0])):
                if l is not None:
                    lines.append(ROOT.TLine(l, 0, l, self.s[0].GetMaximum()))
                    lines[i].SetLineColor(self.s[j].GetLineColor())
                    lines[i].SetLineStyle(10)
                    lines[i].SetLineWidth(2)
                    lines[i].Draw('Same')
                    self.extra_text.append(pt.extraTextFormat('p_{T}(l'+str(j+1)+') < '+str(l) +' GeV'))
                    i += 1
            self.extra_text.append(pt.extraTextFormat('Eff: %.4g' % draw_cuts[1]+'%'))

        if draw_lines is not None:
            line_collection = []
            #Multiple lines
            if isinstance(draw_lines[0], list):
                for il, l in enumerate(draw_lines):
                    x0 = l[0] if l[0] is not None else self.overall_min*0.001
                    x1 = l[1] if l[1] is not None else self.overall_max*3000
                    y0 = l[2] if l[2] is not None else self.min_to_set*0.01
                    y1 = l[3] if l[3] is not None else self.max_to_set*300
                    color = l[4] if l[4] is not None else ROOT.kBlack
                    line_collection.append(ROOT.TLine(x0, y0, x1, y1))
                    line_collection[il].SetLineColor(color)
                    line_collection[il].SetLineWidth(l[5])
                    line_collection[il].SetLineStyle(l[6])

            for l in line_collection:
                l.Draw('same')

        #Write extra text
        if self.extra_text is not None:
            self.drawExtraText()

        
        self.canvas.cd()
        #Create Legend
        legend = ROOT.TLegend(0.4, .7, .9, .9)
        legend.SetNColumns(1)
        legend.SetTextSize(.03)
       
        loop_obj = [item for item in self.s]
        if len(self.b) > 0: loop_obj.extend(self.b)
        for h, n in zip(loop_obj, self.tex_names):
            legend.AddEntry(h, n)
        if self.observed is not None:
            legend.AddEntry(self.observed, 'data')

        legend.SetFillStyle(0)
        legend.SetBorderSize(0)
        legend.Draw()

        if self.draw_ratio is not None:
            just_errors = self.draw_ratio == 'errorsOnly'
            if self.b is None:                 raise RuntimeError("Cannot ask ratio or significance if no background is given")
            ratios = self.calculateRatio()
            self.drawRatio(ratios, custom_labels, just_errors)
            self.ratio_pad.Update()
        if self.draw_significance:
            if self.b is None:                 raise RuntimeError("Cannot ask ratio or significance if no background is given")
            significance_lines = []
            for s in self.s:
                significance_lines.append(ROOT.TLine(s.GetBinLowEdge(1), 0, s.GetBinLowEdge(self.s[0].GetNbinsX()+1), 0))
            significances = self.calculateSignificance(cumulative=True)
            self.drawSignificance(significances, custom_labels, significance_lines)
            self.sig_pad.Update()

        ROOT.gPad.Update() 
        self.canvas.Update()
        #CMS lumi
        cl.CMS_lumi(self.canvas, 4, 11, 'Preliminary', self.year)

        #Save everything
        self.savePlot(output_dir +'/'+ self.name, message)
        ROOT.SetOwnership(self.canvas, False)
        return
Example #2
0
def setDefault(paintformat="4.2f"):
    gROOT.SetBatch(True)
    gStyle.SetOptStat(0)
    tdr.setTDRStyle()
    gStyle.SetPaintTextFormat(paintformat)
    gROOT.ProcessLine("gErrorIgnoreLevel = 1001;")
Example #3
0
File: plot.py Project: lwezenbe/HNL
def generalSettings(paintformat = "4.2f"):
    ROOT.gROOT.SetBatch(True)
    ROOT.gStyle.SetOptStat(0)
    tdr.setTDRStyle()
    ROOT.gStyle.SetPaintTextFormat(paintformat)
    ROOT.gROOT.ProcessLine( "gErrorIgnoreLevel = 1001;")