Belle II Software development
ExpertTrackingValidationModule Class Reference
Inheritance diagram for ExpertTrackingValidationModule:
TrackingValidationModule

Public Member Functions

def __init__ (self, name, contact, fit=False, pulls=False, resolution=False, output_file_name=None, track_filter_object=AlwaysPassFilter(), plot_name_postfix='', plot_title_postfix='', exclude_profile_mc_parameter='', exclude_profile_pr_parameter='', use_expert_folder=True, trackCandidatesColumnName='RecoTracks', mcTrackCandidatesColumnName='MCRecoTracks', cdcHitsColumnName='CDCHits', write_tables=False)
 
def initialize (self)
 
def event (self)
 
def examine_hits_in_event (self)
 
def terminate (self)
 

Public Attributes

 cdcHitsColumnname
 cached name of the CDCHits StoreArray
 
 write_tables
 cached value of the flag to write the validation figures of merit
 
 number_of_total_hits
 number of all hits
 
 number_of_mc_hits
 number of hits on MC track
 
 number_of_pr_hits
 number of hits on pattern reconstructed tracks
 
 is_hit_found
 list of flags for [not-]found hits
 
 is_hit_matched
 list of flags for [not-]matched hits
 
 mc_missing
 list of flags where MCRecoTrack is [not] missing MCTrackCand
 
 ratio_hits_in_mc_tracks_and_not_in_pr_tracks
 list of fraction of number of hits in MC track but not in PR track
 
 ratio_hits_in_mc_tracks_and_in_pr_tracks
 list of fraction of number of hits in MC track and in PR track
 
 ratio_hits_in_missing_mc_tracks_and_in_pr_tracks
 list of fraction of number of hits in missing MC track and in PR track
 
 ratio_hits_in_mc_tracks_and_in_fake_pr_tracks
 list of fraction of number of hits in MC track and in fake PR track
 
 ratio_hits_in_mc_tracks_and_in_good_pr_tracks
 list of fraction of number of hits in MC track and in good PR track
 
 mc_is_primary
 list of flags indicating that the MC track is [not] a primary MCParticle
 
 mc_number_of_hits
 list of the number of MCTrackCandHits on the MC track
 
 number_of_connected_tracks
 This is the number of mcTrackCands sharing a hit with the track cand.
 
 number_of_wrong_hits
 This number gives information about the "badness" of the fake.
 
 pr_number_of_hits
 list of the number of pattern-reconstructed hits
 
 pr_number_of_matched_hits
 list of the number of pattern-reconstructed hits matched to MC track
 

Detailed Description

Module to collect more matching information about the found particles and to generate validation
plots and figures of merit on the performance of track finding. This module gives information on the
number of hits etc. 

Definition at line 39 of file hit_module.py.

Constructor & Destructor Documentation

◆ __init__()

def __init__ (   self,
  name,
  contact,
  fit = False,
  pulls = False,
  resolution = False,
  output_file_name = None,
  track_filter_object = AlwaysPassFilter(),
  plot_name_postfix = '',
  plot_title_postfix = '',
  exclude_profile_mc_parameter = '',
  exclude_profile_pr_parameter = '',
  use_expert_folder = True,
  trackCandidatesColumnName = 'RecoTracks',
  mcTrackCandidatesColumnName = 'MCRecoTracks',
  cdcHitsColumnName = 'CDCHits',
  write_tables = False 
)
Constructor

Reimplemented from TrackingValidationModule.

Definition at line 45 of file hit_module.py.

62 write_tables=False):
63 """Constructor"""
64
65 TrackingValidationModule.__init__(
66 self,
67 name,
68 contact,
69 fit,
70 pulls,
71 resolution,
72 output_file_name,
73 track_filter_object,
74 plot_name_postfix,
75 plot_title_postfix,
76 exclude_profile_mc_parameter,
77 exclude_profile_pr_parameter,
78 use_expert_folder,
79 trackCandidatesColumnName,
80 mcTrackCandidatesColumnName)
81
82
83 self.cdcHitsColumnname = cdcHitsColumnName
84
85 self.write_tables = write_tables
86

Member Function Documentation

◆ event()

def event (   self)
Event method

Reimplemented from TrackingValidationModule.

Definition at line 136 of file hit_module.py.

136 def event(self):
137 """Event method"""
138
139 TrackingValidationModule.event(self)
140 self.examine_hits_in_event()
141

◆ examine_hits_in_event()

def examine_hits_in_event (   self)
Classify all of the hits in the event according to the parent track(s)

Definition at line 142 of file hit_module.py.

142 def examine_hits_in_event(self):
143 """Classify all of the hits in the event according to the parent track(s)"""
144
145 trackCands = Belle2.PyStoreArray(self.trackCandidatesColumnName)
146 mcTrackCands = Belle2.PyStoreArray(self.mcTrackCandidatesColumnName)
147 if self.cdcHitsColumnname not in Belle2.PyStoreArray.list():
148 # No CDC hits available, hit analysis incomplete, don't perform
149 # hit analysis
150 return
151 cdcHits = Belle2.PyStoreArray(self.cdcHitsColumnname)
152
153 # # CDC Hits in MC tracks
154 totalHitListMC = []
155 for mcTrackCand in mcTrackCands:
156 cdcHitIDs = [cdcHit.getArrayIndex() for cdcHit in getObjectList(mcTrackCand.getCDCHitList())] # Checked
157 # Working around a bug in ROOT where you should not access empty std::vectors
158 if len(cdcHitIDs) == 0:
159 cdcHitIDs = set()
160 else:
161 cdcHitIDs = set(cdcHitIDs)
162 totalHitListMC.extend(cdcHitIDs)
163
164 # Make the ids unique
165 totalHitListMC = set(totalHitListMC)
166
167 # # CDC Hits in PR tracks
168 totalHitListPR = []
169 totalHitListPRGood = []
170 totalHitListPRClone = []
171 totalHitListPRFake = []
172 for trackCand in trackCands:
173 if trackCand.getNumberOfTotalHits() == 0:
174 basf2.B2WARNING("Encountered a pattern recognition track with no hits")
175 continue
176
177 cdcHitIDs = [cdcHit.getArrayIndex() for cdcHit in getObjectList(trackCand.getCDCHitList())] # Checked
178 # Working around a bug in ROOT where you should not access empty std::vectors
179 if len(cdcHitIDs) == 0:
180 cdcHitIDs = set()
181 else:
182 cdcHitIDs = set(cdcHitIDs)
183
184 totalHitListPR.extend(cdcHitIDs)
185 if self.trackMatchLookUp.isAnyChargeMatchedPRRecoTrack(trackCand):
186 totalHitListPRGood.extend(cdcHitIDs)
187
188 if self.trackMatchLookUp.isAnyChargeClonePRRecoTrack(trackCand):
189 totalHitListPRClone.extend(cdcHitIDs)
190
191 if (self.trackMatchLookUp.isBackgroundPRRecoTrack(trackCand) or
192 self.trackMatchLookUp.isGhostPRRecoTrack(trackCand)):
193 totalHitListPRFake.extend(cdcHitIDs)
194
195 # Make the ids unique
196 totalHitListPR = set(totalHitListPR)
197 totalHitListPRGood = set(totalHitListPRGood)
198 totalHitListPRClone = set(totalHitListPRClone)
199 totalHitListPRFake = set(totalHitListPRFake)
200
201 # # All CDC Hits
202 totalHitList = {cdcHit.getArrayIndex() for cdcHit in cdcHits}
203
204 number_of_mc_hits = len(totalHitListMC)
205 number_of_pr_hits = len(totalHitListPR)
206 number_of_all_hits = len(totalHitList)
207
208 is_hit_matched = 0
209 is_hit_found = len(totalHitListMC & totalHitListPR)
210
211 for trackCand in trackCands:
212
213 is_matched = self.trackMatchLookUp.isAnyChargeMatchedPRRecoTrack(trackCand)
214 is_clone = self.trackMatchLookUp.isAnyChargeClonePRRecoTrack(trackCand)
215
216 trackCandHits = [cdcHit.getArrayIndex() for cdcHit in getObjectList(trackCand.getCDCHitList())]
217 # Working around a bug in ROOT where you should not access empty std::vectors
218 if len(trackCandHits) == 0:
219 trackCandHits = set()
220 else:
221 trackCandHits = set(trackCandHits)
222
223 # this is not very efficient...
224 list_of_connected_mc_tracks = set()
225 list_of_numbers_of_hits_for_connected_tracks = collections.deque()
226 # number_of_connected_tracks = 0
227 # number_of_wrong_hits = 0
228
229 for mcTrackCand in mcTrackCands:
230 mcTrackCandHits = [cdcHit.getArrayIndex() for cdcHit in getObjectList(mcTrackCand.getCDCHitList())]
231 # Working around a bug in ROOT where you should not access empty std::vectors
232 if len(mcTrackCandHits) == 0:
233 mcTrackCandHits = set()
234 else:
235 mcTrackCandHits = set(mcTrackCandHits)
236
237 length_of_intersection = len(mcTrackCandHits & trackCandHits)
238 if length_of_intersection > 0:
239 list_of_connected_mc_tracks.add(mcTrackCand)
240 list_of_numbers_of_hits_for_connected_tracks.append(length_of_intersection)
241
242 if len(list_of_numbers_of_hits_for_connected_tracks) == 0:
243 self.number_of_wrong_hits.append(0)
244 self.pr_number_of_matched_hits.append(0)
245 else:
246 maximum_intersection = \
247 max(list_of_numbers_of_hits_for_connected_tracks)
248 self.pr_number_of_matched_hits.append(sum(list_of_numbers_of_hits_for_connected_tracks))
249 self.number_of_wrong_hits.append(sum(list_of_numbers_of_hits_for_connected_tracks) -
250 maximum_intersection)
251
252 self.number_of_connected_tracks.append(len(list_of_connected_mc_tracks))
253
254 if is_matched or is_clone:
255 mcTrackCand = \
256 self.trackMatchLookUp.getRelatedMCRecoTrack(trackCand)
257 mcTrackCandHits = [cdcHit.getArrayIndex() for cdcHit in getObjectList(mcTrackCand.getCDCHitList())] # Checked
258 # Working around a bug in ROOT where you should not access empty std::vectors
259 if len(mcTrackCandHits) == 0:
260 mcTrackCandHits = set()
261 else:
262 mcTrackCandHits = set(mcTrackCandHits)
263
264 is_hit_matched += len(trackCandHits & mcTrackCandHits)
265
266 self.pr_number_of_hits.append(len(trackCandHits))
267
268 for mcTrackCand in mcTrackCands:
269 is_missing = \
270 self.trackMatchLookUp.isMissingMCRecoTrack(mcTrackCand)
271
272 mcTrackCandHits = [cdcHit.getArrayIndex() for cdcHit in getObjectList(mcTrackCand.getCDCHitList())] # Checked
273
274 # Working around a bug in ROOT where you should not access empty std::vectors
275 if len(mcTrackCandHits) == 0:
276 continue
277 else:
278 mcTrackCandHits = set(mcTrackCandHits)
279
280 ratio = 1.0 * len(mcTrackCandHits & totalHitListPR) / len(mcTrackCandHits)
281
282 self.ratio_hits_in_mc_tracks_and_not_in_pr_tracks.append(1.0 - ratio)
283 self.ratio_hits_in_mc_tracks_and_in_pr_tracks.append(ratio)
284 if is_missing:
285 self.ratio_hits_in_missing_mc_tracks_and_in_pr_tracks.append(ratio)
286 self.ratio_hits_in_mc_tracks_and_in_good_pr_tracks.append(
287 1.0 * len(mcTrackCandHits & totalHitListPRGood) / len(mcTrackCandHits))
288 self.ratio_hits_in_mc_tracks_and_in_fake_pr_tracks.append(
289 1.0 * len(mcTrackCandHits & totalHitListPRFake) / len(mcTrackCandHits))
290
291 mcParticle = \
292 self.trackMatchLookUp.getRelatedMCParticle(mcTrackCand)
293 is_primary = \
294 mcParticle.hasStatus(Belle2.MCParticle.c_PrimaryParticle)
295 self.mc_is_primary.append(is_primary)
296 self.mc_number_of_hits.append(len(mcTrackCandHits))
297
298 self.mc_missing.append(is_missing)
299
300 self.number_of_total_hits.append(number_of_all_hits)
301 self.number_of_mc_hits.append(number_of_mc_hits)
302 self.number_of_pr_hits.append(number_of_pr_hits)
303
304 self.is_hit_found.append(is_hit_found)
305 self.is_hit_matched.append(is_hit_matched)
306
A (simplified) python wrapper for StoreArray.
Definition: PyStoreArray.h:72
static std::vector< std::string > list(DataStore::EDurability durability=DataStore::EDurability::c_Event)
Return list of available arrays for given durability.
Definition: PyStoreArray.cc:28

◆ initialize()

def initialize (   self)
Receive signal at the start of event processing

Reimplemented from TrackingValidationModule.

Definition at line 87 of file hit_module.py.

87 def initialize(self):
88 """Receive signal at the start of event processing"""
89 TrackingValidationModule.initialize(self)
90
91 # Use deques in favour of lists to prevent repeated memory allocation of cost O(n)
92
93 self.number_of_total_hits = collections.deque()
94
95 self.number_of_mc_hits = collections.deque()
96
97 self.number_of_pr_hits = collections.deque()
98
99 self.is_hit_found = collections.deque()
100
101 self.is_hit_matched = collections.deque()
102
103 # MC information
104
105 self.mc_missing = collections.deque()
106
107 self.ratio_hits_in_mc_tracks_and_not_in_pr_tracks = collections.deque()
108
109 self.ratio_hits_in_mc_tracks_and_in_pr_tracks = collections.deque()
110
111 self.ratio_hits_in_missing_mc_tracks_and_in_pr_tracks = collections.deque()
112
113 self.ratio_hits_in_mc_tracks_and_in_fake_pr_tracks = \
114 collections.deque()
115
116 self.ratio_hits_in_mc_tracks_and_in_good_pr_tracks = \
117 collections.deque()
118
119 self.mc_is_primary = collections.deque()
120
121 self.mc_number_of_hits = collections.deque()
122
123 # PT information
124
125 self.number_of_connected_tracks = collections.deque()
126
127 self.number_of_wrong_hits = collections.deque()
128 # It is calculated by going through all hits of the fake track and the connected mc track cands and counting the number.
129 # These numbers are than summed up and substracted by the biggest number
130 # of hits this candidates shares with the mc track cands.
131
132 self.pr_number_of_hits = collections.deque()
133
134 self.pr_number_of_matched_hits = collections.deque()
135

◆ terminate()

def terminate (   self)
Receive signal at the end of event processing

Reimplemented from TrackingValidationModule.

Definition at line 307 of file hit_module.py.

307 def terminate(self):
308 """Receive signal at the end of event processing"""
309 TrackingValidationModule.terminate(self)
310
311 output_tfile = ROOT.TFile(self.output_file_name, 'update')
312
313 validation_plots = []
314
315 # Hit ratios #
316
317 all_tracks_plot = self.profiles_by_parameters_base(
318 xs=self.ratio_hits_in_mc_tracks_and_in_pr_tracks,
319 quantity_name="ratio of hits in MCTracks found by the track finder",
320 make_hist=True,
321 parameter_names=[],
322 profile_parameters={},
323 unit=None)
324
325 validation_plots.extend(all_tracks_plot)
326
327 missing_tracks_plot = self.profiles_by_parameters_base(
328 xs=self.ratio_hits_in_missing_mc_tracks_and_in_pr_tracks,
329 quantity_name="ratio of hits in missing MCTracks found by the track finder",
330 make_hist=True,
331 parameter_names=[],
332 profile_parameters={},
333 unit=None)
334
335 validation_plots.extend(missing_tracks_plot)
336
337 for validation_plot in validation_plots:
338 validation_plot.write()
339
340 if self.write_tables:
341 # MC Figures of merit
342 mc_figures_of_merit = \
343 ValidationManyFiguresOfMerit(f'{self.validation_name}_mc_figures_of_merit')
344
345 mc_figures_of_merit['mc_pts'] = self.mc_pts
346 mc_figures_of_merit['mc_d0s'] = self.mc_d0s
347 mc_figures_of_merit['mc_matches'] = self.mc_matches
348 mc_figures_of_merit['mc_hit_efficiencies'] = self.mc_hit_efficiencies
349 mc_figures_of_merit['mc_multiplicities'] = self.mc_multiplicities
350 mc_figures_of_merit['mc_phis'] = self.mc_phi
351 mc_figures_of_merit['mc_tan_lambdas'] = self.mc_tan_lambdas
352 mc_figures_of_merit['mc_missing'] = self.mc_missing
353 mc_figures_of_merit['mc_is_primary'] = self.mc_is_primary
354 mc_figures_of_merit['mc_number_of_hits'] = self.mc_number_of_hits
355 mc_figures_of_merit['ratio_hits_in_mc_tracks_and_in_good_pr_tracks'] = \
356 self.ratio_hits_in_mc_tracks_and_in_good_pr_tracks
357 mc_figures_of_merit['ratio_hits_in_mc_tracks_and_in_fake_pr_tracks'] = \
358 self.ratio_hits_in_mc_tracks_and_in_fake_pr_tracks
359 mc_figures_of_merit['ratio_hits_in_mc_tracks_and_not_in_pr_tracks'] = \
360 self.ratio_hits_in_mc_tracks_and_not_in_pr_tracks
361
362 mc_figures_of_merit.write()
363
364 # PR Figures of merit
365 pr_figures_of_merit = \
366 ValidationManyFiguresOfMerit(f'{self.validation_name}_pr_figures_of_merit')
367
368 pr_figures_of_merit['pr_clones_and_matches'] = \
369 self.pr_clones_and_matches
370 pr_figures_of_merit['pr_matches'] = self.pr_matches
371 pr_figures_of_merit['pr_fakes'] = self.pr_fakes
372 pr_figures_of_merit['pr_number_of_hits'] = self.pr_number_of_hits
373 pr_figures_of_merit['pr_number_of_matched_hits'] = \
374 self.pr_number_of_matched_hits
375 pr_figures_of_merit['pr_seed_tan_lambdas'] = self.pr_seed_tan_lambdas
376 pr_figures_of_merit['pr_seed_phi'] = self.pr_seed_phi
377
378 pr_figures_of_merit['number_of_connected_tracks'] = \
379 self.number_of_connected_tracks
380 pr_figures_of_merit['number_of_wrong_hits'] = self.number_of_wrong_hits
381
382 pr_figures_of_merit.write()
383
384 # Hit Figures of merit
385 hit_figures_of_merit = \
386 ValidationFiguresOfMerit(f'{self.validation_name}_hit_figures_of_merit')
387
388 hit_figures_of_merit['number_of_total_hits'] = \
389 np.sum(self.number_of_total_hits)
390 hit_figures_of_merit['number_of_mc_hits'] = \
391 np.sum(self.number_of_mc_hits)
392 hit_figures_of_merit['number_of_pr_hits'] = \
393 np.sum(self.number_of_pr_hits)
394 hit_figures_of_merit['is_hit_found'] = np.sum(self.is_hit_found)
395 hit_figures_of_merit['is_hit_matched'] = np.sum(self.is_hit_matched)
396
397 print(hit_figures_of_merit)
398 hit_figures_of_merit.write()
399
400 output_tfile.Close()

Member Data Documentation

◆ cdcHitsColumnname

cdcHitsColumnname

cached name of the CDCHits StoreArray

Definition at line 83 of file hit_module.py.

◆ is_hit_found

is_hit_found

list of flags for [not-]found hits

Definition at line 99 of file hit_module.py.

◆ is_hit_matched

is_hit_matched

list of flags for [not-]matched hits

Definition at line 101 of file hit_module.py.

◆ mc_is_primary

mc_is_primary

list of flags indicating that the MC track is [not] a primary MCParticle

Definition at line 119 of file hit_module.py.

◆ mc_missing

mc_missing

list of flags where MCRecoTrack is [not] missing MCTrackCand

Definition at line 105 of file hit_module.py.

◆ mc_number_of_hits

mc_number_of_hits

list of the number of MCTrackCandHits on the MC track

Definition at line 121 of file hit_module.py.

◆ number_of_connected_tracks

number_of_connected_tracks

This is the number of mcTrackCands sharing a hit with the track cand.

Definition at line 125 of file hit_module.py.

◆ number_of_mc_hits

number_of_mc_hits

number of hits on MC track

Definition at line 95 of file hit_module.py.

◆ number_of_pr_hits

number_of_pr_hits

number of hits on pattern reconstructed tracks

Definition at line 97 of file hit_module.py.

◆ number_of_total_hits

number_of_total_hits

number of all hits

Definition at line 93 of file hit_module.py.

◆ number_of_wrong_hits

number_of_wrong_hits

This number gives information about the "badness" of the fake.

Definition at line 127 of file hit_module.py.

◆ pr_number_of_hits

pr_number_of_hits

list of the number of pattern-reconstructed hits

Definition at line 132 of file hit_module.py.

◆ pr_number_of_matched_hits

pr_number_of_matched_hits

list of the number of pattern-reconstructed hits matched to MC track

Definition at line 134 of file hit_module.py.

◆ ratio_hits_in_mc_tracks_and_in_fake_pr_tracks

ratio_hits_in_mc_tracks_and_in_fake_pr_tracks

list of fraction of number of hits in MC track and in fake PR track

Definition at line 113 of file hit_module.py.

◆ ratio_hits_in_mc_tracks_and_in_good_pr_tracks

ratio_hits_in_mc_tracks_and_in_good_pr_tracks

list of fraction of number of hits in MC track and in good PR track

Definition at line 116 of file hit_module.py.

◆ ratio_hits_in_mc_tracks_and_in_pr_tracks

ratio_hits_in_mc_tracks_and_in_pr_tracks

list of fraction of number of hits in MC track and in PR track

Definition at line 109 of file hit_module.py.

◆ ratio_hits_in_mc_tracks_and_not_in_pr_tracks

ratio_hits_in_mc_tracks_and_not_in_pr_tracks

list of fraction of number of hits in MC track but not in PR track

Definition at line 107 of file hit_module.py.

◆ ratio_hits_in_missing_mc_tracks_and_in_pr_tracks

ratio_hits_in_missing_mc_tracks_and_in_pr_tracks

list of fraction of number of hits in missing MC track and in PR track

Definition at line 111 of file hit_module.py.

◆ write_tables

write_tables

cached value of the flag to write the validation figures of merit

Definition at line 85 of file hit_module.py.


The documentation for this class was generated from the following file: