truth_ana.py
Go to the documentation of this file.
1 # truth_ana.py
2 # created: April 2021
3 # author: chilgenb@fnal.gov
4 # description: macro for demonstrating how to use garana
5 # usage: You will most likely need to update the file path given to TreeManager.
6 # Then, in your terminal, enter the command 'python truth_ana.py'
7 # and that's all there is to it :)
8 # you can build off the example below to access other trees/variables.
9 # documentation is a work in progress. for now see documentation in
10 # accessor base classes (garana/Base/*.h).
11 
12 
13 import garanainit # script for loading garana libs
14 import ROOT # loads all ROOT libs
15 from ROOT import TH1F
16 from ROOT import TH2F
17 from ROOT import TCanvas
18 from ROOT import TEfficiency
19 import numpy as np
20 garanainit.init() # loads the garana libs
21 
22 #####################################################################
23 # central garana tree manager
24 # it links to all of the individual tree accessors given a file
25 # with garana trees produced in the default garana format
26 tm = ROOT.TreeManager("./structuredtree.root") #change to your file path
27 bt = ROOT.Backtracker(tm) # backtracker for association handling
28 
29 pdgDB = ROOT.TDatabasePDG()
30 pdgDB.ReadPDGTable()
31 
32 pdgToName = {11 : "e^{-}", #leptons
33  -11 : "e^{+}",
34  12 : "#nu_{e}",
35  -12 : "#bar{#nu}_{e}",
36  13 : "#mu^{-}",
37  -13 : "#mu^{+}",
38  14 : "#nu_{#mu}",
39  -14 : "#bar{#nu}_{#mu}",
40  15 : "#tau^{-}",
41  -15 : "#tau^{+}",
42  16 : "#nu_{#tau}",
43  -16 : "#bar{#nu}_{#tau}",
44  22 : "#gamma", # bosons
45  111 : "#pi^{0}", # light mesons
46  211 : "#pi^{+}",
47  -211 : "#pi^{-}",
48  221 : "#eta",
49  130 : "K_{L}^{0}", # strange mesons
50  310 : "K_{S}^{0}",
51  311 : "K^{0}",
52  -311 : "#bar{K^{0}}",
53  321 : "K^{+}",
54  -321 : "K^{-}",
55  2112 : "n", # light baryons
56  2212 : "p",
57  1114 : "#Delta^{-}",
58  2114 : "#Delta^{0}",
59  2214 : "#Delta^{+}",
60  2224 : "#Delta^{++}",
61  3122 : "#Lambda", # strange baryons
62  3222 : "#Sigma^{+}",
63  3212 : "#Sigma^{0}",
64  3112 : "#Sigma^{-}"
65 }
66 
67 # get accessors
68 gen = tm.GetGenTree() # genTree (generator level info)
69 g4 = tm.GetG4Tree() # g4Tree (geant4 level info)
70 
71 # generator information
72 hg4nus = TH2F("hg4nus","g4Tree;N^{0} #nu's;GENIE scatter code",3,0,3,30,0,30)
73 hnureg = TH1F("hnureg",";#nu vertex region;",10,0,10)
74 hngen = TH1F("hngen","genTree;N^{0} MCTruth;",5,0,5)
75 
76 # histograms for counting primaries
77 hnprim = TH1F("hnprim","g4Tree;N^{0} primaries;",40,0,40)
78 hprim_pdg = TH1F("hprim_pdg","g4Tree; MCParticle PDG code;",3400,-400,3000)
79 hprim_mumom = TH1F("hprim_mumom","g4Tree;true momentum [GeV/c];",50,0,5)
80 hprim_pmom = TH1F("hprim_pmom","g4Tree;true momentum [GeV/c];",50,0,5)
81 hprim_mumult = TH1F("hprim_mumult","g4Tree;primary particle multiplicity;",19,0,19)
82 hprim_pmult = TH1F("hprim_pmult","g4Tree;primary particle multiplicity;",19,0,19)
83 hprim_stopmult_tpc = TH1F("hprim_stopmult_tpc","g4Tree; N^{0} primaries stopping in active volume",10,0,10)
84 hprim_stopmult_calo = TH1F("hprim_stopmult_calo","g4Tree; N^{0} primaries stopping in active volume",10,0,10)
85 hprim_chgmult_tpc = TH1F("hprim_chgmult_tpc","g4Tree;N^{0} charged primaries;",19,0,19)
86 hprim_chgmult_calo = TH1F("hprim_chgmult_calo","g4Tree;N^{0} charged primaries;",19,0,19)
87 
88 # primaries polar angle (w.r.t. beam direction)
89 hprim_theta_all = TH1F("hprim_theta_all","g4Tree: primaries;#theta [deg]",90,0,180)
90 hprim_theta_mu = TH1F("hprim_theta_mu", "g4Tree: primaries;#theta [deg]",90,0,180)
91 hprim_theta_p = TH1F("hprim_theta_p", "g4Tree: primaries;#theta [deg]",90,0,180)
92 hprim_theta_pic = TH1F("hprim_theta_pic","g4Tree: primaries;#theta [deg]",90,0,180)
93 
94 # initial and final particle times
95 hprim_t0 = TH1F("hprim_t0", "g4Tree; time [ns];",100,0,1e4)
96 hprim_tf = TH1F("hprim_tf", "g4Tree; time [ns];",100,0,1e4)
97 hall_t0 = TH1F("hall_t0", "g4Tree; time [ns];",100,0,1e4)
98 hall_tf = TH1F("hall_tf", "g4Tree; time [ns];",100,0,1e4)
99 henu_mu = TH1F("henu_mu","genTree;E_{#nu} [GeV]", 50,0,10)
100 henu_mubar = TH1F("henu_mubar","genTree;E_{#nu} [GeV]",50,0,10)
101 henu_e = TH1F("henu_e","genTree;E_{#nu} [GeV]", 50,0,10)
102 henu_ebar = TH1F("henu_ebar","genTree;E_{#nu} [GeV]", 50,0,10)
103 
104 # positions of G4Particles
105 hx = TH1F("hx","g4Tree;x [cm]",100,-300,300)
106 hy = TH1F("hy","g4Tree;y [cm]",100,-450,120)
107 hz = TH1F("hz","g4Tree;z [cm]",100,1250,1750)
108 
109 pdgcts = {13:0} # all numu CC events should have at least one muon
110 pdgcts_calo = {13:0} # primaries passing through ECal
111 
112 
113 # loop over genTree entries
114 for ientry in range(gen.NEntries()):
115 
116  tm.GetEntry(ientry) # fill data members with data for current event
117 
118  if not (gen.IsGenie(0) and gen.IsCC(0) and gen.NuPDG(0)==14 and gen.NuInAV(0)) : continue #nu_mu CC w/vtx in TPC active volume only
119  bt.FillMaps() # load the Backtracker maps for this tree entry
120 
121  # no. of primaries per neutrino interaction
122  hnprim.Fill(g4.NPrimary())
123 
124  # counters
125  nnu = 0 # number of neutrinos
126  nprim_mu = 0 # no. primary muons
127  nprim_p = 0 # no. primary protons
128  nstop_tpc = 0 # no. primaries stopping in the TPC
129  nstop_calo = 0 # no. primaries stopping in the ECal
130  nprim_chg_tpc = 0 # no. charged primaries in the TPC
131  nprim_chg_calo = 0 # no. charged primaries in the ECal
132  inu = -1
133  # loop over entries in the g4Tree
134  for ig4 in range(g4.NSim()) :
135 
136  if g4.IsPrimary(ig4) :
137 
138  theta = ROOT.TMath.RadToDeg()*g4.SimMomBegin(ig4).Theta()
139  hprim_theta_all.Fill(theta)
140  hx.Fill(g4.SimPosBegin(ig4).X())
141  hy.Fill(g4.SimPosBegin(ig4).Y())
142  hz.Fill(g4.SimPosBegin(ig4).Z())
143 
144  if g4.IsCathodeCrosser(ig4) : print('found cathode crossing primary!')
145 
146  pdgcode = g4.PDG(ig4)
147  if abs(pdgcode) > 6000 : continue # ignore recoil nucleus
148 
149  partPDG = pdgDB.GetParticle(pdgcode) # get info about particle by PDG code
150 
151  if not pdgcode in pdgcts :
152  pdgcts[pdgcode] = 0
153 
154  pdgcts[pdgcode] += 1
155 
156  if g4.HasPassedCalo(ig4) :
157  if not pdgcode in pdgcts_calo :
158  pdgcts_calo[pdgcode] = 0
159  pdgcts_calo[pdgcode] += 1
160 
161  hprim_pdg.Fill(pdgcode)
162  if g4.IsStoppedTPC(ig4) : nstop_tpc +=1
163  if g4.IsStoppedCalo(ig4) : nstop_calo +=1
164  if partPDG.Charge()!=0 :
165  if g4.HasPassedTPC(ig4): nprim_chg_tpc +=1
166  if g4.HasPassedCalo(ig4): nprim_chg_calo +=1
167 
168 
169  if abs(g4.PDG(ig4)) == 13 : # is it a muon?
170  hprim_mumom.Fill(g4.SimMomBegin(ig4).P())
171  hprim_theta_mu.Fill(theta)
172  nprim_mu+=1
173 
174  if abs(g4.PDG(ig4)) == 211 : # is it a charged pion?
175  hprim_theta_pic.Fill(theta)
176 
177  if g4.PDG(ig4) == 2212 : # is it a proton?
178  hprim_pmom.Fill(g4.SimMomBegin(ig4).P())
179  hprim_theta_p.Fill(theta)
180  nprim_p+=1
181 
182  else :
183  if g4.IsCathodeCrosser(ig4) : print('found cathode crossing secondary!')
184  continue
185 
186  if (abs(g4.PDG(ig4))==12 or abs(g4.PDG(ig4))==14) :
187  nnu+=1
188 
189  hprim_mumult.Fill(nprim_mu)
190  hprim_pmult.Fill(nprim_p)
191  hprim_stopmult_tpc.Fill(nstop_tpc)
192  hprim_stopmult_calo.Fill(nstop_calo)
193  hprim_chgmult_tpc.Fill(nprim_chg_tpc)
194  hprim_chgmult_calo.Fill(nprim_chg_calo)
195 
196  # loop over all interactions in this event
197  hngen.Fill(gen.NGen())
198  for igen in range(gen.NGen()):
199 
200  if not gen.IsGenie(igen) : continue
201  enu = gen.NuP(igen).E()
202 
203  if gen.NuPDG(igen)==14 : henu_mu.Fill(enu)
204  if gen.NuPDG(igen)==-14 : henu_mubar.Fill(enu)
205  if gen.NuPDG(igen)==12 : henu_e.Fill(enu)
206  if gen.NuPDG(igen)==-12 : henu_ebar.Fill(enu)
207 
208  hnureg.Fill(gen.NuRegion(igen))
209 
210 
211 # make pretty plots using particle names instead of PDG codes
212 hpdgtxt = TH1F("hpdgtxt","g4Tree: primaries;; counts per species",len(pdgcts),0,len(pdgcts))
213 hpdgtxt_calo = TH1F("hpdgtxt_calo","g4Tree: primaries;; counts per species",len(pdgcts),0,len(pdgcts))
214 
215 # loop over counts per pdg in ascending order of counts
216 for i, (k,v) in enumerate(dict(sorted(pdgcts.items(), key=lambda item: item[1])).items()):
217  hpdgtxt.SetBinContent(i+1,v)
218  hpdgtxt.GetXaxis().SetBinLabel(i+1,pdgToName[k])
219 
220  if k in pdgcts_calo.keys():
221  hpdgtxt_calo.SetBinContent(i+1,pdgcts_calo[k])
222 
223 # draw our histogram and save it to file
224 cngen = TCanvas()
225 hngen.Draw("e0hist")
226 
227 cnprim = TCanvas()
228 hnprim.Draw("e0hist")
229 
230 cg4nus = TCanvas()
231 hg4nus.Draw("colz")
232 
233 cnureg = TCanvas()
234 hnureg.Draw("e0hist")
235 
236 #
237 henu_mubar.SetLineColor(ROOT.kCyan)
238 henu_e.SetLineColor(ROOT.kRed)
239 henu_ebar.SetLineColor(ROOT.kMagenta)
240 
241 cenu = TCanvas()
242 henu_mu.Draw("e0hist")
243 henu_mubar.Draw("e0hist same")
244 henu_e.Draw("e0hist same")
245 henu_ebar.Draw("e0hist same")
246 
247 #
248 cprim_pdg = TCanvas()
249 hprim_pdg.Draw("e0hist")
250 
251 #
252 hprim_pmom.SetLineColor(ROOT.kRed)
253 hprim_mumom.SetLineWidth(2)
254 hprim_pmom.SetLineWidth(2)
255 
256 cprim_mom = TCanvas()
257 hprim_pmom.Draw("e0hist")
258 hprim_mumom.Draw("e0hist same")
259 
260 #
261 hprim_pmult.SetLineColor(ROOT.kRed)
262 hprim_mumult.SetLineWidth(2)
263 hprim_pmult.SetLineWidth(2)
264 
265 cprim_mult = TCanvas()
266 hprim_mumult.Draw("e0hist")
267 hprim_pmult.Draw("e0hist same")
268 leg3 = ROOT.TLegend(0.6,0.6,0.8,0.8)
269 leg3.SetBorderSize(0)
270 leg3.AddEntry(hprim_mumult,"#mu^{#pm}","l")
271 leg3.AddEntry(hprim_pmult,"p^{+}","l")
272 leg3.Draw()
273 
274 #
275 hprim_stopmult_calo.SetLineColor(ROOT.kRed)
276 hprim_stopmult_tpc.SetLineWidth(2)
277 hprim_stopmult_calo.SetLineWidth(2)
278 
279 cprim_stopmult = TCanvas()
280 hprim_stopmult_tpc.Draw("e0hist")
281 hprim_stopmult_calo.Draw("e0hist same")
282 leg4 = ROOT.TLegend(0.6,0.6,0.8,0.8)
283 leg4.SetBorderSize(0)
284 leg4.AddEntry(hprim_stopmult_tpc,"TPC","l")
285 leg4.AddEntry(hprim_stopmult_calo,"TPC","l")
286 leg4.Draw()
287 
288 #
289 hprim_chgmult_calo.SetLineColor(ROOT.kRed)
290 hprim_chgmult_tpc.SetLineWidth(2)
291 hprim_chgmult_calo.SetLineWidth(2)
292 
293 cprim_chgmult = TCanvas()
294 hprim_chgmult_tpc.Draw("e0hist")
295 hprim_chgmult_calo.Draw("e0hist same")
296 leg4.Draw()
297 
298 #
299 hpdgtxt.SetFillColor(ROOT.kBlue)
300 hpdgtxt_calo.SetFillColor(ROOT.kRed)
301 hpdgtxt.GetXaxis().SetLabelSize(0.07)
302 
303 ROOT.gStyle.SetOptStat(0)
304 cpdgtxt = TCanvas()
305 cpdgtxt.SetLogx()
306 hpdgtxt.Draw("HBAR1 E0")
307 hpdgtxt_calo.Draw("HBAR1 E0 same")
308 
309 leg = ROOT.TLegend(0.6,0.2,0.8,0.4)
310 leg.SetBorderSize(0)
311 leg.AddEntry("hpdgtxt","primaries in TPC","F")
312 leg.AddEntry("hpdgtxt_calo","primaries in ECal","F")
313 leg.Draw()
314 
315 #
316 hprim_theta_all.SetLineWidth(2)
317 hprim_theta_mu.SetLineWidth(2)
318 hprim_theta_p.SetLineWidth(2)
319 hprim_theta_pic.SetLineWidth(2)
320 
321 hprim_theta_mu.SetLineColor(ROOT.kGreen-1)
322 hprim_theta_p.SetLineColor(ROOT.kRed)
323 hprim_theta_pic.SetLineColor(ROOT.kMagenta)
324 
325 ctheta = TCanvas()
326 hprim_theta_all.Draw("e0hist")
327 hprim_theta_mu.Draw("e0hist same")
328 hprim_theta_p.Draw("e0hist same")
329 hprim_theta_pic.Draw("e0hist same")
330 leg2 = ROOT.TLegend(0.6,0.6,0.8,0.8)
331 leg2.SetBorderSize(0)
332 leg2.AddEntry(hprim_theta_all,"all","l")
333 leg2.AddEntry(hprim_theta_mu,"#mu^{#pm}","l")
334 leg2.AddEntry(hprim_theta_p,"p^{+}","l")
335 leg2.AddEntry(hprim_theta_pic,"#pi^{#pm}","l")
336 leg2.Draw()
337 
338 cx = TCanvas()
339 hx.Draw()
340 
341 cy = TCanvas()
342 hy.Draw()
343 
344 cz = TCanvas()
345 hz.Draw()
346 
347 # ask for user input as a way to keep the program from ending so we can
348 # see the histogram.
349 # python doesn't like empty input strings so I abuse exception handling
350 try:
351  null = input("press <Enter> to close canvas and exit program.")
352 
353 except:
354  null = 'null'
355 #
std::pair< float, std::string > P
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
Definition: enumerate.h:69
T abs(T value)
static int input(void)
Definition: code.cpp:15695
def init()
Definition: garanainit.py:12