4 ROOT.gSystem.Load(
"libtracking")
5 from ROOT
import Belle2
20 """Module to collect matching information about the found particles and to generate
21 validation plots and figures of merit on the performance of track finding."""
23 """ Expert level behavior:
24 expert_level <= default_expert_level: all figures and plots from this module except tree entries
25 expert_level > default_expert_level: everything including tree entries
28 default_expert_level = 10
34 output_file_name=None,
35 reco_tracks_name='RecoTracks',
36 mc_reco_tracks_name='MCRecoTracks',
40 output_file_name = output_file_name
or name +
'TrackingValidation.root'
44 output_file_name=output_file_name,
45 expert_level=expert_level)
63 """Receive signal at the start of event processing"""
69 """Called once at the start of each event"""
72 mc_reco_tracks_det_hit_ids = []
74 for mc_reco_track
in mc_reco_tracks:
75 mc_reco_track_det_hit_ids = utilities.get_det_hit_ids(mc_reco_track)
76 mc_reco_tracks_det_hit_ids.append(mc_reco_track_det_hit_ids)
82 def pick(self, reco_track):
83 """Method to filter the track candidates to reject part of them"""
86 def peel(self, reco_track):
87 """Looks at the individual pattern recognition tracks and store information about them"""
91 mc_reco_track = track_match_look_up.getRelatedMCRecoTrack(reco_track)
92 mc_particle = track_match_look_up.getRelatedMCParticle(reco_track)
93 mc_particle_crops = peelers.peel_mc_particle(mc_particle)
95 hit_content_crops = peelers.peel_reco_track_hit_content(reco_track)
100 subdetector_hit_purity_crops = peelers.peel_subdetector_hit_purity(reco_track, mc_reco_track)
103 trackfinder_crops = peelers.peel_trackfinder(reco_track)
106 qualityindicator_crops = peelers.peel_quality_indicators(reco_track)
109 seed_fit_crops = peelers.peel_reco_track_seed(reco_track)
111 fit_result = track_match_look_up.getRelatedTrackFitResult(reco_track)
112 fit_crops = peelers.peel_track_fit_result(fit_result)
113 fit_status_crops = peelers.peel_fit_status(reco_track)
115 correct_rl_information = sum(peelers.is_correct_rl_information(cdc_hit, reco_track, self.
mc_hit_lookup)
116 for cdc_hit
in reco_track.getCDCHitList())
119 correct_rl_information=correct_rl_information,
122 **pr_to_mc_match_info_crops,
123 **subdetector_hit_purity_crops,
125 **qualityindicator_crops,
135 event_crops = peelers.peel_event_info(event_meta_data)
138 store_array_crops = peelers.peel_store_array_info(reco_track, key=
"pr_{part_name}")
139 mc_store_array_crops = peelers.peel_store_array_info(mc_reco_track, key=
"mc_{part_name}")
142 mc_efficiency_information = {
143 "mc_hit_efficiency": track_match_look_up.getRelatedEfficiency(mc_reco_track)
if mc_reco_track
else float(
"nan"),
144 **peelers.peel_subdetector_hit_efficiency(reco_track=reco_track, mc_reco_track=mc_reco_track,
145 key=
"mc_{part_name}")
151 **mc_store_array_crops,
152 **mc_efficiency_information
158 """Extracts track-match information from the MCMatcherTracksModule results"""
160 is_matched = track_match_look_up.isMatchedPRRecoTrack(reco_track)
161 is_clone = track_match_look_up.isClonePRRecoTrack(reco_track)
162 is_background = track_match_look_up.isBackgroundPRRecoTrack(reco_track)
163 is_ghost = track_match_look_up.isGhostPRRecoTrack(reco_track)
165 reco_track_det_hit_ids = utilities.get_det_hit_ids(reco_track)
166 n_intersecting_mc_tracks = 0
168 intersects = len(mc_reco_track_det_hit_ids & reco_track_det_hit_ids) > 0
170 n_intersecting_mc_tracks += 1
172 mc_particle = track_match_look_up.getRelatedMCParticle(reco_track)
173 mc_is_primary =
False
175 mc_is_primary = bool(mc_particle.hasStatus(Belle2.MCParticle.c_PrimaryParticle))
178 is_matched=is_matched,
179 is_matchedPrimary=is_matched
and mc_is_primary,
181 is_background=is_background,
183 is_clone_or_match=(is_matched
or is_clone),
184 is_fake=
not (is_matched
or is_clone),
185 hit_purity=track_match_look_up.getRelatedPurity(reco_track),
186 n_intersecting_mc_tracks=n_intersecting_mc_tracks,
193 save_tree = refiners.save_tree(folder_name=
"pr_tree", name=
"pr_tree", above_expert_level=default_expert_level)
196 save_clone_rate = refiners.save_fom(
197 name=
"{module.id}_overview_figures_of_merit",
199 title=
"Overview figures in {module.title}",
200 description=
"clone_rate - ratio of clones divided the number of tracks that are related to a particle (clones and matches)",
204 filter_on=
"is_clone_or_match",
209 save_clone_rate_by_seed_tan_lambda_profile = refiners.save_profiles(
210 filter_on=
"is_clone_or_match",
212 'is_clone':
'clone rate',
213 'seed_tan_lambda_estimate':
'seed tan #lambda',
225 save_clone_rate_by_seed_phi0_profile = refiners.save_profiles(
227 'is_clone':
'clone rate',
228 'seed_phi0_estimate':
'seed #phi',
238 save_clone_rate_by_seed_pt_profile = refiners.save_profiles(
239 filter_on=
"is_clone_or_match",
241 'is_clone':
'clone rate',
242 'seed_pt_estimate':
'seed p_{t}',
253 save_fake_rate = refiners.save_fom(
254 name=
"{module.id}_overview_figures_of_merit",
256 title=
"Overview figures in {module.title}",
257 description=
"fake_rate - ratio of pattern recognition tracks that are not related to a particle" +
258 "(background, ghost) to all pattern recognition tracks",
266 save_fake_rate_by_seed_phi0_profile = refiners.save_profiles(
268 'is_fake':
'fake rate',
269 'seed_phi0_estimate':
'seed #phi',
278 save_fake_rate_by_seed_tan_lambda_profile = refiners.save_profiles(
280 'is_fake':
'fake rate',
281 'seed_tan_lambda_estimate':
'seed tan #lambda',
292 save_fake_rate_by_seed_pt_profile = refiners.save_profiles(
294 'is_fake':
'fake rate',
295 'seed_pt_estimate':
'seed p_{t}',
305 save_hit_counts_by_pt_profile = refiners.save_profiles(
306 filter_on=
"is_matched",
308 "pt_truth":
"true p_{t}",
309 "n_pxd_hits":
"pxd hits",
310 "n_svd_hits":
"svd hits",
311 "n_cdc_hits":
"cdc hits",
321 save_hit_efficiency_by_pt_profile = refiners.save_profiles(
322 filter_on=
"is_matchedPrimary",
324 "pt_truth":
"true p_{t}",
325 "mc_pxd_hit_efficiency":
"pxd hit efficiency",
326 "mc_svd_hit_efficiency":
"svd hit efficiency",
327 "mc_cdc_hit_efficiency":
"cdc hit efficiency",
330 "pxd hit efficiency",
331 "svd hit efficiency",
332 "cdc hit efficiency",
337 save_hit_purity_by_pt_profile = refiners.save_profiles(
338 filter_on=
"is_matchedPrimary",
340 "pt_truth":
"true p_{t}",
341 "pxd_hit_purity":
"pxd hit purity",
342 "svd_hit_purity":
"svd hit purity",
343 "cdc_hit_purity":
"cdc hit purity",
353 save_hit_counts_by_tanlambda_profile = refiners.save_profiles(
354 filter_on=
"is_matched",
356 "tan_lambda_truth":
"true tan #lambda",
357 "n_pxd_hits":
"pxd hits",
358 "n_svd_hits":
"svd hits",
359 "n_cdc_hits":
"cdc hits",
369 save_hit_efficiency_by_tanlambda_profile = refiners.save_profiles(
370 filter_on=
"is_matchedPrimary",
372 "tan_lambda_truth":
"true tan #lambda",
373 "mc_pxd_hit_efficiency":
"pxd hit efficiency",
374 "mc_svd_hit_efficiency":
"svd hit efficiency",
375 "mc_cdc_hit_efficiency":
"cdc hit efficiency",
378 "pxd hit efficiency",
379 "svd hit efficiency",
380 "cdc hit efficiency",
385 save_hit_purity_by_tanlambda_profile = refiners.save_profiles(
386 filter_on=
"is_matchedPrimary",
388 "tan_lambda_truth":
"true tan #lambda",
389 "pxd_hit_purity":
"pxd hit purity",
390 "svd_hit_purity":
"svd hit purity",
391 "cdc_hit_purity":
"cdc hit purity",
401 save_hit_efficiency = refiners.save_fom(
402 name=
"{module.id}_subdetector_figures_of_merit",
403 title=
"Overview figures in {module.title}",
404 description=
"Hit efficiency in the subdetectors",
405 key=
"hit efficiency",
406 select=
"mc_hit_efficiency",
407 aggregation=np.nanmean,
408 filter_on=
"is_matchedPrimary"
412 save_pxd_hit_efficiency = refiners.save_fom(
413 name=
"{module.id}_subdetector_figures_of_merit",
414 title=
"Overview figures in {module.title}",
415 description=
"Hit efficiency in the subdetectors",
416 key=
"pxd hit efficiency",
417 select=
"mc_pxd_hit_efficiency",
418 aggregation=np.nanmean,
419 filter_on=
"is_matchedPrimary"
423 save_svd_hit_efficiency = refiners.save_fom(
424 name=
"{module.id}_subdetector_figures_of_merit",
425 title=
"Overview figures in {module.title}",
426 description=
"Hit efficiency in the subdetectors",
427 key=
"svd hit efficiency",
428 select=
"mc_svd_hit_efficiency",
429 aggregation=np.nanmean,
430 filter_on=
"is_matchedPrimary"
434 save_cdc_hit_efficiency = refiners.save_fom(
435 name=
"{module.id}_subdetector_figures_of_merit",
436 title=
"Overview figures in {module.title}",
437 description=
"Hit efficiency in the subdetectors",
438 key=
"cdc hit efficiency",
439 select=
"mc_cdc_hit_efficiency",
440 aggregation=np.nanmean,
441 filter_on=
"is_matchedPrimary"
445 save_hit_purity = refiners.save_fom(
446 name=
"{module.id}_subdetector_figures_of_merit",
447 title=
"Overview figures in {module.title}",
448 description=
"Hit purity in the subdetectors",
451 aggregation=np.nanmean,
452 filter_on=
"is_matchedPrimary"
456 save_pxd_hit_purity = refiners.save_fom(
457 name=
"{module.id}_subdetector_figures_of_merit",
458 title=
"Overview figures in {module.title}",
459 description=
"Hit purity in the subdetectors",
460 key=
"pxd hit purity",
461 select=
"pxd_hit_purity",
462 aggregation=np.nanmean,
463 filter_on=
"is_matchedPrimary"
467 save_svd_hit_purity = refiners.save_fom(
468 name=
"{module.id}_subdetector_figures_of_merit",
469 title=
"Overview figures in {module.title}",
470 description=
"Hit purity in the subdetectors",
471 key=
"svd hit purity",
472 select=
"svd_hit_purity",
473 aggregation=np.nanmean,
474 filter_on=
"is_matchedPrimary"
478 save_cdc_hit_purity = refiners.save_fom(
479 name=
"{module.id}_subdetector_figures_of_merit",
480 title=
"Overview figures in {module.title}",
481 description=
"Hit purity in the subdetectors",
482 key=
"cdc hit purity",
483 select=
"cdc_hit_purity",
484 aggregation=np.nanmean,
485 filter_on=
"is_matchedPrimary"
489 save_p_value_histogram = refiners.save_histograms(
490 filter_on=
"is_matched",
491 select={
"p_value":
"Genfit p value"},
493 The distribution of p values from the Genfit track fit.
494 If all errors are propagated correctly the distribution should be flat.
495 Generally some peaking behvaiour towards zero is too be expected if the errors are underestimated.
497 check=
"The distribution should be flat."
501 save_seed_omega_pull_analysis = refiners.save_pull_analysis(
502 filter_on=
"is_matched",
503 part_name=
"seed_omega",
504 quantity_name=
"seed #omega",
505 folder_name=
"pull_seed_omega",
506 truth_name=
"omega_truth",
511 save_seed_tan_lambda_pull_analysis = refiners.save_pull_analysis(
512 filter_on=
"is_matched",
513 part_name=
"seed_tan_lambda",
514 quantity_name=
"seed tan #lambda",
515 folder_name=
"pull_seed_tan_lambda",
516 truth_name=
"tan_lambda_truth",
520 save_fitted_omega_pull_analysis = refiners.save_pull_analysis(
521 filter_on=
"is_matched",
523 quantity_name=
"#omega",
524 folder_name=
"pull_fitted_omega",
529 save_fitted_tan_lambda_pull_analysis = refiners.save_pull_analysis(
530 filter_on=
"is_matched",
531 part_name=
"tan_lambda",
532 quantity_name=
"tan #lambda",
533 folder_name=
"pull_fitted_tan_lambda",
537 save_fitted_pt_pull_analysis = refiners.save_pull_analysis(
538 filter_on=
"is_matched",
540 quantity_name=
"p_{t}",
541 folder_name=
"pull_fitted_p_t",
545 save_fitted_x_pull_analysis = refiners.save_pull_analysis(
546 filter_on=
"is_matched",
549 folder_name=
"pull_fitted_x{groupby_addition}",
550 groupby=[
None, (
"pt_truth", [0.070, 0.250, 0.600])],
554 save_fitted_y_pull_analysis = refiners.save_pull_analysis(
555 filter_on=
"is_matched",
558 folder_name=
"pull_fitted_y{groupby_addition}",
559 groupby=[
None, (
"pt_truth", [0.070, 0.250, 0.600])],
563 save_fitted_z_pull_analysis = refiners.save_pull_analysis(
564 filter_on=
"is_matched",
567 folder_name=
"pull_fitted_z{groupby_addition}",
568 groupby=[
None, (
"pt_truth", [0.070, 0.250, 0.600])],
572 save_resolutions_by_pt_profile = refiners.save_profiles(
573 filter_on=
"is_matched",
575 "pt_truth":
"true p_{t}",
576 "d0_variance":
"#sigma(d_{0})",
577 "z0_variance":
"#sigma(z_{0})",
578 "pt_resolution":
"#sigma(p_{t}) / p_{t}",
583 "#sigma(p_{t}) / p_{t}",