# histograms are unified! from rootpy.plotting import Hist hist = Hist(10, -3, 3) # <== notice that the name or title is not needed hist.name # the name is automatically a unique ID # Hist is really a subclass of the appropriate ROOT TH1X class hist.__class__.__bases__ # the base class is determined dynamically at runtime hist = Hist(10, -3, 3, type='D', title="asd", linecolor="#ccddee") hist.__class__.__bases__ print hist.GetLineColor() # rootpy has ipython notebook support so things can be drawn inline hist.FillRandom('gaus') hist from rootpy.plotting import Hist2D, Hist3D # variable-width bins h1d = Hist([-10, -3.2, 5.2, 6]) # 2D histogram with fixed-width bins; 10 along x and 5 along y h2d = Hist2D(10, 0, 1, 5, -2, 4, drawstyle='E') # 3 variable-width bins along x and 4 fixed-width bins along y h2d = Hist2D([10, 30, 100, 1000], 4, 10, 33.5) # 3D histogram with fixed-width bins h3d = Hist3D(100, 0, 1, 20, 5.8, 7.2, 1000, -10, 1) # fixed-width bins along x and z and variable-width bins along y h3d = Hist3D(5, 0, 1, [-20, 5, 50, 1e3], 10, 0, 1) from rootpy.plotting import set_style set_style('ATLAS') hist = Hist(50, -3, 3) hist.FillRandom('gaus') hist.xaxis.title = 'Variable [Units]' hist.yaxis.title = 'Entries' hist.linewidth = 3 hist.linestyle = 'dashed' hist.linecolor = 'forestgreen' # SVG hist.markercolor = '#334455' # hex hist.fillstyle = '/' hist.fillcolor = 'red' hist.drawstyle = 'HIST' hist # access bin contents and errors hist[1] = (3, 1.2) hist[1].value hist[1].error # reverse bin contents (and errors) hist[:] = hist.Clone(shallow=True)[::-1] hist # rebin by 2 along x hist.rebinned(5, axis=0) Hist(hist[::10]) # you can construct histograms from "views" of other histograms. The step value in the slice creates a rebinning. # merge specific bins hist.merge_bins([(0, 5), (40, -1)]) # same functionality in 2D and 3D... from rootpy.plotting import F2 h2 = Hist2D(20, 0, 1, 20, 0, 1) h2.FillRandom(F2('x*y')) h2.drawstyle = 'LEGO2' h2 h2_merged = h2.merge_bins([(6, 12)], axis=1) h2_merged.drawstyle = 'LEGO2' h2_merged h2_merged = h2_merged.merge_bins([(6, 12)], axis=0) h2_merged.drawstyle = 'LEGO2' h2_merged Hist2D(h2[5:10,::5], drawstyle='LEGO2') # crop along x and rebin along y h2[:,2:8] = (0, 0) # set specific ranges of bins (value, error) h2 # flatten a histogram by rebinning according to the quantiles h = Hist(1000, -3, 3) h.FillRandom('gaus', 100000) print h.quantiles(5, strict=True) h_flat = h.rebinned(h.quantiles(5, strict=True)) h_flat.SetMinimum(0) h_flat from rootpy.io import root_open from rootpy.testdata import get_filepath # objects are automatically cast to the rootpy subclasses if they exist # support for the with-statement with root_open(get_filepath()) as f: print f for path, dirs, objects in f.walk(): print path, objects f = root_open(get_filepath()) list(f.find('hist1')) # only loop over objects of a given class for path, dirs, objects in f.walk(class_pattern='TH1F'): print objects f.scales.hist1 # easy acess # does something exist in a file? 'scales' in f 'blah' in f 'scales/hist1' in f # create a new file g = root_open('test.root', 'recreate') hist = Hist(10, -3, 3) hist.FillRandom('gaus') # write to this file g.myhist = hist list(g) g.Get('myhist') # ROOT errors become real Python exceptions root_open('does_not_exist.root') g['asasd'] from rootpy.tree import Tree, TreeModel, IntCol, FloatCol from rootpy.vector import LorentzVector from random import gauss, uniform, expovariate from math import pi class Event(TreeModel): number = IntCol() MET_phi = FloatCol() MET = FloatCol(default=-1) jet = LorentzVector output = root_open('test.root', 'recreate') tree = Tree('data', model=Event) for i in xrange(1000): tree.number = i tree.MET_phi = uniform(-pi, pi) if i % 2 == 1: tree.MET = expovariate(10) tree.jet.SetPtEtaPhiM(expovariate(10), gauss(0, 2), uniform(-pi, pi), 0) tree.Fill(reset=True) len(tree) tree.Draw('MET_phi') tree.Draw('jet.Pt()', drawstyle='hist', linewidth=3, linestyle='dotted') # a more complicated model... class Particle(TreeModel): charge = IntCol() fourvector = LorentzVector class Jet(TreeModel): num_tracks = IntCol() vertex_fraction = FloatCol() fourvector = LorentzVector class Event(Particle.prefix('mu1_'), Particle.prefix('mu2_'), Jet.prefix('jet1_'), Jet.prefix('jet2_')): number = IntCol() MET_phi = FloatCol() MET = FloatCol(default=-1) tree2 = Tree('events', model=Event) tree2._buffer from rootpy.tree import Cut a = Cut() a.__class__.__bases__ cut1 = Cut('a < 10') cut2 = Cut('b % 2 == 0') cut1 & cut2 # expansion of ternary conditions cut3 = Cut('10 < a < 20') cut3 # easily combine cuts arbitrarily ((cut1 & cut2) | - cut3)