This example shows how to use FWLite in pyroot. It provides examples of how to load a collection and loop on the events performing selections and plotting an invariant mass distribution.
Basic imports
import ROOT
from DataFormats.FWLite import Events, Handle
# For inline plots
import rootnotes
import rootprint
import utils
from ProgressBar import ProgressBar
Create a handle outside the loop. The handle is used to load the collections of objects in the event loop. It allows to access muons in this case, but the same can be used to access any other collection in the event.
handle = Handle ('std::vector<reco::Muon>')
# a label is just a tuple of strings that is initialized just
# like an edm::InputTag
label = ("muons")
Change the style of the plot from the default with grey background to a cleaner white background
ROOT.gROOT.SetStyle('Plain')
Define a TH1F histogram for the invariant mass plot
zmassHist = ROOT.TH1F ("zmass", "Z Candidate Mass", 50, 60, 120)
Event loop and histogram filling. Using a Z→μ+μ− MC PATtuple.
# %%rootprint
# Muon mass in GeV
muonMass = 0.1057
events = Events ('/afs/cern.ch/user/d/demattia/public/B281755E-29D2-E111-A29E-001E67397701.root')
p = ProgressBar(events.size())
i = 0
for event in events:
i+=1
p.animate(i)
# use getByLabel, just like in cmsRun
event.getByLabel (label, handle)
# get the product
muons = handle.product()
# use muons to make Z peak
numMuons = len(muons)
if numMuons < 2: continue
for outer in range(numMuons - 1):
outerMuon = muons[outer]
for inner in range(outer + 1, numMuons):
innerMuon = muons[inner]
if outerMuon.charge() * innerMuon.charge() >= 0:
continue
# This is good if we have the energy. For a reco::Muon we have it because we are the
# hypothesis that the particle is a muon. For a reco::Track we do not have it.
inner4v = ROOT.TLorentzVector (innerMuon.px(), innerMuon.py(),
innerMuon.pz(), innerMuon.energy())
outer4v = ROOT.TLorentzVector (outerMuon.px(), outerMuon.py(),
outerMuon.pz(), outerMuon.energy())
# If you are using reco::Tracks (for example you are accessing the StandAloneMuons directly instead of through
# the reco::Muon container, you will not have access to the energy method. You can use sqrt(p()^2+muonMass^2) or
# you can create an empty TLorentzVector and use the SetPxPyPzM() method to set the content using the muon mass
# for M, such as:
# inner4v.SetPxPyPzM(innerMuon.px(), innerMuon.py(), innerMuon.pz(), muMass)
zmassHist.Fill( (inner4v + outer4v).M() )
Draw the canvas. We use the rootnotes macro to draw it inline
# make a canvas, draw, and save it
c1 = rootnotes.canvas("test", (400, 400))
zmassHist.Draw()
c1
Question 1: can you compute the efficiency of selecting dimuon candidates where the pt of each muon is above 25 GeV? Draw a canvas with two histograms. On the left the one before cuts and on the right the one after cuts. You can modify the event loop above.
Question 2: perform a fit to the invariant mass distribution and estimate the number of Z boson candidates.
Note: at this level a gaussian fit will be enough. In a subsequent exercise we will refine the estimate using RooFit.
Question 3: Find the name of the collections in the input tree, make the same plot for standAloneMuons. Compute the same efficiency as before. What is the most striking difference you observe?
Note that the standAloneMuons collection is of type std::vector< reco::Track > instead of std::vector< reco::Muon >.
You can use the code in the next cell to find the names of the collections.
Modify the code above to also load the standAloneMuons collection.
%%rootprint
inputFile = ROOT.TFile("/afs/cern.ch/user/d/demattia/public/B281755E-29D2-E111-A29E-001E67397701.root")
tree = inputFile.Get("Events")
# Uncomment this to get the list of all collections maching the pattern
# tree.Print("recoTracks_standAloneMuons_*")
Uncomment and run the next cell to see the suggestion
# print open("FWLiteSuggestionQuestion3.txt").read()