Пример #1
0
 def saveas(self, *fnames, **kwargs):
     """Save plot, close canvas and delete the histograms."""
     save = kwargs.get('save', True)
     close = kwargs.get('close', False)
     outdir = kwargs.get('outdir', "")  # output directory
     tag = kwargs.get('tag', "")  # extra tag for output file
     exts = kwargs.get('ext', [])  # [".png"]
     pdf = kwargs.get('pdf', False)
     exts = ensurelist(exts)
     if pdf:
         exts.append(".pdf")
     if not fnames:
         fnames = [self.name + tag]
     if save:
         for fname in fnames:
             fname = os.path.join(
                 outdir,
                 repkey(fname, VAR=self.name, NAME=self.name, TAG=tag))
             if exts:
                 for ext in ensurelist(exts):
                     if not ext.startswith('.'):
                         ext = '.' + ext
                     fname = re.sub(
                         r"\.?(png|pdf|jpg|gif|eps|tiff?|cc?|root)?$", ext,
                         fname, re.IGNORECASE)
                     self.canvas.SaveAs(fname)
             elif not any(fname.lower().endswith('.' + e) for e in [
                     'png', 'pdf', 'jpg', 'gif', 'eps', 'tif', 'tiff', 'c',
                     'root'
             ]):
                 self.canvas.SaveAs(fname + ".png")
             else:
                 self.canvas.SaveAs(fname)
     if close:
         self.close()
Пример #2
0
 def ls(self, *paths, **kwargs):
     """List contents of given directory."""
     verb = kwargs.get('verb', self.verbosity)
     dryrun = kwargs.get('dry', False)
     here = kwargs.get('here', False)
     lscol = kwargs.get('lscol', self.lscol)
     filters = ensurelist(
         kwargs.get('filter', [])
     )  # inclusive filters with glob pattern, like '*' or '[0-9]' wildcards
     path = self.expandpath(*paths, here=here)
     retlist = self.execute("%s %s%s" % (self.lscmd, self.lsurl, path),
                            fatal=False,
                            dry=dryrun,
                            verb=verb)
     delim = '\r\n' if '\r\n' in retlist else '\n'
     retlist = retlist.split(delim)
     if isinstance(lscol, int):
         retlist = [l.split(' ')[lscol] for l in retlist]
     if retlist and 'No such file or directory' in retlist[0]:
         LOG.warning(retlist[0])
         retlist = []
     elif filters:
         for file in retlist[:]:
             if not any(fnmatch(file, f) for f in filters):
                 retlist.remove(file)
     return retlist
Пример #3
0
def grouphists(hists,searchterms,name=None,title=None,**kwargs):
  """Group histograms in a list corresponding to some searchterm, return their sum.
  E.g. grouphists(hists,['TT','ST'],'Top')
       grouphists(hists,['WW','WZ','ZZ'],'Diboson')"""
  verbosity   = LOG.getverbosity(kwargs)
  searchterms = ensurelist(searchterms)
  replace     = kwargs.get('replace',   False ) # replace grouped histograms with sum in list
  close       = kwargs.get('close',     False ) # close grouped histograms
  kwargs['verb'] = verbosity-1
  matches     = gethist(hists,*searchterms,warn=False,**kwargs) if searchterms else hists
  histsum     = None
  if matches:
    if title==None:
      title   = matches[0].GetTitle() if name==None else name
    if name==None:
      name    = matches[0].GetName()
    histsum   = matches[0].Clone(name)
    histsum.SetTitle(title)
    for hist in matches[1:]:
      histsum.Add(hist)
    LOG.verb("grouphists: Grouping %s into %r"%(quotestrs(h.GetName() for h in matches),name),verbosity,2)
    if replace:
      hists.insert(hists.index(matches[0]),histsum)
      for hist in matches:
        hists.remove(hist)
        if close:
          deletehist(hist)
  else:
    LOG.warning("gethist: Did not find a histogram with searchterms %s..."%(quotestrs(searchterms)))
  return histsum
Пример #4
0
 def setlinestyle(self, hists, **kwargs):
     """Set the line style for a list of histograms."""
     verbosity = LOG.getverbosity(self, kwargs)
     pair = kwargs.get('pair', False)
     triple = kwargs.get('triple', False)
     colors = kwargs.get('color', None)
     colors = kwargs.get('colors', colors) or self.lcolors
     style = kwargs.get('style', True)
     styles = style if islist(style) else None
     styles = kwargs.get('styles', styles) or self.lstyles
     width = kwargs.get('width', 2)
     offset = kwargs.get('offset', 0)
     mstyle = kwargs.get('mstyle', None)
     styles = ensurelist(styles)
     LOG.verb(
         "Plot.setlinestyle: width=%s, colors=%s, styles=%s" %
         (width, colors, styles), verbosity, 2)
     if mstyle == None:
         mstyle = triple or pair
     for i, hist in enumerate(hists):
         hist.SetFillStyle(0)
         if triple:
             hist.SetLineColor(colors[(i // 3) % len(colors)])
             hist.SetLineStyle(styles[i % 3])
             hist.SetMarkerSize(0.6)
             hist.SetMarkerColor(hist.GetLineColor() + 1)
         elif pair:
             hist.SetLineColor(colors[(i // 2) % len(colors)])
             hist.SetLineStyle(styles[i % 2])
             hist.SetMarkerColor(hist.GetLineColor() + 1)
             if i % 2 == 1: hist.SetMarkerSize(0.6)
             else: hist.SetMarkerSize(0.0)
         else:
             hist.SetLineColor(colors[i % len(colors)])
             hist.SetMarkerSize(0.6)
             hist.SetMarkerColor(hist.GetLineColor() + 1)
             if style:
                 if isinstance(style, bool):
                     hist.SetLineStyle(styles[i % len(styles)])
                 else:
                     hist.SetLineStyle(style)
         hist.SetLineWidth(width)
         if triple and i % 3 == 2:
             hist.SetOption('E1')
             #hist.SetLineWidth(0)
             hist.SetLineStyle(kSolid)
             hist.SetLineColor(hist.GetMarkerColor())
         elif not mstyle:
             hist.SetMarkerSize(0)
Пример #5
0
 def ls(self,*paths,**kwargs):
   """List contents of given directory."""
   verb    = kwargs.get('verb',self.verbosity)
   dryrun  = kwargs.get('dry', False)
   filters = ensurelist(kwargs.get('filter',[ ]))  # inclusive filters with glob pattern, like '*' or '[0-9]' wildcards
   path    = self.expandpath(*paths)
   retlist = self.execute("%s %s%s"%(self.lscmd,self.lsurl,path),fatal=False,dry=dryrun,verb=verb).split('\n')
   if retlist and 'No such file or directory' in retlist[0]:
     LOG.warning(retlist[0])
     retlist = [ ]
   elif filters:
     for file in retlist[:]:
       if not any(fnmatch(file,f) for f in filters):
         retlist.remove(file)
   return retlist
Пример #6
0
def comparevars(file, variable, processes, systag, **kwargs):
    """Compare up/down variations of input histograms from ROOT file.
       file:      TFile or TDirectory object
       variable:  Variables object
       processes: list of strings (name of processes)
       systag:    string of systematic (file must contain up/down variation)
     e.g.
       comparevars(file,variable,['ZTT','TTT'],'TES')
  """
    text = kwargs.get('text', None)
    pname = kwargs.get('pname', "stack.png")
    tag = kwargs.get('tag', "")
    groups = kwargs.get('group', [])  # e.g. [(['^TT','ST'],'Top')]
    dname = kwargs.get('dname', None)  # directory ('bin') name
    pname = kwargs.get('save', "plot_$PROC$SYST$TAG.png")  # save as image file
    wname = kwargs.get('write', "plot_$PROC$SYST$TAG")  # write to file
    processes = ensurelist(processes)
    uptag = systag + "Up"
    downtag = systag + "Down"
    tdir = ensureTDirectory(file, dname, cd=True) if dname else file
    for process in processes:
        hists = []
        skip = False
        for var in [uptag, "", downtag]:
            hname = process + var
            hist = gethist(tdir, hname, fatal=False, warn=False)
            if not hist:
                skip = True
                break
            hists.append(hist)
        if skip:
            LOG.warning(
                "comparevars: Could not find %r in %s. Skipping shape comparison..."
                % (hname, tdir.GetPath()))
            continue
        plot = Plot(variable, hists)
        plot.draw(ratio=2, lstyle=1)
        plot.drawlegend()
        if text:
            plot.drawtext(text)
        if pname:
            pname_ = repkey(pname, PROC=process, TAG=tag)
            plot.saveas(pname_, ext=['png'])
        if wname:
            wname_ = repkey(wname, PROC=process, TAG=tag)
            plot.canvas.Write(wname_, TH1.kOverwrite)
        plot.close()
Пример #7
0
def writetemplate(templatename,outfilename,sublist=[],rmlist=[],applist=[],**kwargs):
  """Write file from template."""
  sublist = [(re.compile("\$%s(?!\w)"%p),str(v)) for p, v in sublist]
  with open(templatename,'r') as template:
    with open(outfilename,'w') as file:
      for i, line in enumerate(template.readlines()):
        #linenum = "L%d:"%i
        if any(r in line for r in rmlist):
          continue # skip line
        for regexp, value in sublist:
          #pattern = '$'+pattern
          if regexp.search(line):
            #line = line.replace(pattern,str(value))
            line = regexp.sub(value,line)
        file.write(line)
      for line in ensurelist(applist):
        file.write(line+'\n') # append
Пример #8
0
 def getfiles(self,*paths,**kwargs):
   """Get list of files in a given path.
   Return list of files with full path name, and if needed, a file URL.
   Use the 'filter' option to filter the list of file names with some pattern."""
   verb     = kwargs.get('verb',self.verbosity)
   fileurl  = kwargs.get('url', self.fileurl)
   filters  = ensurelist(kwargs.get('filter',[ ])) # inclusive filters with glob pattern, like '*' or '[0-9]' wildcards
   path     = self.expandpath(*paths)
   filelist = self.ls(path,**kwargs)
   if fileurl and path.startswith(self.parent):
     if not isinstance(fileurl,basestring):
       fileurl = self.fileurl
   else:
     fileurl = ""
   for i, file in enumerate(filelist):
     if filters and not any(fnmatch(file,f) for f in filters): continue
     filelist[i] = fileurl+os.path.join(path,file)
   return filelist
Пример #9
0
 def match(self,patterns,verb=0):
   """Match sample name to some (glob) pattern."""
   patterns = ensurelist(patterns)
   sample   = self.name.strip('/')
   match_   = False
   for pattern in patterns:
     if isglob(pattern):
       if fnmatch(sample,pattern+'*'):
         match_ = True
         break
     else:
       if pattern in sample[:len(pattern)+1]:
         match_ = True
         break
   if verb>=2:
     if match_:
       print ">>> Sample.match: '%s' match to '%s'!"%(sample,pattern)
     else:
       print ">>> Sample.match: NO '%s' match to '%s'!"%(sample,pattern)
   return match_
Пример #10
0
def getTGraphRange(graphs, min=+10e10, max=-10e10, margin=0.0, axis='y'):
    """Get full y-range of a given TGraph object."""
    vmin, vmax = min, max
    graphs = ensurelist(graphs)
    if axis == 'y':
        getUp = lambda g, i: y + graph.GetErrorYhigh(i)
        getLow = lambda g, i: y - graph.GetErrorYlow(i)
    else:
        getUp = lambda g, i: x + graph.GetErrorXhigh(i)
        getLow = lambda g, i: x - graph.GetErrorXlow(i)
    for graph in graphs:
        npoints = graph.GetN()
        x, y = Double(), Double()
        for i in xrange(0, npoints):
            graph.GetPoint(i, x, y)
            vup = getUp(graph, i)
            vlow = getLow(graph, i)
            if vup > vmax: vmax = vup
            if vlow < vmin: vmin = vlow
    if margin > 0:
        range = vmax - vmin
        vmax += range * margin
        vmin -= range * margin
    return (vmax, vmax)
Пример #11
0
    def drawlegend(self, position=None, **kwargs):
        """Create and draw legend.
    Legend position can be controlled in several ways
      drawlegend(position)
      drawlegend(position=position)
    where position is a string which can contain the horizontal position, e.g.
      'left', 'center', 'right', 'L', 'C', 'R', 'x=0.3', ...
    where 'x' is the position (between 0 an 1) of the left side in the frame.
    The position string can also contain the vertical position as e.g.
      'top', 'middle', 'bottom', 'T', 'M', 'B', 'y=0.3', ...
    where 'y' is the position (between 0 an 1) of the top side in the frame.
    Instead of the strings, the exact legend coordinates can be controlled with
    the keywords x1, x2, y1 and y2, or, x1, y1, width and height:
      drawlegend(x1=0.2,width=0.4)
      drawlegend(x1=0.2,width=0.4,y1=0.9,height=0.4)
      drawlegend(x1=0.2,x2=0.6,y1=0.9,y2=0.4)
    These floats are normalized to the axis frame, ignoring the canvas margins:
    x=0 is the left, x=1 is the right, y=0 is the bottom and y=1 is the top side.
    Values less than 0, or larger than 1, will put the legend outside the frame.
    """
        #if not ratio:
        #  tsize *= 0.80
        #  signaltsize *= 0.80
        verbosity = LOG.getverbosity(self, kwargs)
        hists = self.hists
        errstyle = 'lep' if gStyle.GetErrorX() else 'ep'
        entries = kwargs.get('entries', [])
        bands = kwargs.get('band', [self.errband])  # error bands
        bands = ensurelist(bands, nonzero=True)
        bandentries = kwargs.get('bandentries', [])
        title = kwargs.get('header', None)
        title = kwargs.get('title', title)  # legend header/title
        latex = kwargs.get('latex',
                           True)  # automatically format strings as LaTeX
        style = kwargs.get('style', None)
        style0 = kwargs.get('style0', None)  # style of first histogram
        errstyle = kwargs.get('errstyle', errstyle)  # style for an error point
        styles = kwargs.get('styles', [])
        position = kwargs.get('pos', position)  # legend position
        position = kwargs.get('position', position) or self.position
        option = kwargs.get('option', '')
        border = kwargs.get('border', False)
        transparent = kwargs.get('transparent', True)
        x1_user = kwargs.get('x1', None)  # legend left side
        x2_user = kwargs.get('x2', None)  # legend right side
        y1_user = kwargs.get('y1', None)  # legend top side
        y2_user = kwargs.get('y2', None)  # legend bottom side
        width = kwargs.get('width', -1)  # legend width
        height = kwargs.get('height', -1)  # legend height
        tsize = kwargs.get('tsize', _lsize)  # text size
        twidth = kwargs.get('twidth',
                            None) or 1  # scalefactor for legend width
        theight = kwargs.get('theight',
                             None) or 1  # scalefactor for legend height
        texts = kwargs.get('text', [])  # extra text below legend
        ncols = kwargs.get('ncols',
                           self.ncols) or 1  # number of legend columns
        colsep = kwargs.get('colsep',
                            0.06)  # seperation between legend columns
        bold = kwargs.get('bold', True)  # bold legend header
        panel = kwargs.get('panel', 1)  # panel (top=1, bottom=2)
        texts = ensurelist(texts, nonzero=True)
        entries = ensurelist(entries, nonzero=False)
        bandentries = ensurelist(bandentries, nonzero=True)
        headerfont = 62 if bold else 42

        # CHECK
        LOG.insist(self.canvas, "Canvas does not exist!")
        self.canvas.cd(panel)
        scale = 485. / min(gPad.GetWh() * gPad.GetHNDC(),
                           gPad.GetWw() * gPad.GetWNDC())
        tsize *= scale  # text size

        # ENTRIES
        #if len(bandentries)==len(bands) and len(entries)>len(hists):
        #  for band, bandtitle in zip(band,bandentries):
        #    entries.insert(hists.index(band),bandtitle)
        while len(entries) < len(hists):
            entries.append(hists[len(entries)].GetTitle())
        while len(bandentries) < len(bands):
            bandentries.append(bands[len(bandentries)].GetTitle())
        hists = hists + bands
        entries = entries + bandentries
        if latex:
            title = maketitle(title)
            entries = [maketitle(e) for e in entries]
            texts = [maketitle(t) for t in texts]
        maxlen = estimatelen([title] + entries + texts)

        # STYLES
        if style0:
            styles[0] = style0
        while len(styles) < len(hists):
            hist = hists[len(styles)]
            if hist in bands:
                styles.append('f')
            elif style != None:
                styles.append(style)
            elif hasattr(hist, 'GetFillStyle') and hist.GetFillStyle() > 0:
                styles.append('f')
            elif 'E0' in hist.GetOption() or 'E1' in hist.GetOption():
                styles.append(errstyle)
            else:
                styles.append('lp')

        # NUMBER of LINES
        nlines = sum([1 + e.count('\n') for e in entries])
        #else:       nlines += 0.80
        if texts: nlines += sum([1 + t.count('\n') for t in texts])
        if ncols > 1: nlines /= float(ncols)
        if title: nlines += 1 + title.count('\n')

        # DIMENSIONS
        if width < 0:
            width = twidth * max(0.22, min(0.60, 0.036 + 0.016 * maxlen))
        if height < 0: height = theight * 1.34 * tsize * nlines
        if ncols > 1: width *= ncols / (1 - colsep)
        x2 = 0.90
        x1 = x2 - width
        y1 = 0.92
        y2 = y1 - height

        # POSITION
        if position == None:
            position = ""
        position = position.replace('left', 'L').replace(
            'center', 'C').replace('right', 'R').replace(  #.lower()
                'top', 'T').replace('middle', 'M').replace('bottom', 'B')
        if not any(c in position for c in 'TMBy'):  # set default vertical
            position += 'T'
        if not any(c in position for c in 'LCRx'):  # set default horizontal
            position += 'RR' if ncols > 1 else 'R'  # if title else 'L'

        if 'C' in position:
            if 'R' in position: center = 0.57
            elif 'L' in position: center = 0.43
            else: center = 0.50
            x1 = center - width / 2
            x2 = center + width / 2
        elif 'LL' in position:
            x1 = 0.03
            x2 = x1 + width
        elif 'L' in position:
            x1 = 0.08
            x2 = x1 + width
        elif 'RR' in position:
            x2 = 0.97
            x1 = x2 - width
        elif 'R' in position:
            x2 = 0.92
            x1 = x2 - width
        elif 'x=' in position:
            x1 = float(re.findall(r"x=(\d\.\d+)", position)[0])
            x2 = x1 + width
        if 'M' in position:
            if 'T' in position: middle = 0.57
            elif 'B' in position: middle = 0.43
            else: middle = 0.50
            y1 = middle - height / 2
            y2 = middle + height / 2
        elif 'TT' in position:
            y2 = 0.97
            y1 = y2 - height
        elif 'T' in position:
            y2 = 0.92
            y1 = y2 - height
        elif 'BB' in position:
            y1 = 0.03
            y2 = y1 + height
        elif 'B' in position:
            y1 = 0.08
            y2 = y1 + height
        elif 'y=' in position:
            y2 = float(re.findall(r"y=(\d\.\d+)", position)[0])
            y1 = y2 - height
        if x1_user != None:
            x1 = x1_user
            x2 = x1 + width if x2_user == None else x2_user
        if y1_user != None:
            y1 = y1_user
            y2 = y1 - height if y2_user == None else y2_user
        L, R = gPad.GetLeftMargin(), gPad.GetRightMargin()
        T, B = gPad.GetTopMargin(), gPad.GetBottomMargin()
        X1, X2 = L + (1 - L - R) * x1, L + (
            1 - L - R) * x2  # convert frame to canvas coordinates
        Y1, Y2 = B + (1 - T - B) * y1, B + (
            1 - T - B) * y2  # convert frame to canvas coordinates
        legend = TLegend(X1, Y1, X2, Y2)
        LOG.verb(
            "Plot.drawlegend: position=%r, height=%.3f, width=%.3f, (x1,y1,x2,y2)=(%.2f,%.2f,%.2f,%.2f), (X1,Y1,X2,Y2)=(%.2f,%.2f,%.2f,%.2f)"
            % (position, height, width, x1, y1, x2, y2, X1, Y1, X2, Y2),
            verbosity, 1)

        # MARGIN
        if ncols >= 2:
            margin = 0.090 / width
        else:
            margin = 0.044 / width
        legend.SetMargin(margin)

        # STYLE
        if transparent: legend.SetFillStyle(0)  # 0 = transparent
        else: legend.SetFillColor(0)
        legend.SetBorderSize(border)
        legend.SetTextSize(tsize)
        legend.SetTextFont(headerfont)  # bold for title
        if ncols > 1:
            legend.SetNColumns(ncols)
            legend.SetColumnSeparation(colsep)

        # HEADER
        if title:
            legend.SetHeader(title)
        legend.SetTextFont(42)  # no bold for entries

        # ENTRIES
        if hists:
            for hist1, entry1, style1 in columnize(zip(hists, entries, styles),
                                                   ncols):
                for entry in entry1.split('\n'):
                    legend.AddEntry(hist1, entry, style1)
                    hist1, style1 = 0, ''
        for line in texts:
            legend.AddEntry(0, line, '')

        if verbosity >= 2:
            print ">>> Plot.drawlegend: title=%r, texts=%s, latex=%s" % (
                title, texts, latex)
            print ">>> Plot.drawlegend: hists=%s" % (hists)
            print ">>> Plot.drawlegend: entries=%s" % (entries)
            print ">>> Plot.drawlegend: styles=%s" % (styles)
            print ">>> Plot.drawlegend: nlines=%s, len(hists)=%s, len(texts)=%s, ncols=%s, margin=%s" % (
                nlines, len(hists), len(texts), ncols, margin)

        legend.Draw(option)
        self.legends.append(legend)
        return legend
Пример #12
0
    def draw(self, *args, **kwargs):
        """Central method of Plot class: make plot with canvas, axis, error, ratio..."""
        # https://root.cern.ch/doc/master/classTHStack.html
        # https://root.cern.ch/doc/master/classTHistPainter.html#HP01e
        verbosity = LOG.getverbosity(self, kwargs)
        xtitle = (args[0] if args else self.xtitle) or ""
        ratio = kwargs.get('ratio', self.ratio)  # make ratio plot
        square = kwargs.get('square', False)  # square canvas
        lmargin = kwargs.get('lmargin', 1.)  # canvas left margin
        rmargin = kwargs.get('rmargin', 1.)  # canvas righ margin
        tmargin = kwargs.get('tmargin', 1.)  # canvas bottom margin
        bmargin = kwargs.get('bmargin', 1.)  # canvas top margin
        errbars = kwargs.get('errbars', True)  # add error bars to histogram
        staterr = kwargs.get('staterr', False)  # create stat. error band
        sysvars = kwargs.get('sysvars',
                             [])  # create sys. error band from variations
        errtitle = kwargs.get('errtitle', None)  # title for error band
        norm = kwargs.get('norm', self.norm)  # normalize all histograms
        title = kwargs.get('title', self.title)  # title for legend
        xtitle = kwargs.get('xtitle', xtitle)  # x axis title
        ytitle = kwargs.get(
            'ytitle', self.ytitle
        )  # y axis title (if None, automatically set by Plot.setaxis)
        rtitle = kwargs.get('rtitle', "Ratio")  # y axis title of ratio panel
        latex = kwargs.get(
            'latex',
            self.latex)  # automatically format strings as LaTeX with makelatex
        xmin = kwargs.get('xmin', self.xmin)
        xmax = kwargs.get('xmax', self.xmax)
        ymin = kwargs.get('ymin', self.ymin)
        ymax = kwargs.get('ymax', self.ymax)
        rmin = kwargs.get('rmin', self.rmin) or 0.45  # ratio ymin
        rmax = kwargs.get('rmax', self.rmax) or 1.55  # ratio ymax
        ratiorange = kwargs.get('rrange',
                                self.ratiorange)  # ratio range around 1.0
        binlabels = kwargs.get(
            'binlabels', self.binlabels)  # list of alphanumeric bin labels
        ytitleoffset = kwargs.get('ytitleoffset', 1.0)
        xtitleoffset = kwargs.get('xtitleoffset', 1.0)
        logx = kwargs.get('logx', self.logx)
        logy = kwargs.get('logy', self.logy)
        ymargin = kwargs.get(
            'ymargin',
            self.ymargin)  # margin between hist maximum and plot's top
        logyrange = kwargs.get(
            'logyrange',
            self.logyrange)  # log(y) range from hist maximum to ymin
        grid = kwargs.get('grid', True)
        tsize = kwargs.get('tsize', _tsize)  # text size for axis title
        pair = kwargs.get('pair', False)
        triple = kwargs.get('triple', False)
        lcolors = kwargs.get('colors', None)
        lcolors = kwargs.get('lcolors', lcolors) or self.lcolors  # line colors
        fcolors = kwargs.get('fcolors', None) or self.fcolors  # fill colors
        lstyles = kwargs.get('lstyle', None)
        lstyles = kwargs.get('lstyles', lstyles) or self.lstyles  # line styles
        lwidth = kwargs.get('lwidth', 2)  # line width
        mstyle = kwargs.get('mstyle', None)  # marker style
        option = kwargs.get('option',
                            'HIST')  # draw option for every histogram
        options = kwargs.get('options', [])  # draw option list per histogram
        roption = kwargs.get('roption', None)  # draw option of ratio plot
        enderrorsize = kwargs.get('enderrorsize',
                                  2.0)  # size of line at end of error bar
        errorX = kwargs.get('errorX', True)  # horizontal error bars
        dividebins = kwargs.get('dividebins', self.dividebins)
        lcolors = ensurelist(lcolors)
        fcolors = ensurelist(fcolors)
        lstyles = ensurelist(lstyles)
        self.ratio = ratio
        self.lcolors = lcolors
        self.fcolors = fcolors
        self.lstyles = lstyles
        if not xmin: xmin = self.xmin
        if not xmax: xmax = self.xmax
        hists = self.hists
        denom = ratio if isinstance(ratio, int) and (ratio != 0) else False
        denom = max(0, min(len(hists), kwargs.get(
            'denom', denom)))  # denominator histogram in ratio plot

        # NORMALIZE
        if norm:
            if ytitle == None:
                ytitle = "A.U."
            scale = 1.0 if isinstance(norm, bool) else norm
            normalize(self.hists, scale=scale)

        # DIVIDE BY BINSIZE
        if dividebins:
            for i, oldhist in enumerate(self.hists):
                newhist = dividebybinsize(oldhist, zero=True, zeroerrs=False)
                if oldhist != newhist:
                    LOG.verb(
                        "Plot.draw: replace %s -> %s" % (oldhist, newhist),
                        verbosity, 2)
                    self.hists[i] = newhist
                    self.garbage.append(oldhist)
            #if sysvars:
            #  histlist = sysvars.values() if isinstance(sysvars,dict) else sysvars
            #  for (histup,hist,histdown) in histlist:
            #    dividebybinsize(histup,  zero=True,zeroerrs=False)
            #    dividebybinsize(histdown,zero=True,zeroerrs=False)
            #    if hist not in self.hists:
            #      dividebybinsize(hist,zero=True,zeroerrs=False)

        # DRAW OPTIONS
        if errbars:
            option = 'E0 ' + option  #E01
            if not roption:
                roption = 'HISTE'
        if len(options) == 0:
            options = [option] * len(hists)
            if staterr:
                options[0] = 'HIST'  # E3'
        else:
            while len(options) < len(hists):
                options.append(options[-1])
        #if not self.histsD and staterr and errbars:
        #  i = denominator-1 if denominator>0 else 0
        #  options[i] = options[i].replace('E0','')
        gStyle.SetEndErrorSize(enderrorsize)
        if errorX:
            gStyle.SetErrorX(0.5)
        else:
            gStyle.SetErrorX(0)

        # CANVAS
        self.canvas = self.setcanvas(square=square,
                                     ratio=ratio,
                                     lmargin=lmargin,
                                     rmargin=rmargin,
                                     tmargin=tmargin,
                                     bmargin=bmargin)

        # DRAW
        self.canvas.cd(1)
        #self.frame.Draw('AXIS') # 'AXIS' breaks grid
        for i, (hist, option1) in enumerate(zip(hists, options)):
            if triple and i % 3 == 2:
                option1 = 'E1'
            option1 += " SAME"
            hist.Draw(option1)
            LOG.verb(
                "Plot.draw: i=%s, hist=%s, option=%r" % (i, hist, option1),
                verbosity, 2)

        # STYLE
        lhists, mhists = [], []
        for hist, opt in zip(hists, options):
            if 'H' in opt: lhists.append(hist)
            else: mhists.append(hist)
        self.setlinestyle(lhists,
                          colors=lcolors,
                          styles=lstyles,
                          mstyle=mstyle,
                          width=lwidth,
                          pair=pair,
                          triple=triple)
        self.setmarkerstyle(*mhists, colors=lcolors)

        # CMS STYLE
        if CMSStyle.lumiText:
            #mainpad = self.canvas.GetPad(1 if ratio else 0)
            CMSStyle.setCMSLumiStyle(gPad, 0)

        # ERROR BAND
        if staterr or sysvars:
            #seterrorbandstyle(hists[0],fill=False)
            self.errband = geterrorband(self.hists[0],
                                        sysvars=sysvars,
                                        color=self.hists[0].GetLineColor(),
                                        name=makehistname(
                                            "errband", self.name),
                                        title=errtitle)
            self.errband.Draw('E2 SAME')

        # AXES
        self.setaxes(self.frame,
                     *hists,
                     xmin=xmin,
                     xmax=xmax,
                     ymin=ymin,
                     ymax=ymax,
                     logy=logy,
                     logx=logx,
                     xtitle=xtitle,
                     ytitle=ytitle,
                     ytitleoffset=ytitleoffset,
                     xtitleoffset=xtitleoffset,
                     binlabels=binlabels,
                     ymargin=ymargin,
                     logyrange=logyrange,
                     main=ratio,
                     grid=grid,
                     latex=latex)

        # RATIO
        if ratio:
            self.canvas.cd(2)
            self.ratio = Ratio(*hists,
                               errband=self.errband,
                               denom=denom,
                               drawzero=True,
                               option=roption)
            self.ratio.draw(roption, xmin=xmin, xmax=xmax)
            self.setaxes(self.ratio,
                         xmin=xmin,
                         xmax=xmax,
                         ymin=rmin,
                         ymax=rmax,
                         logx=logx,
                         binlabels=binlabels,
                         center=True,
                         nydiv=506,
                         rrange=ratiorange,
                         xtitle=xtitle,
                         ytitle=rtitle,
                         xtitleoffset=xtitleoffset,
                         grid=grid,
                         latex=latex)
            self.canvas.cd(1)
Пример #13
0
 def __init__(self, *args, **kwargs):
   """
   Initialize with list of histograms:
     Plot(hists)
   or with a variable (string or Variable object) as well:
     Plot(variable,hists)
   """
   variable   = None
   hists      = None
   self.verbosity = LOG.getverbosity(kwargs)
   if len(args)==1 and islist(args[0]):
     hists    = args[0] # list of histograms
   elif len(args)==2:
     variable = args[0] # string or Variable
     hists    = ensurelist(args[1]) # list of histograms
   else:
     LOG.throw(IOError,"Plot: Wrong input %s"%(args))
   if kwargs.get('clone',False):
     hists    = [h.Clone(h.GetName()+"_plot") for h in hists]
   self.hists = hists
   self.frame = kwargs.get('frame', None )
   frame      = self.frame or self.hists[0]
   if isinstance(variable,Variable):
     self.variable   = variable
     self.name       = kwargs.get('name',       variable.filename    )
     self.xtitle     = kwargs.get('xtitle',     variable.title       )
     self.xmin       = kwargs.get('xmin',       variable.xmin        )
     self.xmax       = kwargs.get('xmax',       variable.xmax        )
     self.ymin       = kwargs.get('ymin',       variable.ymin        )
     self.ymax       = kwargs.get('ymax',       variable.ymax        )
     self.rmin       = kwargs.get('rmin',       variable.rmin        )
     self.rmax       = kwargs.get('rmax',       variable.rmax        )
     self.ratiorange = kwargs.get('rrange',     variable.ratiorange  )
     self.binlabels  = kwargs.get('binlabels',  variable.binlabels   )
     self.logx       = kwargs.get('logx',       variable.logx        )
     self.logy       = kwargs.get('logy',       variable.logy        )
     self.ymargin    = kwargs.get('ymargin',    variable.ymargin     )
     self.logyrange  = kwargs.get('logyrange',  variable.logyrange   )
     self.position   = kwargs.get('position',   variable.position    )
     self.ncols      = kwargs.get('ncols',      variable.ncols       )
     self.latex      = kwargs.get('latex',      False                ) # already done by Variable.__init__
     self.dividebins = kwargs.get('dividebins', variable.dividebins  ) # divide each histogram bins by it bin size
   else:
     self.variable   = variable or frame.GetXaxis().GetTitle()
     self.name       = kwargs.get('name',       None                 )
     self.xtitle     = kwargs.get('xtitle',     self.variable        )
     self.xmin       = kwargs.get('xmin', frame.GetXaxis().GetXmin() )
     self.xmax       = kwargs.get('xmax', frame.GetXaxis().GetXmax() )
     self.ymin       = kwargs.get('ymin',       None                 )
     self.ymax       = kwargs.get('ymax',       None                 )
     self.rmin       = kwargs.get('rmin',       None                 )
     self.rmax       = kwargs.get('rmax',       None                 )
     self.ratiorange = kwargs.get('rrange',     None                 )
     self.binlabels  = kwargs.get('binlabels',  None                 )
     self.logx       = kwargs.get('logx',       False                )
     self.logy       = kwargs.get('logy',       False                )
     self.ymargin    = kwargs.get('ymargin',    None                 )
     self.logyrange  = kwargs.get('logyrange',  None                 )
     self.position   = kwargs.get('position',   ""                   )
     self.ncols      = kwargs.get('ncols',      None                 )
     self.latex      = kwargs.get('latex',      True                 )
     self.dividebins = kwargs.get('dividebins', frame.GetXaxis().IsVariableBinSize())
   self.ytitle       = kwargs.get('ytitle', frame.GetYaxis().GetTitle() or None )
   self.name         = self.name or (self.hists[0].GetName() if self.hists else "noname")
   self.title        = kwargs.get('title',      None                 )
   self.errband      = None
   self.ratio        = kwargs.get('ratio',      False                )
   self.append       = kwargs.get('append',     ""                   )
   self.norm         = kwargs.get('norm',       False                )
   self.lcolors      = kwargs.get('lcolors',    _lcolors             )
   self.fcolors      = kwargs.get('fcolors',    _fcolors             )
   self.lstyles      = kwargs.get('lstyles',    _lstyles             )
   self.canvas       = None
   self.legends      = [ ]
   self.texts        = [ ] # to save TLatex objects made by drawtext
   self.lines        = [ ]
   self.garbage      = [ ]