tracks.py
Go to the documentation of this file.
1 # tracks.py
2 # created: April 2021
3 # author: chilgenb@fnal.gov
4 # description: macro for demonstrating how to use garana
5 # usage: in your terminal, enter the command 'python tracks.py'
6 # and that's all there is to it :)
7 # you can build off the example below to access other trees/variables.
8 # documentation is a work in progress. for now see documentation in
9 # accessor base classes (garana/Base/*.h).
10 
11 
12 import garanainit # script for loading garana libs
13 import ROOT, sys
14 from ROOT import TH1F, TH2F, TCanvas
15 from ROOT import gStyle, gROOT
16 #from ROOT import TCanvas
17 import numpy as np
18 import math
19 
20 ######################################################################################
21 #python wrapper for track parameters array
22 # N.B. assume backward and forward fit give very similar track params and use forward only
23 def GetTrackPars(rec,itrk) :
24  parsvec = ROOT.std.vector("float")(5)
25  pars = np.asarray(parsvec) # python-friendly array
26  rec.TrackParBeg(itrk,pars)
27  return pars
28 
29 
30 # inputs
31 # - pos : trajectory point on a fit track (TLorentzvector)
32 # - x0 : 6th track parameter (independent of track fit)
33 # - params[5] : track fit parameters(y0,z0,c,phi0,lambda)
34 # output
35 # - phi (radians)
36 def GetPhi(pos,x0,pars):
37 
38  # give params human-readable names
39  y0 = pars[0]
40  z0 = pars[1]
41  r = 1.0/pars[2] # radius of curvature of circle in y-z plane
42  phi0 = pars[3]
43  lam = pars[4]
44 
45  # circle center
46  yc = y0 + r * math.cos(phi0)
47  zc = z0 - r * math.sin(phi0)
48 
49  # need to get phi from x-coordinate
50  # in y,z, phi is degenerate: phi = phi + m*2pi, m is int
51  return (pos.X()-x0)/(r*math.tan(lam))+phi0
52 
53 
54 
55 
56 # phi-difference between track endpoints
57 # input: rec (recoTree accessor) and track index (int)
58 # output: value of delta phi (float)
59 # N.B. assume backward and forward fit give very similar track params and use forward only
60 def GetDeltaPhi(rec, itrk) :
61 
62  #parsvec = ROOT.std.vector("float")(5)
63  #pars = np.asarray(parsvec) # python-friendly array
64  #rec.TrackParBeg(itrk,pars)
65  pars = GetTrackPars(rec,itrk)
66 
67  vtx = rec.TrackVertex(itrk)
68  end = rec.TrackEnd(itrk)
69 
70  phivtx = GetPhi(vtx,vtx.X(),pars)
71  phiend = GetPhi(end,vtx.X(),pars)
72  return phiend-phivtx
73 
74 
75 
76 ############################################################
77 garanainit.init() # loads the garana libs
78 
79 # central garana tree manager
80 # it links to all of the individual tree accessors given a file
81 # with garana trees produced in the default garana format
82 tm = ROOT.TreeManager("../structuredtree.root") #change to your file path
83 bt = ROOT.Backtracker(tm)
84 
85 # get accessors
86 gen = tm.GetGenTree() # genTree
87 g4 = tm.GetG4Tree() # g4Tree
88 rec = tm.GetRecoTree() # recoTree
89 
90 print("found trees with "+str(rec.NEntries())+" entries")
91 
92 # set up histograms
93 # counting
94 hntrack = TH1F("hntrack", ";N^{0} tracks per #nu;", 50,-0.5,49.5)
95 hnhit = TH1F("hnhit", "TPC track reco; N^{0} hits per track;",200,0.5,1000.5)
96 hnvtx = TH1F("hnvtx", ";N^{0} vertices per #nu;", 6,1.5,7.5)
97 hnvtxtrk= TH1F("hnvtxtrk",";N^{0} vertices per track;", 5,-0.5,4.5)
98 hntrkvtx= TH1F("hntrkvtx",";N^{0} tracks per vertex;", 7,2.5,9.5)
99 
100 # track parameters
101 hx0 = TH1F("hx0", "TPC track reco: fit parameters;x_{0} [cm]", 50,-280,280)
102 hy0 = TH1F("hy0", "TPC track reco: fit parameters;y_{0} [cm]", 50,-450,150)
103 hz0 = TH1F("hz0", "TPC track reco: fit parameters;z_{0} [cm]", 50,1250,1750)
104 hr = TH1F("hr", "TPC track reco: fit parameters;radius in y-z plane [cm]", 100,0,800)
105 hphi0 = TH1F("hphi0", "TPC track reco: fit parameters;#phi_{0} [rad]", 40,-20,-20)
106 hlambda = TH1F("hlambda", "TPC track reco: fit parameters;#lambda [rad]", 50,-3.2,3.2)
107 hdeltaphi = TH1F("hdeltaphi", "TPC track reco: fit parameters;#phi_{end}- #phi_{vertex} [rad]",50,-2*math.pi,2*math.pi)
108 hdeltaphilen = TH1F("hdeltaphilen", "TPC track reco: fit parameters;(#phi_{end}- #phi_{vertex})/track length [rad/cm]",50,-0.005,0.005)
109 
110 # reco track length fwd and back
111 hlength_fwd = TH1F("hlength_fwd",";track length [cm]",100,0,500)
112 hlength_bkd = TH1F("hlength_bkd",";track length [cm]",100,0,500)
113 
114 #reco mom fwd and back
115 hmom_fwd = TH1F("hmom_fwd",";momentum [GeV/c]",100,0,5)
116 hmom_bkd = TH1F("hmom_bkd",";momentum [GeV/c]",100,0,5)
117 
118 # truth matching
119 hpval = TH1F("hpval","Track reco;p-value;",100,0,1)
120 hpdg = TH1F("hpdg",";PDG code",2800,-500,2300)
121 hpdg_max = TH1F("hpdg_max",";PDG code",2800,-500,2300) #MCParticles contributing most energy to track
122 hpdg_max_pval = TH2F("hpdg_max_pval",";track fit p-value;PDG code",40,0,1,2800,-500,2300)
123 hng4p = TH1F("hng4p",";number MCParticles matched to track",7,-0.5,6.5) # num MCParticles associated to track
124 hg4mom = TH1F("hg4mom",";momentum per particle [GeV/c]",100,0,5) # MCParticle momenta
125 hg4mom_tot_pval = TH2F("hg4mom_tot_pval","TPC track reco;track fit p-value ; p_{true} [GeV/c]",40,0,1,40,0,3)
126 hg4mom1 = TH1F("hg4mom1",";maximum single-particle momentum [GeV/c]",100,0,5) # MCParticle momenta w/max edep
127 hg4mom1_frac = TH1F("hg4mom1_frac",";fraction of total momentum held by single-particle max",100,0,1.01)
128 
129 hntrkpart = TH1F("hntrkpart", "MCParticle #rightarrow Track ; N^{0} tracks per particle",10,-0.5,9.5) # num tracks associated to G4Particle
130 hntrkpart_p = TH1F("hntrkpart_p", "MCParticle #rightarrow Track ; N^{0} tracks per particle",9,0.5,9.5)
131 hntrkpart_mu = TH1F("hntrkpart_mu", "MCParticle #rightarrow Track ; N^{0} tracks per particle",9,0.5,9.5)
132 hntrkpart_pic = TH1F("hntrkpart_pic","MCParticle #rightarrow Track ; N^{0} tracks per particle",9,0.5,9.5)
133 hntrkpart_e = TH1F("hntrkpart_e", "MCParticle #rightarrow Track ; N^{0} tracks per particle",9,0.5,9.5)
134 hntrkpart_vs_mom = TH2F('hntrkpart_vs_mom','MCParticle #rightarrow Track ; N^{0} tracks per particle; true initial momentum [GeV/c]',10,-0.5,9.5,50,0,3)
135 hntrkpart_vs_gyro = TH2F('hntrkpart_vs_gyro','MCParticle #rightarrow Track ; N^{0} tracks per particle;gyroradius [m]',10,-0.5,9.5,50,0,10)
136 
137 hnmom1_frac = TH2F("hnmom1_frac",";fraction of total momentum ; number of particles",50,0,1.01,14,0.5,14.5)
138 
139 # resolution
140 hmomres2d = TH2F("hmomres2d",";P_{true} [GeV/c] ; P_{reco} [GeV/c]",50,0,3,50,0,3)
141 hmomres2d_pval = TH2F("hmomres2d_pval",";track fit p-value;p_{true} - p_{reco} [GeV/c]",50,0,1,50,-3,5)
142 hmomres2d_frac_pval = TH2F("hmomres2d_frac_pval",";track fit p-value;(p_{true} - p_{reco})/p_{true}",50,0,1,50,-1,1)
143 hmomres_diff = TH1F("hmomres_diff","TPC track reco; p_{true} - p_{reco} [GeV/c];",80,-3,5)
144 hmomres_frac = TH1F("hmomres_frac","TPC track reco; ( p_{true} - p_{reco})/p_{true};",60,-1,1)
145 
146 hxdiff = TH1F("hxdiff","TPC track reco;true - reco [cm]",100,-35,35)
147 hydiff = TH1F("hydiff","TPC track reco;true - reco [cm]",100,-35,35)
148 hzdiff = TH1F("hzdiff","TPC track reco;true - reco [cm]",100,-35,35)
149 
150 # loop over events
151 for ientry in range(tm.NEntries()) :
152 
153  tm.GetEntry(ientry) # fill data members with data for current event
154 
155  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
156  bt.FillMaps()
157 
158  hntrack.Fill(rec.NTrack())
159  hnvtx.Fill(rec.NVertex())
160 
161 
162  # loop over all reco tracks
163  for itrk in range(rec.NTrack()):
164 
165  hnhit.Fill(rec.NTrackHit(itrk))
166  hnvtxtrk.Fill(len(bt.TrackToVertices(itrk)))
167 
168  pval = ROOT.TMath.Prob(rec.TrackChiSqrFwd(itrk),rec.NTrackHit(itrk)-5)
169  hpval.Fill(pval)
170  if pval<1e-9 : continue
171 
172  trkpars = GetTrackPars(rec,itrk)
173  trkvtx = rec.TrackVertex(itrk)
174  hx0.Fill(trkvtx.X())
175  hy0.Fill(trkpars[0])
176  hz0.Fill(trkpars[1])
177  hr.Fill(1.0/trkpars[2])
178  hphi0.Fill(trkpars[3])
179  hlambda.Fill(trkpars[4])
180  hdeltaphi.Fill(GetDeltaPhi(rec,itrk))
181  hdeltaphilen.Fill(GetDeltaPhi(rec,itrk)/rec.TrackLenFwd(itrk))
182 
183  hlength_fwd.Fill(rec.TrackLenFwd(itrk))
184  hlength_bkd.Fill(rec.TrackLenBkd(itrk))
185 
186  if rec.TrackMomBeg(itrk).Mag()>0 :
187  hmom_fwd.Fill(rec.TrackMomBeg(itrk).Mag())
188 
189  if rec.TrackMomEnd(itrk).Mag()>0 :
190  hmom_bkd.Fill(rec.TrackMomEnd(itrk).Mag())
191 
192  ig4ps = bt.TrackToG4Particles(itrk)
193  hng4p.Fill(len(ig4ps))
194 
195  imax = 0
196  maxp = -1.
197  sump = 0.
198  for ig4p in ig4ps :
199 
200  hg4mom.Fill(g4.SimMomEnter(ig4p)[0].P())
201  hpdg.Fill(g4.PDG(ig4p))
202  sump += g4.SimMomEnter(ig4p)[0].P()
203  if g4.SimMomEnter(ig4p)[0].P() > maxp :
204  maxp = g4.SimMomEnter(ig4p)[0].P()
205  imax = ig4p
206 
207  hg4mom1.Fill(maxp)
208  hg4mom1_frac.Fill(maxp/sump)
209  hnmom1_frac.Fill(maxp/sump,len(ig4ps))
210 
211  hpdg_max.Fill(g4.PDG(imax))
212  hpdg_max_pval.Fill(pval,g4.PDG(imax))
213 
214  posbeg = rec.TrackVertex(itrk)
215  posend = rec.TrackEnd(itrk)
216  trueposbeg = rec.TrackTruePosBeg(itrk);
217  trueposend = rec.TrackTruePosEnd(itrk);
218 
219  if trueposend.Vect().Mag() != 0 :
220  hxdiff.Fill(trueposend.X() - posend.X())
221  hydiff.Fill(trueposend.Y() - posend.Y())
222  hzdiff.Fill(trueposend.Z() - posend.Z())
223 
224 
225  if g4.PDG(imax)==13 and rec.TrackMomBeg(itrk).Mag() > 0:
226  hmomres2d.Fill(sump,rec.TrackMomBeg(itrk).Mag())
227 
228 
229  hg4mom_tot_pval.Fill(pval,maxp)
230  hmomres_diff.Fill(maxp-rec.TrackMomBeg(itrk).Mag())
231  hmomres_frac.Fill((maxp-rec.TrackMomBeg(itrk).Mag())/sump)
232  hmomres2d_pval.Fill(pval,maxp-rec.TrackMomBeg(itrk).Mag())
233  hmomres2d_frac_pval.Fill(pval,(maxp-rec.TrackMomBeg(itrk).Mag())/sump)
234 
235  # loop over G4Particles
236  for ig4p in range(g4.NSim()) :
237 
238  # track indices matched to this particle
239  itrks = bt.G4ParticleToTracks(ig4p)
240 
241  if len(itrks) > 0 : # could have no matches
242 
243  # try to avoid cathode crossers (for now)
244  if g4.IsCathodeCrosser(ig4p) : continue
245 
246  ntracks = 0
247  for itrk in itrks :
248  if len(bt.TrackToG4Particles(itrk)) > 1 : continue
249  ntracks += 1
250 
251  if ntracks==0 : continue
252 
253  hntrkpart.Fill(ntracks) #len(itrks))
254  hntrkpart_vs_mom.Fill(len(itrks),g4.SimMomEnter(ig4p,0).P())
255  hntrkpart_vs_gyro.Fill(len(itrks),3.3*g4.SimMomEnter(ig4p,0).Pt()/0.5)
256 
257  if abs(g4.PDG(ig4p)) == 2212 : # proton
258  hntrkpart_p.Fill(ntracks) #len(itrks))
259 
260  if abs(g4.PDG(ig4p)) == 13 : # mu^+/-
261  hntrkpart_mu.Fill(ntracks) #len(itrks))
262 
263  if abs(g4.PDG(ig4p)) == 211 : # pi^+/-
264  hntrkpart_pic.Fill(ntracks) #len(itrks))
265 
266  if abs(g4.PDG(ig4p)) == 11 : # e^+/-
267  hntrkpart_e.Fill(ntracks)
268 
269  for ivtx in range(rec.NVertex()) :
270  hntrkvtx.Fill(len(bt.VertexToTracks(ivtx)))
271 
272 print('fraction of all tracks with multiple MCParticle matches: '
273  + str( 1.0*(hng4p.Integral()-hng4p.GetBinContent(hng4p.FindBin(1.001)))/hng4p.Integral() ) )
274 
275 
276 #style opts
277 
278 hlength_bkd.SetLineColor(ROOT.kRed)
279 hlength_bkd.SetLineWidth(2)
280 hlength_fwd.SetLineWidth(2)
281 
282 hmom_bkd.SetLineColor(ROOT.kRed)
283 hmom_bkd.SetLineWidth(2)
284 hmom_fwd.SetLineWidth(2)
285 
286 hpdg_max.SetLineColor(ROOT.kRed)
287 hpdg_max.SetLineWidth(2)
288 hpdg.SetLineWidth(2)
289 
290 hntrkpart_p.SetLineColor(ROOT.kRed)
291 hntrkpart_mu.SetLineColor(ROOT.kGreen-1)
292 hntrkpart_pic.SetLineColor(ROOT.kOrange)
293 hntrkpart_e.SetLineColor(ROOT.kMagenta)
294 hntrkpart_p.SetLineWidth(2)
295 hntrkpart_mu.SetLineWidth(2)
296 hntrkpart_pic.SetLineWidth(2)
297 hntrkpart.SetLineWidth(2)
298 hntrkpart_e.SetLineWidth(2)
299 
300 hxdiff.SetLineWidth(2)
301 hydiff.SetLineWidth(2)
302 hzdiff.SetLineWidth(2)
303 
304 hxdiff.SetLineColor(ROOT.kRed)
305 hzdiff.SetLineColor(ROOT.kGreen-2)
306 
307 # draw our histogram and save it to file
308 clength = TCanvas()
309 hlength_fwd.Draw("ehist")
310 hlength_bkd.Draw("same ehist")
311 clength.SaveAs('track-length.png')
312 
313 cmom = TCanvas()
314 hmom_fwd.Draw("ehist")
315 hmom_bkd.Draw("same ehist")
316 cmom.SaveAs('reco_momentum.png')
317 
318 cng4p = TCanvas()
319 hng4p.Draw()
320 cng4p.SaveAs('num_g4particles_per_track.png')
321 
322 cg4mom = TCanvas()
323 hg4mom.Draw()
324 
325 
326 cg4mom1 = TCanvas()
327 hg4mom1.Draw()
328 
329 cg4mom1_frac = TCanvas()
330 hg4mom1_frac.Draw()
331 
332 cnmom1_frac = TCanvas()
333 hnmom1_frac.Draw("colz")
334 
335 cmomres2d = TCanvas()
336 hmomres2d.Draw("colz")
337 
338 cpdg = TCanvas()
339 hpdg.Draw()
340 hpdg_max.Draw("same")
341 
342 #
343 ROOT.gStyle.SetOptStat(0)
344 hntrkpart.GetXaxis().SetNdivisions(10)
345 cntrkpart = TCanvas()
346 hntrkpart_p.Draw("ehist")
347 hntrkpart_mu.Draw("same ehist")
348 hntrkpart_pic.Draw("same ehist")
349 hntrkpart_e.Draw("same ehist")
350 
351 leg = ROOT.TLegend(0.65,0.4,0.8,0.75)
352 leg.SetBorderSize(0)
353 leg.AddEntry("hntrkpart_p", "p", "L")
354 leg.AddEntry("hntrkpart_mu", "#mu^{#pm}", "L")
355 leg.AddEntry("hntrkpart_pic", "#pi^{#pm}", "L")
356 leg.AddEntry("hntrkpart_e", "e^{#pm}", "L")
357 leg.Draw()
358 cntrkpart.Modified()
359 cntrkpart.SaveAs('track_ntracks_per_mcp.png')
360 
361 cntrkpart.SetLogy()
362 cntrkpart.SaveAs('track_ntracks_per_mcp_logy.png')
363 
364 ROOT.gStyle.SetOptStat(1)
365 cmomres_diff = TCanvas()
366 hmomres_diff.Draw()
367 cmomres_diff.SaveAs('momentum_res_diff.png')
368 
369 cmomres_frac = TCanvas()
370 hmomres_frac.Draw()
371 cmomres_frac.SaveAs('momentum_res_frac.png')
372 
373 #
374 hntrack.SetLineWidth(2)
375 hntrack.GetXaxis().SetNdivisions(10)
376 cntrack = TCanvas()
377 hntrack.Draw()
378 cntrack.SaveAs('track_ntrack_per_nu.png')
379 
380 hnhit.GetXaxis().SetNdivisions(10)
381 cnhit = TCanvas()
382 hnhit.Draw()
383 cnhit.SaveAs('nhit_per_track.png')
384 
385 cmomres2d_pval = TCanvas()
386 hmomres2d_pval.Draw("colz")
387 
388 cg4mom_tot_pval = TCanvas()
389 hg4mom_tot_pval.Draw("colz")
390 
391 cpdg_max_pval = TCanvas()
392 hpdg_max_pval.Draw("colz")
393 
394 #
395 cposdiff = TCanvas()
396 hxdiff.GetYaxis().SetRangeUser(0,1.1*max((hxdiff.GetMaximum(),hydiff.GetMaximum(),hzdiff.GetMaximum())))
397 hxdiff.Draw()
398 hydiff.Draw("sames")
399 hzdiff.Draw("sames")
400 
401 legdiff = ROOT.TLegend(0.2,0.6,0.35,0.85)
402 legdiff.SetBorderSize(0)
403 legdiff.AddEntry(hxdiff,"x","l")
404 legdiff.AddEntry(hydiff,"y","l")
405 legdiff.AddEntry(hzdiff,"z","l")
406 legdiff.Draw()
407 
408 #
409 hpval.SetLineWidth(2)
410 cpval = TCanvas()
411 cpval.SetLogy()
412 hpval.Draw()
413 cpval.SaveAs('track_reco_pval.png')
414 
415 #
416 cmomfracres2d_pval = TCanvas()
417 hmomres2d_frac_pval.Draw("colz")
418 
419 #
420 hnvtx.GetXaxis().SetNdivisions(10)
421 cnvtx = TCanvas()
422 hnvtx.SetLineWidth(2)
423 hnvtx.Draw()
424 cnvtx.SaveAs('num_vertex_per_nu.png')
425 
426 #
427 hnvtxtrk.GetXaxis().SetNdivisions(10)
428 cnvtxtrk = TCanvas()
429 hnvtxtrk.SetLineWidth(2)
430 hnvtxtrk.Draw()
431 cnvtxtrk.SaveAs('num_vertex_per_track.png')
432 
433 #
434 hntrkvtx.GetXaxis().SetNdivisions(10)
435 cntrkvtx = TCanvas()
436 hntrkvtx.SetLineWidth(2)
437 hntrkvtx.Draw()
438 cnvtx.SaveAs('num_track_per_vertex.png')
439 
440 #
441 hx0.SetLineWidth(2)
442 cx0 = TCanvas()
443 hx0.Draw()
444 cx0.SaveAs('reco_x0.png')
445 
446 hy0.SetLineWidth(2)
447 cy0 = TCanvas()
448 hy0.Draw()
449 cy0.SaveAs('reco_y0.png')
450 
451 hz0.SetLineWidth(2)
452 cz0 = TCanvas()
453 hz0.Draw()
454 cz0.SaveAs('reco_z0.png')
455 
456 hr.SetLineWidth(2)
457 cr = TCanvas()
458 hr.Draw()
459 cr.SaveAs('reco_r.png')
460 
461 hphi0.SetLineWidth(2)
462 cphi0 = TCanvas()
463 hphi0.Draw()
464 cphi0.SaveAs('reco_phi0.png')
465 
466 hlambda.SetLineWidth(2)
467 clambda = TCanvas()
468 hlambda.Draw()
469 clambda.SaveAs('reco_lambda.png')
470 
471 hdeltaphi.SetLineWidth(2)
472 cdeltaphi = TCanvas()
473 hdeltaphi.Draw()
474 cdeltaphi.SaveAs('reco_delta-phi.png')
475 
476 hdeltaphilen.SetLineWidth(2)
477 cdeltaphilen = TCanvas()
478 hdeltaphilen.Draw()
479 cdeltaphilen.SaveAs('reco_delta-phi-per-length.png')
480 
481 ROOT.gStyle.SetOptStat(0)
482 cntrkpart_vs_mom = TCanvas()
483 cntrkpart_vs_mom.SetLogz()
484 hntrkpart_vs_mom.Draw("colz")
485 prof = hntrkpart_vs_mom.ProfileX()
486 prof.SetLineWidth(2)
487 prof.SetLineColor(ROOT.kRed)
488 prof.Draw('same')
489 
490 cntrkpart_vs_gyro = TCanvas()
491 cntrkpart_vs_gyro.SetLogz()
492 hntrkpart_vs_gyro.Draw("colz")
493 prof = hntrkpart_vs_gyro.ProfileX()
494 prof.SetLineWidth(2)
495 prof.SetLineColor(ROOT.kRed)
496 prof.Draw('same')
497 
498 # end draw plots
499 ########################################################################
500 # ask for user input as a way to keep the program from ending so we can
501 # see the histogram.
502 # python doesn't like empty input strings so I abuse exception handling
503 try:
504  null = input("press <Enter> to close canvas and exit program.")
505 
506 except:
507  null = 'null'
508 
def GetPhi(pos, x0, pars)
Definition: tracks.py:36
std::pair< float, std::string > P
T abs(T value)
static int input(void)
Definition: code.cpp:15695
static int max(int a, int b)
def GetTrackPars(rec, itrk)
python wrapper for track parameters array N.B.
Definition: tracks.py:23
def init()
Definition: garanainit.py:12
def GetDeltaPhi(rec, itrk)
Definition: tracks.py:60
static QCString str