Belle II Software development
eventwise_module.py
1
8
9import ROOT
10from ROOT import Belle2
11
12import numpy as np
13
14import tracking.validation.utilities as utilities
15
16import tracking.harvest.refiners as refiners
17import tracking.harvest.harvesting as harvesting
18ROOT.gSystem.Load("libtracking")
19
20
22 """Module to perform event-by-event tracking validation."""
23
24 """ Expert level behavior:
25 expert_level <= default_expert_level: all figures and plots from this module except tree entries
26 expert_level > default_expert_level: everything including tree entries
27 """
28
29
30 default_expert_level = 10
31
32 def __init__(self,
33 name,
34 contact,
35 output_file_name=None,
36 reco_tracks_name='RecoTracks',
37 mc_reco_tracks_name='MCRecoTracks',
38 expert_level=None):
39 """Constructor"""
40
41 output_file_name = output_file_name or name + 'TrackingValidation.root'
42
43 super().__init__(foreach="EventMetaData", # Dummy for on element per event
44 name=name,
45 output_file_name=output_file_name,
46 contact=contact,
47 expert_level=expert_level)
48
49 ## cached value of the RecoTracks collection name
50 self.reco_tracks_name = reco_tracks_name
51 ## cached value of the MCRecoTracks collection name
52 self.mc_reco_tracks_name = mc_reco_tracks_name
53 ## cached value of the CDCHits collection name
54 self.cdc_hits_name = "CDCHits"
55
56 def initialize(self):
57 """Initialization signal at the start of the event processing"""
58 super().initialize()
59 ## Reference to the track-match object that examines relation information from MCMatcherTracksModule
60 self.track_match_look_up = Belle2.TrackMatchLookUp(self.mc_reco_tracks_name,
61 self.reco_tracks_name)
62
63 def pick(self, event_meta_data=None):
64 """Always pick"""
65 return True
66
67 def peel(self, event_meta_data=None):
68 """Peel information from the event"""
69 # Note event_meta_data is just used as a dummy.
70
71 track_match_look_up = self.track_match_look_up
72 reco_tracks = Belle2.PyStoreArray(self.reco_tracks_name)
73 mc_reco_tracks = Belle2.PyStoreArray(self.mc_reco_tracks_name)
74 cdc_hits = Belle2.PyStoreArray(self.cdc_hits_name)
75 mc_particles = Belle2.PyStoreArray("MCParticles")
76
77 # General object count in the event.
78 if mc_particles:
79 n_mc_particles = mc_particles.getEntries()
80 else:
81 n_mc_particles = -1
82
83 if mc_reco_tracks:
84 n_mc_reco_tracks = mc_reco_tracks.getEntries()
85 else:
86 n_mc_reco_tracks = -1
87
88 n_reco_tracks = reco_tracks.getEntries()
89
90 # Aggregate information about Monte Carlo tracks
91 all_mc_tracks_det_hit_ids = set()
92 n_matched_mc_reco_tracks = 0
93 n_matched_correct_charge_mc_reco_tracks = 0
94 n_matched_wrong_charge_mc_reco_tracks = 0
95 n_merged_mc_reco_tracks = 0
96 n_merged_correct_charge_mc_reco_tracks = 0
97 n_merged_wrong_charge_mc_reco_tracks = 0
98 n_missing_mc_reco_tracks = 0
99 for mc_reco_track in mc_reco_tracks:
100 mc_reco_track_det_hit_ids = utilities.get_det_hit_ids(mc_reco_track)
101 all_mc_tracks_det_hit_ids.update(mc_reco_track_det_hit_ids)
102
103 is_matched = track_match_look_up.isAnyChargeMatchedMCRecoTrack(mc_reco_track)
104 is_matched_correct_charge = track_match_look_up.isCorrectChargeMatchedMCRecoTrack(mc_reco_track)
105 is_matched_wrong_charge = track_match_look_up.isWrongChargeMatchedMCRecoTrack(mc_reco_track)
106 is_merged = track_match_look_up.isAnyChargeMergedMCRecoTrack(mc_reco_track)
107 is_merged_correct_charge = track_match_look_up.isCorrectChargeMergedMCRecoTrack(mc_reco_track)
108 is_merged_wrong_charge = track_match_look_up.isWrongChargeMergedMCRecoTrack(mc_reco_track)
109 is_missing = track_match_look_up.isMissingMCRecoTrack(mc_reco_track)
110
111 if is_matched:
112 n_matched_mc_reco_tracks += 1
113 if is_matched_correct_charge:
114 n_matched_correct_charge_mc_reco_tracks += 1
115 elif is_matched_wrong_charge:
116 n_matched_wrong_charge_mc_reco_tracks += 1
117 elif is_merged:
118 n_merged_mc_reco_tracks += 1
119 if is_merged_correct_charge:
120 n_merged_correct_charge_mc_reco_tracks += 1
121 elif is_merged_wrong_charge:
122 n_merged_wrong_charge_mc_reco_tracks += 1
123 elif is_missing:
124 n_missing_mc_reco_tracks += 1
125
126 # Aggregate information about pattern recognition tracks
127 n_matched_reco_tracks = 0
128 n_matched_correct_charge_reco_tracks = 0
129 n_matched_wrong_charge_reco_tracks = 0
130 n_clone_reco_tracks = 0
131 n_clone_correct_charge_reco_tracks = 0
132 n_clone_wrong_charge_reco_tracks = 0
133 n_background_reco_tracks = 0
134 n_ghost_reco_tracks = 0
135
136 all_tracks_det_hit_ids = set()
137 n_matched_hits = 0
138 for reco_track in reco_tracks:
139 is_matched = track_match_look_up.isAnyChargeMatchedPRRecoTrack(reco_track)
140 is_matched_correct_charge = track_match_look_up.isCorrectChargeMatchedPRRecoTrack(reco_track)
141 is_matched_wrong_charge = track_match_look_up.isWrongChargeMatchedPRRecoTrack(reco_track)
142 is_clone = track_match_look_up.isAnyChargeClonePRRecoTrack(reco_track)
143 is_clone_correct_charge = track_match_look_up.isCorrectChargeClonePRRecoTrack(reco_track)
144 is_clone_wrong_charge = track_match_look_up.isWrongChargeClonePRRecoTrack(reco_track)
145 is_background = track_match_look_up.isBackgroundPRRecoTrack(reco_track)
146 is_ghost = track_match_look_up.isGhostPRRecoTrack(reco_track)
147
148 if is_matched:
149 n_matched_reco_tracks += 1
150 if is_matched_correct_charge:
151 n_matched_correct_charge_reco_tracks += 1
152 elif is_matched_wrong_charge:
153 n_matched_wrong_charge_reco_tracks += 1
154 elif is_clone:
155 n_clone_reco_tracks += 1
156 if is_clone_correct_charge:
157 n_clone_correct_charge_reco_tracks += 1
158 elif is_clone_wrong_charge:
159 n_clone_wrong_charge_reco_tracks += 1
160 elif is_background:
161 n_background_reco_tracks += 1
162 elif is_ghost:
163 n_ghost_reco_tracks += 1
164
165 reco_track_det_hit_ids = utilities.get_det_hit_ids(reco_track)
166
167 all_tracks_det_hit_ids.update(reco_track_det_hit_ids)
168 if is_matched or is_clone:
169 mc_reco_track = self.track_match_look_up.getRelatedMCRecoTrack(reco_track)
170
171 mc_reco_track_det_hit_ids = utilities.get_det_hit_ids(mc_reco_track)
172 n_matched_hits += len(reco_track_det_hit_ids & mc_reco_track_det_hit_ids)
173
174 return dict(
175 n_mc_particles=n_mc_particles,
176 n_mc_reco_tracks=n_mc_reco_tracks,
177 n_reco_tracks=n_reco_tracks,
178
179 n_matched_mc_reco_tracks=n_matched_mc_reco_tracks,
180 n_matched_correct_charge_mc_reco_tracks=n_matched_correct_charge_mc_reco_tracks,
181 n_matched_wrong_charge_mc_reco_tracks=n_matched_wrong_charge_mc_reco_tracks,
182
183 n_merged_mc_reco_tracks=n_merged_mc_reco_tracks,
184 n_merged_correct_charge_mc_reco_tracks=n_merged_correct_charge_mc_reco_tracks,
185 n_merged_wrong_charge_mc_reco_tracks=n_merged_wrong_charge_mc_reco_tracks,
186
187 n_missing_mc_reco_tracks=n_missing_mc_reco_tracks,
188
189
190 n_matched_reco_tracks=n_matched_reco_tracks,
191 n_matched_correct_charge_reco_tracks=n_matched_correct_charge_reco_tracks,
192 n_matched_wrong_charge_reco_tracks=n_matched_wrong_charge_reco_tracks,
193 n_clone_reco_tracks=n_clone_reco_tracks,
194 n_clone_correct_charge_reco_tracks=n_clone_correct_charge_reco_tracks,
195 n_clone_wrong_charge_reco_tracks=n_clone_wrong_charge_reco_tracks,
196
197 n_background_reco_tracks=n_background_reco_tracks,
198 n_ghost_reco_tracks=n_ghost_reco_tracks,
199
200 n_cdc_hits=cdc_hits.getEntries(),
201 n_all_mc_track_hits=len(all_mc_tracks_det_hit_ids),
202 n_all_track_hits=len(all_tracks_det_hit_ids),
203 n_found_hits=len(all_mc_tracks_det_hit_ids & all_tracks_det_hit_ids),
204 n_matched_hits=n_matched_hits
205 )
206
207 # Refiners to be executed on terminate #
208 # ==================================== #
209
210 ## Save a tree of all collected variables in a sub folder
211 save_tree = refiners.save_tree(
212 # using cond to suppress false doxygen warnings
213 ## \cond
214 folder_name="event_tree",
215 name="event_tree",
216 above_expert_level=default_expert_level
217 ## \endcond
218 )
219
220 ## Save selected hit counters
221 save_clone_rate = refiners.save_fom(
222 # using cond to suppress false doxygen warnings
223 ## \cond
224 name="{module.id}_hit_figures_of_merit",
225 title="Hit sums in {module.title}",
226 description="", # to be given
227 select=[
228 "n_cdc_hits",
229 "n_all_mc_track_hits",
230 "n_all_track_hits",
231 "n_found_hits",
232 "n_matched_hits",
233 ],
234
235 aggregation=np.sum,
236 key="{part_name}",
237 ## \endcond
238 )
__init__(self, name, contact, output_file_name=None, reco_tracks_name='RecoTracks', mc_reco_tracks_name='MCRecoTracks', expert_level=None)