10 from ROOT
import Belle2
22 ROOT.gSystem.Load(
"libtracking")
26 """Module to collect matching information about the found particles and to generate
27 validation plots and figures of merit on the performance of track finding."""
29 """ Expert level behavior:
30 expert_level <= default_expert_level: all figures and plots from this module except tree entries
31 expert_level > default_expert_level: everything including tree entries
34 default_expert_level = 10
40 output_file_name=None,
41 reco_tracks_name='RecoTracks',
42 mc_reco_tracks_name='MCRecoTracks',
46 output_file_name = output_file_name
or name +
'TrackingValidation.root'
47 super().
__init__(foreach=reco_tracks_name,
50 output_file_name=output_file_name,
51 expert_level=expert_level)
69 """Receive signal at the start of event processing"""
75 """Called once at the start of each event"""
78 mc_reco_tracks_det_hit_ids = []
80 for mc_reco_track
in mc_reco_tracks:
81 mc_reco_track_det_hit_ids = utilities.get_det_hit_ids(mc_reco_track)
82 mc_reco_tracks_det_hit_ids.append(mc_reco_track_det_hit_ids)
88 def pick(self, reco_track):
89 """Method to filter the track candidates to reject part of them"""
92 def peel(self, reco_track):
93 """Looks at the individual pattern recognition tracks and store information about them"""
97 mc_reco_track = track_match_look_up.getRelatedMCRecoTrack(reco_track)
98 mc_particle = track_match_look_up.getRelatedMCParticle(reco_track)
99 mc_particle_crops = peelers.peel_mc_particle(mc_particle)
101 hit_content_crops = peelers.peel_reco_track_hit_content(reco_track)
106 subdetector_hit_purity_crops = peelers.peel_subdetector_hit_purity(reco_track, mc_reco_track)
109 trackfinder_crops = peelers.peel_trackfinder(reco_track)
112 qualityindicator_crops = peelers.peel_quality_indicators(reco_track)
115 seed_fit_crops = peelers.peel_reco_track_seed(reco_track)
117 fit_result = track_match_look_up.getRelatedTrackFitResult(reco_track)
118 fit_crops = peelers.peel_track_fit_result(fit_result)
119 fit_status_crops = peelers.peel_fit_status(reco_track)
121 correct_rl_information = sum(peelers.is_correct_rl_information(cdc_hit, reco_track, self.
mc_hit_lookupmc_hit_lookup)
122 for cdc_hit
in getObjectList(reco_track.getCDCHitList()))
125 correct_rl_information=correct_rl_information,
128 **pr_to_mc_match_info_crops,
129 **subdetector_hit_purity_crops,
131 **qualityindicator_crops,
141 event_crops = peelers.peel_event_info(event_meta_data)
144 store_array_crops = peelers.peel_store_array_info(reco_track, key=
"pr_{part_name}")
145 mc_store_array_crops = peelers.peel_store_array_info(mc_reco_track, key=
"mc_{part_name}")
148 mc_efficiency_information = {
149 "mc_hit_efficiency": track_match_look_up.getRelatedEfficiency(mc_reco_track)
if mc_reco_track
else float(
"nan"),
150 **peelers.peel_subdetector_hit_efficiency(reco_track=reco_track, mc_reco_track=mc_reco_track,
151 key=
"mc_{part_name}")
157 **mc_store_array_crops,
158 **mc_efficiency_information
164 """Extracts track-match information from the MCMatcherTracksModule results"""
166 is_matched = track_match_look_up.isMatchedPRRecoTrack(reco_track)
167 is_clone = track_match_look_up.isClonePRRecoTrack(reco_track)
168 is_background = track_match_look_up.isBackgroundPRRecoTrack(reco_track)
169 is_ghost = track_match_look_up.isGhostPRRecoTrack(reco_track)
171 reco_track_det_hit_ids = utilities.get_det_hit_ids(reco_track)
172 n_intersecting_mc_tracks = 0
174 intersects = len(mc_reco_track_det_hit_ids & reco_track_det_hit_ids) > 0
176 n_intersecting_mc_tracks += 1
178 mc_particle = track_match_look_up.getRelatedMCParticle(reco_track)
179 mc_is_primary =
False
181 mc_is_primary = bool(mc_particle.hasStatus(Belle2.MCParticle.c_PrimaryParticle))
184 is_matched=is_matched,
185 is_matchedPrimary=is_matched
and mc_is_primary,
187 is_background=is_background,
189 is_clone_or_match=(is_matched
or is_clone),
190 is_fake=
not (is_matched
or is_clone),
191 hit_purity=track_match_look_up.getRelatedPurity(reco_track),
192 n_intersecting_mc_tracks=n_intersecting_mc_tracks,
199 save_tree = refiners.save_tree(
201 folder_name=
"pr_tree", name=
"pr_tree", above_expert_level=default_expert_level
206 save_clone_rate = refiners.save_fom(
208 name=
"{module.id}_overview_figures_of_merit",
210 title=
"Overview figures in {module.title}",
211 description=
"clone_rate - ratio of clones divided the number of tracks that are related to a particle (clones and matches)",
215 filter_on=
"is_clone_or_match",
221 save_clone_rate_by_seed_tan_lambda_profile = refiners.save_profiles(
223 filter_on=
"is_clone_or_match",
225 'is_clone':
'clone rate',
226 'seed_tan_lambda_estimate':
'seed tan #lambda',
239 save_clone_rate_by_seed_phi0_profile = refiners.save_profiles(
242 'is_clone':
'clone rate',
243 'seed_phi0_estimate':
'seed #phi',
254 save_clone_rate_by_seed_pt_profile = refiners.save_profiles(
256 filter_on=
"is_clone_or_match",
258 'is_clone':
'clone rate',
259 'seed_pt_estimate':
'seed p_{t}',
272 save_clone_rate_by_seed_pt_profile_groupbyCharge = refiners.save_profiles(
274 filter_on=
"is_clone_or_match",
276 'is_clone':
'clone rate',
277 'seed_pt_estimate':
'seed p_{t}',
281 groupby=[(
"charge_truth", [0.])],
291 save_clone_rate_by_seed_tan_lambda_profile_groupbyCharge = refiners.save_profiles(
293 filter_on=
"is_clone_or_match",
295 'is_clone':
'clone rate',
296 'seed_tan_lambda_estimate':
'seed tan #lambda',
300 groupby=[(
"charge_truth", [0.])],
309 save_fake_rate = refiners.save_fom(
311 name=
"{module.id}_overview_figures_of_merit",
313 title=
"Overview figures in {module.title}",
314 description=
"fake_rate - ratio of pattern recognition tracks that are not related to a particle" +
315 "(background, ghost) to all pattern recognition tracks",
324 save_fake_rate_by_seed_phi0_profile = refiners.save_profiles(
327 'is_fake':
'fake rate',
328 'seed_phi0_estimate':
'seed #phi',
338 save_fake_rate_by_seed_tan_lambda_profile = refiners.save_profiles(
341 'is_fake':
'fake rate',
342 'seed_tan_lambda_estimate':
'seed tan #lambda',
354 save_fake_rate_by_seed_pt_profile = refiners.save_profiles(
357 'is_fake':
'fake rate',
358 'seed_pt_estimate':
'seed p_{t}',
370 save_fake_rate_by_seed_tan_lambda_profile_groupbyCharge = refiners.save_profiles(
372 filter_on=
"has_trackFitResult",
374 'is_fake':
'fake rate',
375 'seed_tan_lambda_estimate':
'seed tan #lambda',
382 groupby=[(
"track_charge", [0.])],
388 save_fake_rate_by_seed_pt_profile_groupbyCharge = refiners.save_profiles(
390 filter_on=
"has_trackFitResult",
392 'is_fake':
'fake rate',
393 'seed_pt_estimate':
'seed p_{t}',
400 groupby=[(
"track_charge", [0.])],
405 save_hit_counts_by_pt_profile = refiners.save_profiles(
407 filter_on=
"is_matched",
409 "pt_truth":
"true p_{t}",
410 "n_pxd_hits":
"pxd hits",
411 "n_svd_hits":
"svd hits",
412 "n_cdc_hits":
"cdc hits",
426 save_hit_efficiency_by_pt_profile = refiners.save_profiles(
428 filter_on=
"is_matchedPrimary",
430 "pt_truth":
"true p_{t}",
431 "mc_pxd_hit_efficiency":
"pxd hit efficiency",
432 "mc_svd_hit_efficiency":
"svd hit efficiency",
433 "mc_cdc_hit_efficiency":
"cdc hit efficiency",
436 "pxd hit efficiency",
437 "svd hit efficiency",
438 "cdc hit efficiency",
447 save_hit_purity_by_pt_profile = refiners.save_profiles(
449 filter_on=
"is_matchedPrimary",
451 "pt_truth":
"true p_{t}",
452 "pxd_hit_purity":
"pxd hit purity",
453 "svd_hit_purity":
"svd hit purity",
454 "cdc_hit_purity":
"cdc hit purity",
468 save_hit_counts_by_tanlambda_profile = refiners.save_profiles(
470 filter_on=
"is_matched",
472 "tan_lambda_truth":
"true tan #lambda",
473 "n_pxd_hits":
"pxd hits",
474 "n_svd_hits":
"svd hits",
475 "n_cdc_hits":
"cdc hits",
489 save_hit_efficiency_by_tanlambda_profile = refiners.save_profiles(
491 filter_on=
"is_matchedPrimary",
493 "tan_lambda_truth":
"true tan #lambda",
494 "mc_pxd_hit_efficiency":
"pxd hit efficiency",
495 "mc_svd_hit_efficiency":
"svd hit efficiency",
496 "mc_cdc_hit_efficiency":
"cdc hit efficiency",
499 "pxd hit efficiency",
500 "svd hit efficiency",
501 "cdc hit efficiency",
510 save_hit_purity_by_tanlambda_profile = refiners.save_profiles(
512 filter_on=
"is_matchedPrimary",
514 "tan_lambda_truth":
"true tan #lambda",
515 "pxd_hit_purity":
"pxd hit purity",
516 "svd_hit_purity":
"svd hit purity",
517 "cdc_hit_purity":
"cdc hit purity",
532 save_hit_counts_by_pt_profile_groupbyCharge = refiners.save_profiles(
534 filter_on=
"is_matched",
536 "pt_truth":
"true p_{t}",
537 "n_pxd_hits":
"pxd hits",
538 "n_svd_hits":
"svd hits",
539 "n_cdc_hits":
"cdc hits",
546 groupby=[(
"charge_truth", [0.])],
555 save_hit_counts_by_tanlambda_profile_groupbyCharge = refiners.save_profiles(
557 filter_on=
"is_matched",
559 "tan_lambda_truth":
"true tan #lambda",
560 "n_pxd_hits":
"pxd hits",
561 "n_svd_hits":
"svd hits",
562 "n_cdc_hits":
"cdc hits",
569 groupby=[(
"charge_truth", [0.])],
578 save_hit_efficiency_by_pt_profile_groupbyCharge = refiners.save_profiles(
580 filter_on=
"is_matchedPrimary",
582 "pt_truth":
"true p_{t}",
583 "mc_pxd_hit_efficiency":
"pxd hit efficiency",
584 "mc_svd_hit_efficiency":
"svd hit efficiency",
585 "mc_cdc_hit_efficiency":
"cdc hit efficiency",
588 "pxd hit efficiency",
589 "svd hit efficiency",
590 "cdc hit efficiency",
592 groupby=[(
"charge_truth", [0.])],
601 save_hit_efficiency_by_tanlambda_profile_groupbyCharge = refiners.save_profiles(
603 filter_on=
"is_matchedPrimary",
605 "tan_lambda_truth":
"true tan #lambda",
606 "mc_pxd_hit_efficiency":
"pxd hit efficiency",
607 "mc_svd_hit_efficiency":
"svd hit efficiency",
608 "mc_cdc_hit_efficiency":
"cdc hit efficiency",
611 "pxd hit efficiency",
612 "svd hit efficiency",
613 "cdc hit efficiency",
615 groupby=[(
"charge_truth", [0.])],
623 save_hit_efficiency = refiners.save_fom(
625 name=
"{module.id}_subdetector_figures_of_merit",
626 title=
"Overview figures in {module.title}",
627 description=
"Hit efficiency in the subdetectors",
628 key=
"hit efficiency",
629 select=
"mc_hit_efficiency",
630 aggregation=np.nanmean,
631 filter_on=
"is_matchedPrimary"
636 save_pxd_hit_efficiency = refiners.save_fom(
638 name=
"{module.id}_subdetector_figures_of_merit",
639 title=
"Overview figures in {module.title}",
640 description=
"Hit efficiency in the subdetectors",
641 key=
"pxd hit efficiency",
642 select=
"mc_pxd_hit_efficiency",
643 aggregation=np.nanmean,
644 filter_on=
"is_matchedPrimary"
649 save_svd_hit_efficiency = refiners.save_fom(
651 name=
"{module.id}_subdetector_figures_of_merit",
652 title=
"Overview figures in {module.title}",
653 description=
"Hit efficiency in the subdetectors",
654 key=
"svd hit efficiency",
655 select=
"mc_svd_hit_efficiency",
656 aggregation=np.nanmean,
657 filter_on=
"is_matchedPrimary"
662 save_cdc_hit_efficiency = refiners.save_fom(
664 name=
"{module.id}_subdetector_figures_of_merit",
665 title=
"Overview figures in {module.title}",
666 description=
"Hit efficiency in the subdetectors",
667 key=
"cdc hit efficiency",
668 select=
"mc_cdc_hit_efficiency",
669 aggregation=np.nanmean,
670 filter_on=
"is_matchedPrimary"
675 save_hit_purity = refiners.save_fom(
677 name=
"{module.id}_subdetector_figures_of_merit",
678 title=
"Overview figures in {module.title}",
679 description=
"Hit purity in the subdetectors",
682 aggregation=np.nanmean,
683 filter_on=
"is_matchedPrimary"
688 save_pxd_hit_purity = refiners.save_fom(
690 name=
"{module.id}_subdetector_figures_of_merit",
691 title=
"Overview figures in {module.title}",
692 description=
"Hit purity in the subdetectors",
693 key=
"pxd hit purity",
694 select=
"pxd_hit_purity",
695 aggregation=np.nanmean,
696 filter_on=
"is_matchedPrimary"
701 save_svd_hit_purity = refiners.save_fom(
703 name=
"{module.id}_subdetector_figures_of_merit",
704 title=
"Overview figures in {module.title}",
705 description=
"Hit purity in the subdetectors",
706 key=
"svd hit purity",
707 select=
"svd_hit_purity",
708 aggregation=np.nanmean,
709 filter_on=
"is_matchedPrimary"
714 save_cdc_hit_purity = refiners.save_fom(
716 name=
"{module.id}_subdetector_figures_of_merit",
717 title=
"Overview figures in {module.title}",
718 description=
"Hit purity in the subdetectors",
719 key=
"cdc hit purity",
720 select=
"cdc_hit_purity",
721 aggregation=np.nanmean,
722 filter_on=
"is_matchedPrimary"
727 save_p_value_histogram = refiners.save_histograms(
729 filter_on=
"is_matched",
730 select={
"p_value":
"Genfit p value"},
732 The distribution of p values from the Genfit track fit.
733 If all errors are propagated correctly the distribution should be flat.
734 Generally some peaking behvaiour towards zero is too be expected if the errors are underestimated.
736 check=
"The distribution should be flat."
741 save_seed_omega_pull_analysis = refiners.save_pull_analysis(
743 filter_on=
"is_matched",
744 part_name=
"seed_omega",
745 quantity_name=
"seed #omega",
746 folder_name=
"pull_seed_omega",
747 truth_name=
"omega_truth",
753 save_seed_tan_lambda_pull_analysis = refiners.save_pull_analysis(
755 filter_on=
"is_matched",
756 part_name=
"seed_tan_lambda",
757 quantity_name=
"seed tan #lambda",
758 folder_name=
"pull_seed_tan_lambda",
759 truth_name=
"tan_lambda_truth",
764 save_fitted_omega_pull_analysis = refiners.save_pull_analysis(
766 filter_on=
"is_matched",
768 quantity_name=
"#omega",
769 folder_name=
"pull_fitted_omega",
775 save_fitted_tan_lambda_pull_analysis = refiners.save_pull_analysis(
777 filter_on=
"is_matched",
778 part_name=
"tan_lambda",
779 quantity_name=
"tan #lambda",
780 folder_name=
"pull_fitted_tan_lambda",
785 save_fitted_pt_pull_analysis = refiners.save_pull_analysis(
787 filter_on=
"is_matched",
789 quantity_name=
"p_{t}",
790 folder_name=
"pull_fitted_p_t",
795 save_fitted_x_pull_analysis = refiners.save_pull_analysis(
797 filter_on=
"is_matched",
800 folder_name=
"pull_fitted_x{groupby_addition}",
801 groupby=[
None, (
"pt_truth", [0.070, 0.250, 0.600])],
806 save_fitted_y_pull_analysis = refiners.save_pull_analysis(
808 filter_on=
"is_matched",
811 folder_name=
"pull_fitted_y{groupby_addition}",
812 groupby=[
None, (
"pt_truth", [0.070, 0.250, 0.600])],
817 save_fitted_z_pull_analysis = refiners.save_pull_analysis(
819 filter_on=
"is_matched",
822 folder_name=
"pull_fitted_z{groupby_addition}",
823 groupby=[
None, (
"pt_truth", [0.070, 0.250, 0.600])],
828 save_resolutions_by_pt_profile = refiners.save_profiles(
830 filter_on=
"is_matched",
832 "pt_truth":
"true p_{t}",
833 "d0_variance":
"#sigma(d_{0})",
834 "z0_variance":
"#sigma(z_{0})",
835 "pt_resolution":
"#sigma(p_{t}) / p_{t}",
840 "#sigma(p_{t}) / p_{t}",
a (simplified) python wrapper for StoreArray.
a (simplified) python wrapper for StoreObjPtr.
static const CDCMCHitLookUp & getInstance()
Getter for the singletone instance.
Class to provide convenient methods to look up matching information between pattern recognition and M...
mc_hit_lookup
Cache for the MC hit lookup.
mc_reco_tracks_det_hit_ids
Cache for the hit content of the Monte Carlo tracks - updated each event.
track_match_look_up
Reference to the track match lookup object reading the relation information constructed by the MCMatc...
mc_reco_tracks_name
Name of the StoreArray of the ideal mc tracks.
def peel(self, reco_track)
def peel_pr_to_mc_match_info(self, reco_track)
def __init__(self, name, contact, output_file_name=None, reco_tracks_name='RecoTracks', mc_reco_tracks_name='MCRecoTracks', expert_level=None)
def pick(self, reco_track)
reco_tracks_name
Name of the StoreArray of the tracks from pattern recognition.
int default_expert_level
the threshold value for the expert level