Belle II Software  release-05-02-19
mc_side_module.py
1 import basf2
2 
3 import ROOT
4 ROOT.gSystem.Load("libtracking")
5 from ROOT import Belle2
6 
7 import numpy as np
8 
9 import tracking.validation.utilities as utilities
10 
11 import tracking.harvest.refiners as refiners
12 import tracking.harvest.harvesting as harvesting
13 import tracking.harvest.peelers as peelers
14 
15 
16 class MCSideTrackingValidationModule(harvesting.HarvestingModule):
17  """Module to collect matching information about the found particles and to generate
18  validation plots and figures of merit on the performance of track finding."""
19 
20  """ Expert level behavior:
21  expert_level = default_expert_level: all figures and plots from this module except tree entries
22  expert_level > default_expert_level: everything including tree entries
23  expert_level <= default_expert_level//2: only basic figures
24  default_expert_level//2 < expert_level < default_expert_level: basic figures and basic tree entries
25  """
26 
27  default_expert_level = 10
28 
29  def __init__(
30  self,
31  name,
32  contact,
33  output_file_name=None,
34  reco_tracks_name='RecoTracks',
35  mc_reco_tracks_name='MCRecoTracks',
36  expert_level=None):
37  """Constructor"""
38 
39  output_file_name = output_file_name or name + 'TrackingValidation.root'
40 
41  super().__init__(foreach=mc_reco_tracks_name,
42  name=name,
43  output_file_name=output_file_name,
44  contact=contact,
45  expert_level=expert_level)
46 
47 
48  self.reco_tracks_name = reco_tracks_name
49 
50 
51  self.mc_reco_tracks_name = mc_reco_tracks_name
52 
53 
54  self.track_match_look_up = None
55 
56  if self.expert_level >= self.default_expert_level:
57 
58  self.found_det_hit_ids = set()
59 
60 
61  self.matched_det_hit_ids = set()
62 
63 
64  self.clone_det_hit_ids = set()
65 
66 
67  self.fake_det_hit_ids = set()
68 
69  def initialize(self):
70  """Initialization signal at the start of the event processing"""
71  super().initialize()
73 
74  def prepare(self):
75  """Collect some statistics about the pattern recognition tracks used for comparision to the MC tracks
76 
77  Executed once at the start of each event.
78  """
79  super().prepare()
80  if self.expert_level >= self.default_expert_level:
81  reco_tracks = Belle2.PyStoreArray(self.reco_tracks_name)
82  track_match_look_up = self.track_match_look_up
83 
84  found_det_hit_ids = set()
85  matched_det_hit_ids = set()
86  clone_det_hit_ids = set()
87  fake_det_hit_ids = set()
88 
89  for reco_track in reco_tracks:
90  det_hit_ids = utilities.get_det_hit_ids(reco_track)
91 
92  found_det_hit_ids |= det_hit_ids
93 
94  if track_match_look_up.isMatchedPRRecoTrack(reco_track):
95  matched_det_hit_ids |= det_hit_ids
96 
97  if track_match_look_up.isClonePRRecoTrack(reco_track):
98  clone_det_hit_ids |= det_hit_ids
99 
100  if (track_match_look_up.isGhostPRRecoTrack(reco_track) or
101  track_match_look_up.isBackgroundPRRecoTrack(reco_track)):
102  fake_det_hit_ids |= det_hit_ids
103 
104  self.found_det_hit_ids = found_det_hit_ids
105  self.matched_det_hit_ids = matched_det_hit_ids
106  self.clone_det_hit_ids = clone_det_hit_ids
107  self.fake_det_hit_ids = fake_det_hit_ids
108 
109  def pick(self, mc_reco_track):
110  """Pick every MCRecoTrack"""
111  return True
112 
113  def peel(self, mc_reco_track):
114  """Looks at the individual Monte Carlo tracks and store information about them"""
115  track_match_look_up = self.track_match_look_up
116 
117  # Analyse from the Monte Carlo reference side
118  mc_reco_tracks = Belle2.PyStoreArray(self.foreach)
119  multiplicity = mc_reco_tracks.getEntries()
120 
121  mc_particle = track_match_look_up.getRelatedMCParticle(mc_reco_track)
122  is_primary = bool(mc_particle.hasStatus(Belle2.MCParticle.c_PrimaryParticle))
123  mc_to_pr_match_info_crops = self.peel_mc_to_pr_match_info(mc_reco_track)
124  mc_store_array_crops = peelers.peel_store_array_info(mc_reco_track, key="mc_{part_name}")
125 
126  crops = dict(is_primary=is_primary,
127  multiplicity=multiplicity,
128  **mc_to_pr_match_info_crops,
129  **mc_store_array_crops
130  )
131 
132  if self.expert_level >= self.default_expert_level:
133  reco_track = track_match_look_up.getRelatedPRRecoTrack(mc_reco_track)
134  mc_particle_crops = peelers.peel_mc_particle(mc_particle)
135  hit_content_crops = peelers.peel_reco_track_hit_content(mc_reco_track)
136 
137  # Custom peel function to get single detector hit purities
138  subdetector_hit_efficiency_crops = peelers.peel_subdetector_hit_efficiency(mc_reco_track, reco_track)
139 
140  mc_hit_efficiencies_in_all_pr_tracks_crops = self.peel_hit_efficiencies_in_all_pr_tracks(mc_reco_track)
141 
142  # Event Info
143  event_meta_data = Belle2.PyStoreObj("EventMetaData")
144  event_crops = peelers.peel_event_info(event_meta_data)
145 
146  # Store Array for easier joining
147  store_array_crops = peelers.peel_store_array_info(reco_track, key="pr_{part_name}")
148 
149  # Information on PR reco track
150  pr_purity_information = {
151  "pr_hit_purity": track_match_look_up.getRelatedPurity(reco_track) if reco_track else float("nan"),
152  **peelers.peel_subdetector_hit_purity(reco_track=reco_track, mc_reco_track=mc_reco_track,
153  key="pr_{part_name}")
154  }
155 
156  # Information on TrackFinders
157  trackfinder_crops = peelers.peel_trackfinder(reco_track)
158 
159  # Basic peel function to get Quality Indicators
160  qualityindicator_crops = peelers.peel_quality_indicators(reco_track)
161 
162  crops.update(dict(**hit_content_crops,
163  **mc_particle_crops,
164  **subdetector_hit_efficiency_crops,
165  **mc_hit_efficiencies_in_all_pr_tracks_crops,
166  **event_crops,
167  **store_array_crops,
168  **pr_purity_information,
169  **trackfinder_crops,
170  **qualityindicator_crops
171  ))
172 
173  return crops
174 
175  def peel_mc_to_pr_match_info(self, mc_reco_track):
176  """Extracts track-match information from the MCMatcherTracksModule results"""
177  track_match_look_up = self.track_match_look_up
178  return dict(
179  is_matched=track_match_look_up.isMatchedMCRecoTrack(mc_reco_track),
180  is_merged=track_match_look_up.isMergedMCRecoTrack(mc_reco_track),
181  is_missing=track_match_look_up.isMissingMCRecoTrack(mc_reco_track),
182  hit_efficiency=track_match_look_up.getRelatedEfficiency(mc_reco_track),
183  )
184 
185  def peel_hit_efficiencies_in_all_pr_tracks(self, mc_reco_track):
186  """Extracts hit efficiencies"""
187  mc_det_hit_ids = utilities.get_det_hit_ids(mc_reco_track)
188 
189  hit_efficiency_in_all_found = utilities.calc_hit_efficiency(self.found_det_hit_ids,
190  mc_det_hit_ids)
191 
192  unfound_hit_efficiency = 1.0 - hit_efficiency_in_all_found
193 
194  hit_efficiency_in_all_matched = utilities.calc_hit_efficiency(self.matched_det_hit_ids,
195  mc_det_hit_ids)
196 
197  hit_efficiency_in_all_fake = utilities.calc_hit_efficiency(self.fake_det_hit_ids,
198  mc_det_hit_ids)
199 
200  hit_efficiency_crops = dict(
201  hit_efficiency_in_all_found=hit_efficiency_in_all_found,
202  unfound_hit_efficiency=unfound_hit_efficiency,
203  hit_efficiency_in_all_matched=hit_efficiency_in_all_matched,
204  hit_efficiency_in_all_fake=hit_efficiency_in_all_fake,
205  )
206  return hit_efficiency_crops
207 
208  # Refiners to be executed on terminate #
209  # #################################### #
210 
211 
212  save_tree = refiners.save_tree(name="mc_tree", folder_name="mc_tree", above_expert_level=default_expert_level)
213 
214 
215  save_tree_basic = refiners.save_tree(name="mc_tree", folder_name="mc_tree",
216  above_expert_level=default_expert_level // 2, below_expert_level=default_expert_level)
217 
218 
219  save_overview_figures_of_merit = refiners.save_fom(
220  name="{module.id}_overview_figures_of_merit",
221  title="Overview figures in {module.title}",
222  aggregation=np.nanmean,
223  key="{part_name}",
224  select={"is_matched": "finding efficiency", "hit_efficiency": "hit efficiency", },
225  filter_on="is_primary",
226  description="""
227 finding efficiency - the ratio of matched primary Monte Carlo tracks to all Monte Carlo tracks
228 hit efficiency - the ratio of hits picked up by the matched pattern recognition track of primary Monte Carlo tracks
229 """
230  )
231 
232  # Default refiners that can be disabled with a lower expert_level
233  # #################################### #
234 
235 
236  save_hit_efficiency_histogram = refiners.save_histograms(
237  above_expert_level=default_expert_level - 1,
238  select={"hit_efficiency": "hit efficiency"},
239  filter_on="is_primary",
240  description="Not a serious plot yet.",
241  )
242 
243 
244  renaming_select_for_finding_efficiency_profiles = {
245  'is_matched': 'finding efficiency',
246  'd0_truth': 'd_{0}',
247  'pt_truth': 'p_{t}',
248  'multiplicity': 'multiplicity',
249  'phi0_truth': '#phi',
250  }
251 
252 
253  save_finding_efficiency_profiles = refiners.save_profiles(
254  above_expert_level=default_expert_level - 1,
255  select=renaming_select_for_finding_efficiency_profiles,
256  y='finding efficiency',
257  y_binary=True,
258  filter_on="is_primary",
259  outlier_z_score=5.0,
260  allow_discrete=True,
261  )
262 
263 
264  save_finding_efficiency_by_tan_lamba_profiles = refiners.save_profiles(
265  above_expert_level=default_expert_level - 1,
266  select={
267  'is_matched': 'finding efficiency',
268  'tan_lambda_truth': 'tan #lambda'
269  },
270  y='finding efficiency',
271  y_binary=True,
272  filter_on="is_primary",
273  outlier_z_score=5.0,
274  lower_bound=-1.73,
275  upper_bound=3.27,
276  )
277 
278 
279  save_finding_efficiency_by_tan_lamba_in_pt_groups_profiles = refiners.save_profiles(
280  above_expert_level=default_expert_level - 1,
281  select={
282  'is_matched': 'finding efficiency',
283  'tan_lambda_truth': 'tan #lambda'
284  },
285  y='finding efficiency',
286  y_binary=True,
287  filter_on="is_primary",
288  groupby=[("pt_truth", [0.070, 0.250, 0.600])],
289  outlier_z_score=5.0,
290  lower_bound=-1.73,
291  upper_bound=3.27,
292  )
293 
294  # Make profiles of the hit efficiencies versus various fit parameters
295 
296  renaming_select_for_hit_efficiency_profiles = {
297  'hit_efficiency': 'hit efficiency',
298  'd0_truth': 'd_{0}',
299  'pt_truth': 'p_{t}',
300  'multiplicity': 'multiplicity',
301  'phi0_truth': '#phi',
302  }
303 
304 
305  save_hit_efficiency_profiles = refiners.save_profiles(
306  above_expert_level=default_expert_level - 1,
307  select=renaming_select_for_hit_efficiency_profiles,
308  y='hit efficiency',
309  y_binary=True,
310  filter_on="is_primary",
311  outlier_z_score=5.0,
312  allow_discrete=True,
313  )
314 
315 
316  save_hit_efficiency_by_tan_lambda_profiles = refiners.save_profiles(
317  above_expert_level=default_expert_level - 1,
318  select={
319  'hit_efficiency': 'hit efficiency',
320  'tan_lambda_truth': 'tan #lambda',
321  },
322  y='hit efficiency',
323  y_binary=True,
324  filter_on="is_primary",
325  outlier_z_score=5.0,
326  lower_bound=-1.73,
327  upper_bound=3.27,
328  )
329 
330 
333  save_hit_efficiency_in_all_found_hist = refiners.save_histograms(
334  above_expert_level=default_expert_level - 1,
335  # renaming quantity to name that is more suitable for display
336  select=dict(hit_efficiency_in_all_found="total hit efficiency vs. all reconstructed tracks")
337  )
338 
339 
342  save_missing_mc_tracks_hit_efficiency_in_all_found_hist = refiners.save_histograms(
343  above_expert_level=default_expert_level - 1,
344  filter_on="is_missing", # show only the efficiencies of missing mc tracks
345  # renaming quantity to name that is more suitable for display
346  select=dict(hit_efficiency_in_all_found="total hit efficiency in all reconstructed tracks for missing mc tracks")
347  )
tracking.harvesting_validation.mc_side_module.MCSideTrackingValidationModule
Definition: mc_side_module.py:16
tracking.harvest.refiners
Definition: refiners.py:1
tracking.harvesting_validation.mc_side_module.MCSideTrackingValidationModule.reco_tracks_name
reco_tracks_name
Name of the StoreArray of the tracks from pattern recognition.
Definition: mc_side_module.py:41
tracking.harvesting_validation.mc_side_module.MCSideTrackingValidationModule.mc_reco_tracks_name
mc_reco_tracks_name
Name of the StoreArray of the ideal mc tracks.
Definition: mc_side_module.py:44
tracking.harvesting_validation.mc_side_module.MCSideTrackingValidationModule.peel
def peel(self, mc_reco_track)
Definition: mc_side_module.py:113
tracking.harvesting_validation.mc_side_module.MCSideTrackingValidationModule.__init__
def __init__(self, name, contact, output_file_name=None, reco_tracks_name='RecoTracks', mc_reco_tracks_name='MCRecoTracks', expert_level=None)
Definition: mc_side_module.py:29
Belle2::PyStoreObj
a (simplified) python wrapper for StoreObjPtr.
Definition: PyStoreObj.h:69
Belle2::TrackMatchLookUp
Class to provide convenient methods to look up matching information between pattern recognition and M...
Definition: TrackMatchLookUp.h:43
tracking.harvest.harvesting
Definition: harvesting.py:1
tracking.harvesting_validation.mc_side_module.MCSideTrackingValidationModule.found_det_hit_ids
found_det_hit_ids
Set of all detector and hits ids contained in any pr track.
Definition: mc_side_module.py:51
tracking.harvest.peelers
Definition: peelers.py:1
tracking.harvesting_validation.mc_side_module.MCSideTrackingValidationModule.clone_det_hit_ids
clone_det_hit_ids
Set of all detector and hits ids contained in clone pr tracks.
Definition: mc_side_module.py:57
tracking.harvesting_validation.mc_side_module.MCSideTrackingValidationModule.track_match_look_up
track_match_look_up
Reference to the track match lookup object reading the relation information constructed by the MCMatc...
Definition: mc_side_module.py:47
tracking.harvesting_validation.mc_side_module.MCSideTrackingValidationModule.pick
def pick(self, mc_reco_track)
Definition: mc_side_module.py:109
tracking.harvesting_validation.mc_side_module.MCSideTrackingValidationModule.peel_hit_efficiencies_in_all_pr_tracks
def peel_hit_efficiencies_in_all_pr_tracks(self, mc_reco_track)
Definition: mc_side_module.py:185
tracking.harvesting_validation.mc_side_module.MCSideTrackingValidationModule.default_expert_level
int default_expert_level
the threshold value for the expert level
Definition: mc_side_module.py:27
tracking.harvesting_validation.mc_side_module.MCSideTrackingValidationModule.fake_det_hit_ids
fake_det_hit_ids
Set of all detector and hits ids contained in background and ghost pr tracks.
Definition: mc_side_module.py:60
tracking.harvesting_validation.mc_side_module.MCSideTrackingValidationModule.matched_det_hit_ids
matched_det_hit_ids
Set of all detector and hits ids contained in matched pr tracks.
Definition: mc_side_module.py:54
tracking.validation.utilities
Definition: utilities.py:1
Belle2::PyStoreArray
a (simplified) python wrapper for StoreArray.
Definition: PyStoreArray.h:58
tracking.harvesting_validation.mc_side_module.MCSideTrackingValidationModule.initialize
def initialize(self)
Definition: mc_side_module.py:69
tracking.harvesting_validation.mc_side_module.MCSideTrackingValidationModule.peel_mc_to_pr_match_info
def peel_mc_to_pr_match_info(self, mc_reco_track)
Definition: mc_side_module.py:175
tracking.harvesting_validation.mc_side_module.MCSideTrackingValidationModule.prepare
def prepare(self)
Definition: mc_side_module.py:74