Belle II Software development
PrintTrueHits.py
1#!/usr/bin/env python3
2
3
10
11import basf2 as b2
12from ROOT import Belle2
13
14b2.logging.log_level = b2.LogLevel.WARNING
15
16
17class CheckTrueHits(b2.Module):
18
19 """
20 Lists TrueHits with MCParticles and SimHits that generated them.
21 """
22
23 def __init__(self):
24 """Initialize the module"""
25
26 super().__init__()
27
29 'through': {'total': 0, 'secondary': 0, 'remapped': 0},
30 'into': {'total': 0, 'secondary': 0, 'remapped': 0},
31 'out': {'total': 0, 'secondary': 0, 'remapped': 0},
32 'inside': {'total': 0, 'secondary': 0, 'remapped': 0}
33 }
34
36 'through': {'total': 0, 'secondary': 0, 'remapped': 0},
37 'into': {'total': 0, 'secondary': 0, 'remapped': 0},
38 'out': {'total': 0, 'secondary': 0, 'remapped': 0},
39 'inside': {'total': 0, 'secondary': 0, 'remapped': 0}
40 }
41
42 def initialize(self):
43 """ Does nothing """
44
45 def beginRun(self):
46 """ Does nothing """
47
48 def event(self):
49 """
50 List VXD TrueHits, the MCParticles that generated them, related
51 SimHits, and check the reconstruction of the mid-point parameters.
52 """
53
54 pxd_truehits = Belle2.PyStoreArray('PXDTrueHits')
55 svd_truehits = Belle2.PyStoreArray('SVDTrueHits')
57
58 for truehit in pxd_truehits:
59 # Get the VXD and sensor thickness
60 id = truehit.getSensorID()
61 layer = id.getLayerNumber()
62 ladder = id.getLadderNumber()
63 sensor = id.getSensorNumber()
64 sensor_info = geocache.get(id)
65 thickness = sensor_info.getThickness()
66 base_info = \
67 f'\nPXDTrueHit {truehit.getArrayIndex()}: layer:{layer} ladder:{ladder} sensor:{sensor}'
68 # Classify the TrueHit
69 into_type = \
70 abs(abs(truehit.getEntryW()) - thickness / 2.0) < 1.0e-6
71 out_type = \
72 abs(abs(truehit.getExitW()) - thickness / 2.0) < 1.0e-6
73 through_type = into_type and out_type
74 truehit_type_text = 'inside' # should not create TrueHit
75 if through_type:
76 truehit_type_text = 'through'
77 elif into_type:
78 truehit_type_text = 'into'
79 elif out_type:
80 truehit_type_text = 'out'
81 base_info = '\n' + 'TrueHit type: ' + truehit_type_text
82 # Get the generating MCParticle and check sign of relation weight
83 mcparticle_relations = truehit.getRelationsFrom('MCParticles')
84 if mcparticle_relations.size() == 0:
85 b2.B2INFO('Found PXDTrueHit w/o relation to MCParticles')
86 continue
87 weight = mcparticle_relations.weight(0)
88 particle = mcparticle_relations[0]
89 particle_type_text = 'secondary'
90 if particle.hasStatus(Belle2.MCParticle.c_PrimaryParticle):
91 particle_type_text = 'primary'
92 mcparticle_message = f"MCParticle {particle.getArrayIndex()}: {particle_type_text + ' '}"
93 self.truehit_stats_pxd[truehit_type_text]['total'] += 1
94 if particle_type_text == 'secondary':
95 self.truehit_stats_pxd[truehit_type_text]['secondary'] += 1
96 if weight < 0:
97 self.truehit_stats_pxd[truehit_type_text]['remapped'] += 1
98 mcparticle_message += 'remapped ' + str(weight)
99 else:
100 continue
101 b2.B2INFO(base_info + '\n' + mcparticle_message)
102 # Now get and print out the SimHits
103 simhits = truehit.getRelationsTo('PXDSimHits')
104 b2.B2INFO('SimHits:')
105 for simhit in simhits:
106 particle_type_text = 'secondary'
107 simhit_weight = 0.0
108 particle_index = -1
109
110 simhit_relations = simhit.getRelationsFrom('MCParticles')
111 if simhit_relations.size() == 0:
112 particle_type_text = 'none'
113 else:
114 simhit_weight = simhit_relations.weight(0)
115 particle = simhit_relations[0]
116 particle_index = particle.getArrayIndex()
117 if particle.hasStatus(Belle2.MCParticle.c_PrimaryParticle):
118 particle_type_text = 'primary'
119 simhit_text = \
120 f'{simhit.getArrayIndex()} {particle_type_text} {particle_index} {simhit_weight:9.6f}'
121 simhit_text += \
122 f' {simhit.getPosIn().X():8.4f} {simhit.getPosIn().Y():8.4f} {simhit.getPosIn().Z():8.4f}'
123 simhit_text += \
124 f'{simhit.getGlobalTime():8.5f}'
125 b2.B2INFO(simhit_text)
126 # Print the truhit position
127 midpoint_text = 'TrueHit position:\n'
128 midpoint_text += \
129 f'IN: ({truehit.getEntryU():8.4f},{truehit.getEntryV():8.4f},{truehit.getEntryW():8.4f})\n'
130 midpoint_text += \
131 f'MID: ({truehit.getU():8.4f},{truehit.getV():8.4f},{truehit.getW():8.4f})\n'
132 midpoint_text += \
133 f'OUT: ({truehit.getExitU():8.4f},{truehit.getExitV():8.4f},{truehit.getExitW():8.4f})\n'
134 # Print the truhit momenta
135 midpoint_text += '\nTrueHit momentum:\n'
136 midpoint_text += \
137 f'IN: ({truehit.getEntryMomentum().X():8.4f},{truehit.getEntryMomentum().Y():8.4f},' + \
138 f'{truehit.getEntryMomentum().Z():8.4f})\n'
139 midpoint_text += \
140 f'MID: ({truehit.getMomentum().X():8.4f},{truehit.getMomentum().Y():8.4f},{truehit.getMomentum().Z():8.4f})\n'
141 midpoint_text += \
142 f'OUT: ({truehit.getExitMomentum().X():8.4f},{truehit.getExitMomentum().Y():8.4f},' + \
143 f'{truehit.getExitMomentum().Z():8.4f})\n'
144 # Print the truhit time
145 midpoint_text += f'Time: {truehit.getGlobalTime():8.5f}\n'
146 b2.B2INFO(midpoint_text)
147
148 for truehit in svd_truehits:
149 # Get the VXD and sensor thickness
150 id = truehit.getSensorID()
151 layer = id.getLayerNumber()
152 ladder = id.getLadderNumber()
153 sensor = id.getSensorNumber()
154 sensor_info = geocache.get(id)
155 thickness = sensor_info.getThickness()
156 base_info = \
157 f'\nSVDTrueHit {truehit.getArrayIndex()}: layer:{layer} ladder:{ladder} sensor:{sensor}'
158 # Classify the TrueHit
159 into_type = \
160 abs(abs(truehit.getEntryW()) - thickness / 2.0) < 1.0e-6
161 out_type = \
162 abs(abs(truehit.getExitW()) - thickness / 2.0) < 1.0e-6
163 through_type = into_type and out_type
164 truehit_type_text = 'inside' # should not create TrueHit
165 if through_type:
166 truehit_type_text = 'through'
167 elif into_type:
168 truehit_type_text = 'into'
169 elif out_type:
170 truehit_type_text = 'out'
171 base_info += '\n' + 'TrueHit type: ' + truehit_type_text
172 # Get the generating MCParticle and check sign of relation weight
173 mcparticle_relations = truehit.getRelationsFrom('MCParticles')
174 if mcparticle_relations.size() == 0:
175 b2.B2INFO('Found SVDTrueHit w/o relation to MCParticles')
176 continue
177 weight = mcparticle_relations.weight(0)
178 particle = mcparticle_relations[0]
179 particle_type_text = 'secondary'
180 if particle.hasStatus(Belle2.MCParticle.c_PrimaryParticle):
181 particle_type_text = 'primary'
182 mcparticle_message = f"MCParticle {particle.getArrayIndex()}: {particle_type_text + ' '}"
183 self.truehit_stats_svd[truehit_type_text]['total'] += 1
184 if particle_type_text == 'secondary':
185 self.truehit_stats_svd[truehit_type_text]['secondary'] += 1
186 if weight < 0:
187 self.truehit_stats_svd[truehit_type_text]['remapped'] += 1
188 mcparticle_message += 'remapped ' + str(weight)
189 else:
190 continue
191 b2.B2INFO(base_info + '\n' + mcparticle_message)
192 # Now get and print out the SimHits
193 simhits = truehit.getRelationsTo('SVDSimHits')
194 b2.B2INFO('SimHits:')
195 for simhit in simhits:
196 particle_type_text = 'secondary'
197 simhit_weight = 0.0
198 particle_index = -1
199
200 simhit_relations = simhit.getRelationsFrom('MCParticles')
201 if simhit_relations.size() == 0:
202 particle_type_text = 'none'
203 else:
204 simhit_weight = simhit_relations.weight(0)
205 particle = simhit_relations[0]
206 particle_index = particle.getArrayIndex()
207 if particle.hasStatus(Belle2.MCParticle.c_PrimaryParticle):
208 particle_type_text = 'primary'
209 simhit_text = \
210 f'{simhit.getArrayIndex()} {particle_type_text} {particle_index} {simhit_weight:9.6f}'
211 simhit_text += \
212 f' {simhit.getPosIn().X():8.4f} {simhit.getPosIn().Y():8.4f} {simhit.getPosIn().Z():8.4f}'
213 simhit_text += \
214 f'{simhit.getGlobalTime():8.5f} '
215 b2.B2INFO(simhit_text)
216 # Print the truhit position
217 midpoint_text = 'TrueHit position:\n'
218 midpoint_text += \
219 f'IN: ({truehit.getEntryU():8.4f},{truehit.getEntryV():8.4f},{truehit.getEntryW():8.4f})\n'
220 midpoint_text += \
221 f'MID: ({truehit.getU():8.4f},{truehit.getV():8.4f},{truehit.getW():8.4f})\n'
222 midpoint_text += \
223 f'OUT: ({truehit.getExitU():8.4f},{truehit.getExitV():8.4f},{truehit.getExitW():8.4f})\n'
224 # Print the truhit momenta
225 midpoint_text += '\nTrueHit momentum:\n'
226 midpoint_text += \
227 f'IN: ({truehit.getEntryMomentum().X():8.4f},{truehit.getEntryMomentum().Y():8.4f},' + \
228 f'{truehit.getEntryMomentum().Z():8.4f})\n'
229 midpoint_text += \
230 f'MID: ({truehit.getMomentum().X():8.4f},{truehit.getMomentum().Y():8.4f},{truehit.getMomentum().Z():8.4f})\n'
231 midpoint_text += \
232 f'OUT: ({truehit.getExitMomentum().X():8.4f},{truehit.getExitMomentum().Y():8.4f},' + \
233 f'{truehit.getExitMomentum().Z():8.4f})\n'
234 # Print the truhit time
235 midpoint_text += f'Time: {truehit.getGlobalTime():8.5f}\n'
236 b2.B2INFO(midpoint_text)
237
238 def terminate(self):
239 """ Write results """
240 b2.B2INFO(
241 f'\nStatistics for PXD: {str(self.truehit_stats_pxd)};\nStatistics for SVD: {str(self.truehit_stats_svd)}\n')
242
243
244# Particle gun module
245particlegun = b2.register_module('ParticleGun')
246# Create Event information
247eventinfosetter = b2.register_module('EventInfoSetter')
248# Show progress of processing
249progress = b2.register_module('Progress')
250# Load parameters
251gearbox = b2.register_module('Gearbox')
252# Create geometry
253geometry = b2.register_module('Geometry')
254# Run simulation
255simulation = b2.register_module('FullSim')
256# simulation.param('StoreAllSecondaries', True)
257# PXD digitization module
258printParticles = CheckTrueHits()
259printParticles.set_log_level(b2.LogLevel.INFO)
260
261# Specify number of events to generate
262eventinfosetter.param({'evtNumList': [200], 'runList': [1]})
263
264# Set parameters for particlegun
265particlegun.param({
266 'nTracks': 1,
267 'varyNTracks': True,
268 'pdgCodes': [211, -211, 11, -11],
269 'momentumGeneration': 'normalPt',
270 'momentumParams': [2, 1],
271 'phiGeneration': 'normal',
272 'phiParams': [0, 360],
273 'thetaGeneration': 'uniformCos',
274 'thetaParams': [17, 150],
275 'vertexGeneration': 'normal',
276 'xVertexParams': [0, 1],
277 'yVertexParams': [0, 1],
278 'zVertexParams': [0, 1],
279 'independentVertices': False,
280})
281
282
283# create processing path
284main = b2.create_path()
285main.add_module(eventinfosetter)
286main.add_module(progress)
287main.add_module(particlegun)
288main.add_module(gearbox)
289main.add_module(geometry)
290main.add_module(simulation)
291main.add_module(printParticles)
292
293# generate events
294b2.process(main)
295
296# show call statistics
297print(b2.statistics)
A (simplified) python wrapper for StoreArray.
Definition: PyStoreArray.h:72
static GeoCache & getInstance()
Return a reference to the singleton instance.
Definition: GeoCache.cc:214
truehit_stats_pxd
TrueHit statistics for the PXD.
truehit_stats_svd
Truehit statistics for the SVD.