Belle II Software  release-08-01-10
testCosmicT0Finder.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 
4 
11 
12 # ---------------------------------------------------------------------------------
13 # Test of performance and validation of TOPCosmicT0Finder with simulation
14 # Input file can be prepared with top/examples/simGCRData.py
15 # Output ntuple to cosmicT0FinderNtuple.root
16 # ---------------------------------------------------------------------------------
17 
18 import basf2 as b2
19 from ROOT import Belle2
20 from ROOT import TH1F
21 from ROOT import gROOT, addressof
22 import math
23 import ROOT
24 from ROOT.Math import XYZVector
25 
26 timeShift = 100 # ns (can be arbitrary chosen)
27 
28 
29 class ShiftDigits(b2.Module):
30  ''' shift digits in time by timeShift'''
31 
32  def event(self):
33  ''' event processing '''
34 
35  digits = Belle2.PyStoreArray('TOPDigits')
36  for digit in digits:
37  digit.setTime(digit.getTime() + timeShift)
38 
39 
40 gROOT.ProcessLine('struct TreeStruct {\
41  int slot; /* slot number */ \
42  int nfot; /* number of photons in the slot */ \
43  int pdg; /* PDG code from barHit */ \
44  float x; /* local x from barHit */ \
45  float y; /* local y from barHit */ \
46  float z; /* local z from barHit */ \
47  float t; /* time from barHit */ \
48  float p; /* momentum from barHit */ \
49  float theta; /* momentum theta [deg] from barHit */ \
50  float phi; /* momentum local phi [deg] from barHit */ \
51  float dx; /* extHit - barHit difference in local x */ \
52  float dy; /* extHit - barHit difference in local y */ \
53  float dz; /* extHit - barHit difference in local z */ \
54  float dt; /* extHit - barHit difference in time */ \
55  float dp; /* extHit - barHit difference in momentum */ \
56  float dtheta; /* extHit - barHit difference in theta [deg] */ \
57  float dphi; /* extHit - barHit difference in local phi [deg] */ \
58  float t0; /* t0 determined by TOPCosmicT0Finder */ \
59  float t0err; /* error on t0 */ \
60  float timeShift; /* time shift applied to TOPDigits */ \
61  float dt0; /* difference: dt + t0 - timeShift */ \
62 };')
63 
64 from ROOT import TreeStruct # noqa
65 
66 
67 class Ntuple(b2.Module):
68  ''' makes ntuple for MC studies of TOPCosmicT0Finder performance '''
69 
70  def initialize(self):
71  ''' initialize '''
72 
73 
74  self.filefile = ROOT.TFile('cosmicT0FinderNtuple.root', 'recreate')
75 
76  self.treetree = ROOT.TTree('tree', '')
77 
78  self.datadata = TreeStruct()
79 
80  for key in TreeStruct.__dict__.keys():
81  if '__' not in key:
82  formstring = '/F'
83  if isinstance(self.datadata.__getattribute__(key), int):
84  formstring = '/I'
85  self.treetree.Branch(key, addressof(self.datadata, key), key + formstring)
86 
87 
88  self.resoreso = TH1F('reso', 'T0 residuals', 200, -1.0, 1.0)
89  self.resoreso.SetXTitle('#Delta t0 [ns]')
90 
91  self.pullpull = TH1F('pull', 'T0 pulls', 200, -10.0, 10.0)
92 
93  def event(self):
94  ''' event processing: fill ntuple and histograms '''
95 
96  mcParticles = Belle2.PyStoreArray('MCParticles')
97  timeZeros = Belle2.PyStoreArray('TOPTimeZeros')
98  geo = Belle2.TOP.TOPGeometryPar.Instance().getGeometry()
99  for timeZero in timeZeros:
100  extHit = timeZero.getRelated('ExtHits')
101  if not extHit:
102  b2.B2WARNING('no related extHits')
103  continue
104  barHit = None
105  for barhit in mcParticles[0].getRelationsWith('TOPBarHits'):
106  if barhit.getModuleID() == extHit.getCopyID():
107  barHit = barhit
108  if not barHit:
109  b2.B2WARNING('no corresponding TOPBarHit')
110  continue
111 
112  moduleID = timeZero.getModuleID()
113  if extHit.getCopyID() != moduleID:
114  b2.B2ERROR('moduleID in extHit differs: ' + str(extHit.getCopyID()) +
115  ' ' + str(moduleID))
116  if barHit.getModuleID() != moduleID:
117  b2.B2ERROR('moduleID in barHit differs: ' + str(barHit.getModuleID()) +
118  ' ' + str(moduleID))
119 
120  self.datadata.slot = moduleID
121  self.datadata.nfot = timeZero.getNumPhotons()
122  self.datadata.pdg = barHit.getPDG()
123  pos = barHit.getLocalPosition()
124  self.datadata.x = pos.X()
125  self.datadata.y = pos.Y()
126  self.datadata.z = pos.Z()
127  self.datadata.t = barHit.getTime()
128  module = geo.getModule(moduleID)
129  mom = module.momentumToLocal(barHit.getMomentum())
130  self.datadata.p = mom.R()
131  self.datadata.theta = math.degrees(mom.Theta())
132  self.datadata.phi = math.degrees(mom.Phi())
133  dr = module.momentumToLocal(extHit.getPosition() - XYZVector(barHit.getPosition()))
134  self.datadata.dx = dr.X()
135  self.datadata.dy = dr.Y()
136  self.datadata.dz = dr.Z()
137  self.datadata.dt = extHit.getTOF() - self.datadata.t
138  momExt = module.momentumToLocal(extHit.getMomentum())
139  self.datadata.dp = momExt.R() - self.datadata.p
140  self.datadata.dtheta = math.degrees(momExt.Theta()) - self.datadata.theta
141  self.datadata.dphi = math.degrees(momExt.Phi()) - self.datadata.phi
142  self.datadata.t0 = timeZero.getTime()
143  self.datadata.t0err = timeZero.getError()
144  self.datadata.timeShift = timeShift
145  self.datadata.dt0 = self.datadata.dt + self.datadata.t0 - self.datadata.timeShift
146  self.filefile.cd()
147  self.treetree.Fill()
148  self.resoreso.Fill(self.datadata.dt0)
149  self.pullpull.Fill(self.datadata.dt0/self.datadata.t0err)
150  if timeZero.getChi2().GetEntries() > 0:
151  timeZero.getChi2().Write()
152  timeZero.getPDF().Write()
153  timeZero.getHits().Write()
154 
155  def terminate(self):
156  ''' terminate: write and close root file '''
157 
158  self.filefile.cd()
159  self.filefile.Write()
160  self.filefile.Close()
161 
162 
163 # Suppress messages and warnings during processing:
164 b2.set_log_level(b2.LogLevel.WARNING)
165 
166 # Create path
167 main = b2.create_path()
168 
169 # input
170 roinput = b2.register_module('RootInput')
171 main.add_module(roinput)
172 
173 # Initialize TOP geometry parameters (creation of Geant geometry is not needed)
174 main.add_module('TOPGeometryParInitializer')
175 
176 # shift digits in time
177 main.add_module(ShiftDigits())
178 
179 # t0 finder
180 finder = b2.register_module('TOPCosmicT0Finder')
181 finder.param('useIncomingTrack', False) # or True
182 # finder.param('saveHistograms', True)
183 main.add_module(finder)
184 
185 # ntuple
186 main.add_module(Ntuple())
187 
188 # Print progress
189 main.add_module('Progress')
190 
191 # Process events
192 b2.process(main)
193 
194 # Print statistics
195 print(b2.statistics)
A (simplified) python wrapper for StoreArray.
Definition: PyStoreArray.h:72
static TOPGeometryPar * Instance()
Static method to obtain the pointer to its instance.
data
data structure to be written to tree
reso
histogram of t0 residuals
pull
histogram of t0 pulls