Belle II Software development
pr_side_module.py
1
8
9import ROOT
10from ROOT import Belle2
11
12
13import numpy as np
14
15import tracking.harvest.harvesting as harvesting
16import tracking.harvest.refiners as refiners
17import tracking.validation.utilities as utilities
18
19from tracking.validation.utilities import getObjectList
20
21import tracking.harvest.peelers as peelers
22ROOT.gSystem.Load("libtracking")
23
24
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."""
28
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
32 """
33
34 default_expert_level = 10
35
37 self,
38 name,
39 contact,
40 output_file_name=None,
41 reco_tracks_name='RecoTracks',
42 mc_reco_tracks_name='MCRecoTracks',
43 expert_level=None):
44 """Constructor"""
45
46 output_file_name = output_file_name or name + 'TrackingValidation.root'
47 super().__init__(foreach=reco_tracks_name,
48 name=name,
49 contact=contact,
50 output_file_name=output_file_name,
51 expert_level=expert_level)
52
53 ## Name of the StoreArray of the tracks from pattern recognition
54 self.reco_tracks_name = reco_tracks_name
55
56 ## Name of the StoreArray of the ideal mc tracks
57 self.mc_reco_tracks_name = mc_reco_tracks_name
58
59 ## Reference to the track match lookup object reading the relation information constructed by the MCMatcherTracksModule
60 self.track_match_look_up = None
61
62 ## Cache for the hit content of the Monte Carlo tracks - updated each event
63 self.mc_reco_tracks_det_hit_ids = []
64
65 ## Cache for the MC hit lookup
66 self.mc_hit_lookup = Belle2.TrackFindingCDC.CDCMCHitLookUp.getInstance()
67
68 def initialize(self):
69 """Receive signal at the start of event processing"""
70 super().initialize()
71 self.track_match_look_up = Belle2.TrackMatchLookUp(self.mc_reco_tracks_name,
72 self.reco_tracks_name)
73
74 def prepare(self):
75 """Called once at the start of each event"""
76 super().prepare()
77 mc_reco_tracks = Belle2.PyStoreArray(self.mc_reco_tracks_name)
78 mc_reco_tracks_det_hit_ids = []
79
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)
83
84 self.mc_reco_tracks_det_hit_ids = mc_reco_tracks_det_hit_ids
85
86 self.mc_hit_lookup.fill()
87
88 def pick(self, reco_track):
89 """Method to filter the track candidates to reject part of them"""
90 return True
91
92 def peel(self, reco_track):
93 """Looks at the individual pattern recognition tracks and store information about them"""
94 track_match_look_up = self.track_match_look_up
95
96 # Matching information
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)
100
101 hit_content_crops = peelers.peel_reco_track_hit_content(reco_track)
102
103 pr_to_mc_match_info_crops = self.peel_pr_to_mc_match_info(reco_track)
104
105 # Peel function to get hit purity of subdetectors
106 subdetector_hit_purity_crops = peelers.peel_subdetector_hit_purity(reco_track, mc_reco_track)
107
108 # Information on TrackFinders
109 trackfinder_crops = peelers.peel_trackfinder(reco_track)
110
111 # Basic peel function to get Quality Indicators
112 qualityindicator_crops = peelers.peel_quality_indicators(reco_track)
113
114 # Get the fit results
115 seed_fit_crops = peelers.peel_reco_track_seed(reco_track)
116
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)
120
121 correct_rl_information = sum(peelers.is_correct_rl_information(cdc_hit, reco_track, self.mc_hit_lookup)
122 for cdc_hit in getObjectList(reco_track.getCDCHitList()))
123
124 crops = dict(
125 correct_rl_information=correct_rl_information,
126 **mc_particle_crops,
127 **hit_content_crops,
128 **pr_to_mc_match_info_crops,
129 **subdetector_hit_purity_crops, # Custom
130 **trackfinder_crops,
131 **qualityindicator_crops,
132 **seed_fit_crops,
133 **fit_crops,
134 **fit_status_crops,
135 )
136
137 if self.expert_level >= self.default_expert_level:
138
139 # Event Info
140 event_meta_data = Belle2.PyStoreObj("EventMetaData")
141 event_crops = peelers.peel_event_info(event_meta_data)
142
143 # Store Array for easier joining
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}")
146
147 # Information on PR reco track
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}")
152 }
153
154 crops.update(
155 **event_crops,
156 **store_array_crops,
157 **mc_store_array_crops,
158 **mc_efficiency_information
159 )
160
161 return crops
162
163 def peel_pr_to_mc_match_info(self, reco_track):
164 """Extracts track-match information from the MCMatcherTracksModule results"""
165 track_match_look_up = self.track_match_look_up
166 is_matched = track_match_look_up.isAnyChargeMatchedPRRecoTrack(reco_track)
167 is_matched_correct_charge = track_match_look_up.isCorrectChargeMatchedPRRecoTrack(reco_track)
168 is_matched_wrong_charge = track_match_look_up.isWrongChargeMatchedPRRecoTrack(reco_track)
169 is_clone = track_match_look_up.isAnyChargeClonePRRecoTrack(reco_track)
170 is_clone_correct_charge = track_match_look_up.isCorrectChargeClonePRRecoTrack(reco_track)
171 is_clone_wrong_charge = track_match_look_up.isWrongChargeClonePRRecoTrack(reco_track)
172 is_background = track_match_look_up.isBackgroundPRRecoTrack(reco_track)
173 is_ghost = track_match_look_up.isGhostPRRecoTrack(reco_track)
174
175 reco_track_det_hit_ids = utilities.get_det_hit_ids(reco_track)
176 n_intersecting_mc_tracks = 0
177 for mc_reco_track_det_hit_ids in self.mc_reco_tracks_det_hit_ids:
178 intersects = len(mc_reco_track_det_hit_ids & reco_track_det_hit_ids) > 0
179 if intersects:
180 n_intersecting_mc_tracks += 1
181
182 mc_particle = track_match_look_up.getRelatedMCParticle(reco_track)
183 mc_is_primary = False
184 if mc_particle:
185 mc_is_primary = bool(mc_particle.hasStatus(Belle2.MCParticle.c_PrimaryParticle))
186
187 return dict(
188 is_matched=is_matched,
189 is_matchedPrimary=is_matched and mc_is_primary,
190 is_matched_correct_charge=is_matched_correct_charge,
191 is_matchedPrimary_correct_charge=is_matched_correct_charge and mc_is_primary,
192 is_matched_wrong_charge=is_matched_wrong_charge,
193 is_matchedPrimary_wrong_charge=is_matched_wrong_charge and mc_is_primary,
194
195 is_clone=is_clone,
196 is_clone_correct_charge=is_clone_correct_charge,
197 is_clone_wrong_charge=is_clone_wrong_charge,
198
199 is_background=is_background,
200 is_ghost=is_ghost,
201 is_clone_or_match=(is_matched or is_clone),
202 is_fake=not (is_matched or is_clone),
203 hit_purity=track_match_look_up.getRelatedPurity(reco_track),
204 n_intersecting_mc_tracks=n_intersecting_mc_tracks,
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 ## \cond
213 folder_name="pr_tree", name="pr_tree", above_expert_level=default_expert_level
214 ## \endcond
215 )
216
217 ## Save RecoTrack clone-rate information
218 save_clone_rate = refiners.save_fom(
219 ## \cond
220 name="{module.id}_overview_figures_of_merit",
221 # Same as in the mc side module to combine the overview figures of merit into the same TNTuple
222 title="Overview figures in {module.title}",
223 description="clone_rate - ratio of clones divided the number of tracks that are related to a particle (clones and matches)",
224 key="clone rate",
225 select=["is_clone"],
226 aggregation=np.mean,
227 filter_on="is_clone_or_match",
228 ## \endcond
229 )
230
231 ## Make profile of the clone rate versus seed tan(lambda)
232 ## Rename the quantities to names that display nicely by root latex translation
233 save_clone_rate_by_seed_tan_lambda_profile = refiners.save_profiles(
234 ## \cond
235 filter_on="is_clone_or_match",
236 select={
237 'is_clone': 'clone rate',
238 'seed_tan_lambda_estimate': 'seed tan #lambda',
239 },
240 y='clone rate',
241 y_binary=True,
242 outlier_z_score=5.0,
243 lower_bound=-1.73,
244 upper_bound=3.27,
245 bins=50
246 ## \endcond
247 )
248
249 ## Make profile of the clone rate versus seed phi0
250 ## Rename the quantities to names that display nicely by root latex translation
251 save_clone_rate_by_seed_phi0_profile = refiners.save_profiles(
252 ## \cond
253 select={
254 'is_clone': 'clone rate',
255 'seed_phi0_estimate': 'seed #phi',
256 },
257 y='clone rate',
258 y_binary=True,
259 outlier_z_score=5.0,
260 bins=50
261 ## \endcond
262 )
263
264 ## Make profile of the clone rate versus seed transverse momentum
265 ## Rename the quantities to names that display nicely by root latex translation
266 save_clone_rate_by_seed_pt_profile = refiners.save_profiles(
267 ## \cond
268 filter_on="is_clone_or_match",
269 select={
270 'is_clone': 'clone rate',
271 'seed_pt_estimate': 'seed p_{t}',
272 },
273 y='clone rate',
274 y_binary=True,
275 outlier_z_score=5.0,
276 lower_bound=0,
277 upper_bound=1.7,
278 bins=50
279 ## \endcond
280 )
281
282 ## Charge dependent histograms
283 ## Make profile of the clone rate versus seed transverse momentum
284 save_clone_rate_by_seed_pt_profile_groupbyCharge = refiners.save_profiles(
285 ## \cond
286 filter_on="is_clone_or_match",
287 select={
288 'is_clone': 'clone rate',
289 'seed_pt_estimate': 'seed p_{t}',
290 },
291 y='clone rate',
292 y_binary=True,
293 groupby=[("charge_truth", [0.])],
294 outlier_z_score=5.0,
295 lower_bound=0,
296 upper_bound=1.7,
297 bins=50
298 ## \endcond
299 )
300
301 ## Charge dependent histograms
302 ## Make profile of the clone rate versus seed tan(lambda)
303 save_clone_rate_by_seed_tan_lambda_profile_groupbyCharge = refiners.save_profiles(
304 ## \cond
305 filter_on="is_clone_or_match",
306 select={
307 'is_clone': 'clone rate',
308 'seed_tan_lambda_estimate': 'seed tan #lambda',
309 },
310 y='clone rate',
311 y_binary=True,
312 groupby=[("charge_truth", [0.])],
313 outlier_z_score=5.0,
314 lower_bound=-1.73,
315 upper_bound=3.27,
316 bins=50
317 ## \endcond
318 )
319
320 ## Save RecoTrack fake-rate information
321 save_fake_rate = refiners.save_fom(
322 ## \cond
323 name="{module.id}_overview_figures_of_merit",
324 # Same as in the mc side module to combine the overview figures of merit into the same TNTuple
325 title="Overview figures in {module.title}",
326 description="fake_rate - ratio of pattern recognition tracks that are not related to a particle" +
327 "(background, ghost) to all pattern recognition tracks",
328 key="fake rate",
329 select="is_fake",
330 aggregation=np.mean,
331 ## \endcond
332 )
333
334 ## Make profile of the fake rate versus seed phi0
335 ## Rename the quantities to names that display nicely by root latex translation
336 save_fake_rate_by_seed_phi0_profile = refiners.save_profiles(
337 ## \cond
338 select={
339 'is_fake': 'fake rate',
340 'seed_phi0_estimate': 'seed #phi',
341 },
342 y='fake rate',
343 y_binary=True,
344 outlier_z_score=5.0,
345 ## \endcond
346 )
347
348 ## Make profile of the fake rate versus seed tan(lambda)
349 ## Rename the quantities to names that display nicely by root latex translation
350 save_fake_rate_by_seed_tan_lambda_profile = refiners.save_profiles(
351 ## \cond
352 select={
353 'is_fake': 'fake rate',
354 'seed_tan_lambda_estimate': 'seed tan #lambda',
355 },
356 y='fake rate',
357 y_binary=True,
358 outlier_z_score=5.0,
359 lower_bound=-1.73,
360 upper_bound=3.27,
361 ## \endcond
362 )
363
364 ## Make profile of the fake rate versus seed transverse momentum
365 ## Rename the quantities to names that display nicely by root latex translation
366 save_fake_rate_by_seed_pt_profile = refiners.save_profiles(
367 ## \cond
368 select={
369 'is_fake': 'fake rate',
370 'seed_pt_estimate': 'seed p_{t}',
371 },
372 y='fake rate',
373 y_binary=True,
374 outlier_z_score=5.0,
375 lower_bound=0,
376 upper_bound=1.7,
377 ## \endcond
378 )
379
380 ## Charge dependent histograms
381 ## Make profile of the fake rate versus seed tan(lambda)
382 save_fake_rate_by_seed_tan_lambda_profile_groupbyCharge = refiners.save_profiles(
383 ## \cond
384 filter_on="has_trackFitResult",
385 select={
386 'is_fake': 'fake rate',
387 'seed_tan_lambda_estimate': 'seed tan #lambda',
388 },
389 y='fake rate',
390 y_binary=True,
391 outlier_z_score=5.0,
392 lower_bound=-1.73,
393 upper_bound=3.27,
394 groupby=[("track_charge", [0.])],
395 ## \endcond
396 )
397
398 ## Charge dependent histograms
399 ## Make profile of the fake rate versus seed transverse momentum
400 save_fake_rate_by_seed_pt_profile_groupbyCharge = refiners.save_profiles(
401 ## \cond
402 filter_on="has_trackFitResult",
403 select={
404 'is_fake': 'fake rate',
405 'seed_pt_estimate': 'seed p_{t}',
406 },
407 y='fake rate',
408 y_binary=True,
409 outlier_z_score=5.0,
410 lower_bound=0,
411 upper_bound=1.7,
412 groupby=[("track_charge", [0.])],
413 ## \endcond
414 )
415
416 ## Hit counts in each sub detector by the true pt value
417 save_hit_counts_by_pt_profile = refiners.save_profiles(
418 ## \cond
419 filter_on="is_matched",
420 select={
421 "pt_truth": "true p_{t}",
422 "n_pxd_hits": "pxd hits",
423 "n_svd_hits": "svd hits",
424 "n_cdc_hits": "cdc hits",
425 },
426 y=[
427 "pxd hits",
428 "svd hits",
429 "cdc hits",
430 ],
431 outlier_z_score=5.0,
432 lower_bound=0,
433 upper_bound=1.7,
434 ## \endcond
435 )
436
437 ## Hit efficiency in each sub detector by the true pt value
438 save_hit_efficiency_by_pt_profile = refiners.save_profiles(
439 ## \cond
440 filter_on="is_matchedPrimary",
441 select={
442 "pt_truth": "true p_{t}",
443 "mc_pxd_hit_efficiency": "pxd hit efficiency",
444 "mc_svd_hit_efficiency": "svd hit efficiency",
445 "mc_cdc_hit_efficiency": "cdc hit efficiency",
446 },
447 y=[
448 "pxd hit efficiency",
449 "svd hit efficiency",
450 "cdc hit efficiency",
451 ],
452 outlier_z_score=5.0,
453 lower_bound=0,
454 upper_bound=1.7,
455 ## \endcond
456 )
457
458 ## Hit purity in each sub detector by the true pt value
459 save_hit_purity_by_pt_profile = refiners.save_profiles(
460 ## \cond
461 filter_on="is_matchedPrimary",
462 select={
463 "pt_truth": "true p_{t}",
464 "pxd_hit_purity": "pxd hit purity",
465 "svd_hit_purity": "svd hit purity",
466 "cdc_hit_purity": "cdc hit purity",
467 },
468 y=[
469 "pxd hit purity",
470 "svd hit purity",
471 "cdc hit purity",
472 ],
473 outlier_z_score=5.0,
474 lower_bound=0,
475 upper_bound=1.7,
476 ## \endcond
477 )
478
479 ## Hit counts in each sub detector by the true tanlambda value
480 save_hit_counts_by_tanlambda_profile = refiners.save_profiles(
481 ## \cond
482 filter_on="is_matched",
483 select={
484 "tan_lambda_truth": "true tan #lambda",
485 "n_pxd_hits": "pxd hits",
486 "n_svd_hits": "svd hits",
487 "n_cdc_hits": "cdc hits",
488 },
489 y=[
490 "pxd hits",
491 "svd hits",
492 "cdc hits",
493 ],
494 outlier_z_score=5.0,
495 lower_bound=-1.73,
496 upper_bound=3.27,
497 ## \endcond
498 )
499
500 ## Hit efficiency in each sub detector by the true tanlambda value
501 save_hit_efficiency_by_tanlambda_profile = refiners.save_profiles(
502 ## \cond
503 filter_on="is_matchedPrimary",
504 select={
505 "tan_lambda_truth": "true tan #lambda",
506 "mc_pxd_hit_efficiency": "pxd hit efficiency",
507 "mc_svd_hit_efficiency": "svd hit efficiency",
508 "mc_cdc_hit_efficiency": "cdc hit efficiency",
509 },
510 y=[
511 "pxd hit efficiency",
512 "svd hit efficiency",
513 "cdc hit efficiency",
514 ],
515 outlier_z_score=5.0,
516 lower_bound=-1.73,
517 upper_bound=3.27,
518 ## \endcond
519 )
520
521 ## Hit purity in each sub detector by the true tanlambda value
522 save_hit_purity_by_tanlambda_profile = refiners.save_profiles(
523 ## \cond
524 filter_on="is_matchedPrimary",
525 select={
526 "tan_lambda_truth": "true tan #lambda",
527 "pxd_hit_purity": "pxd hit purity",
528 "svd_hit_purity": "svd hit purity",
529 "cdc_hit_purity": "cdc hit purity",
530 },
531 y=[
532 "pxd hit purity",
533 "svd hit purity",
534 "cdc hit purity",
535 ],
536 outlier_z_score=5.0,
537 lower_bound=-1.73,
538 upper_bound=3.27,
539 ## \endcond
540 )
541
542 ## Charge dependent histograms
543 ## Hit counts in each sub detector by the true pt value
544 save_hit_counts_by_pt_profile_groupbyCharge = refiners.save_profiles(
545 ## \cond
546 filter_on="is_matched",
547 select={
548 "pt_truth": "true p_{t}",
549 "n_pxd_hits": "pxd hits",
550 "n_svd_hits": "svd hits",
551 "n_cdc_hits": "cdc hits",
552 },
553 y=[
554 "pxd hits",
555 "svd hits",
556 "cdc hits",
557 ],
558 groupby=[("charge_truth", [0.])],
559 outlier_z_score=5.0,
560 lower_bound=0,
561 upper_bound=1.7,
562 ## \endcond
563 )
564
565 ## Charge dependent histograms
566 ## Hit counts in each sub detector by the true tan lambda value
567 save_hit_counts_by_tanlambda_profile_groupbyCharge = refiners.save_profiles(
568 ## \cond
569 filter_on="is_matched",
570 select={
571 "tan_lambda_truth": "true tan #lambda",
572 "n_pxd_hits": "pxd hits",
573 "n_svd_hits": "svd hits",
574 "n_cdc_hits": "cdc hits",
575 },
576 y=[
577 "pxd hits",
578 "svd hits",
579 "cdc hits",
580 ],
581 groupby=[("charge_truth", [0.])],
582 outlier_z_score=5.0,
583 lower_bound=-1.73,
584 upper_bound=3.27,
585 ## \endcond
586 )
587
588 ## Charge dependent histograms
589 ## Hit efficiency in each sub detector by the true pt value
590 save_hit_efficiency_by_pt_profile_groupbyCharge = refiners.save_profiles(
591 ## \cond
592 filter_on="is_matchedPrimary",
593 select={
594 "pt_truth": "true p_{t}",
595 "mc_pxd_hit_efficiency": "pxd hit efficiency",
596 "mc_svd_hit_efficiency": "svd hit efficiency",
597 "mc_cdc_hit_efficiency": "cdc hit efficiency",
598 },
599 y=[
600 "pxd hit efficiency",
601 "svd hit efficiency",
602 "cdc hit efficiency",
603 ],
604 groupby=[("charge_truth", [0.])],
605 outlier_z_score=5.0,
606 lower_bound=0,
607 upper_bound=1.7,
608 ## \endcond
609 )
610
611 ## Charge dependent histograms
612 ## Hit efficiency in each sub detector by the true tan lambda value
613 save_hit_efficiency_by_tanlambda_profile_groupbyCharge = refiners.save_profiles(
614 ## \cond
615 filter_on="is_matchedPrimary",
616 select={
617 "tan_lambda_truth": "true tan #lambda",
618 "mc_pxd_hit_efficiency": "pxd hit efficiency",
619 "mc_svd_hit_efficiency": "svd hit efficiency",
620 "mc_cdc_hit_efficiency": "cdc hit efficiency",
621 },
622 y=[
623 "pxd hit efficiency",
624 "svd hit efficiency",
625 "cdc hit efficiency",
626 ],
627 groupby=[("charge_truth", [0.])],
628 outlier_z_score=5.0,
629 lower_bound=-1.73,
630 upper_bound=3.27,
631 ## \endcond
632 )
633
634 ## Save simple FOM
635 save_hit_efficiency = refiners.save_fom(
636 ## \cond
637 name="{module.id}_subdetector_figures_of_merit",
638 title="Overview figures in {module.title}",
639 description="Hit efficiency in the subdetectors",
640 key="hit efficiency",
641 select="mc_hit_efficiency",
642 aggregation=np.nanmean,
643 filter_on="is_matchedPrimary"
644 ## \endcond
645 )
646
647 ## Save simple FOM
648 save_pxd_hit_efficiency = refiners.save_fom(
649 ## \cond
650 name="{module.id}_subdetector_figures_of_merit",
651 title="Overview figures in {module.title}",
652 description="Hit efficiency in the subdetectors",
653 key="pxd hit efficiency",
654 select="mc_pxd_hit_efficiency",
655 aggregation=np.nanmean,
656 filter_on="is_matchedPrimary"
657 ## \endcond
658 )
659
660 ## Save simple FOM
661 save_svd_hit_efficiency = refiners.save_fom(
662 ## \cond
663 name="{module.id}_subdetector_figures_of_merit",
664 title="Overview figures in {module.title}",
665 description="Hit efficiency in the subdetectors",
666 key="svd hit efficiency",
667 select="mc_svd_hit_efficiency",
668 aggregation=np.nanmean,
669 filter_on="is_matchedPrimary"
670 ## \endcond
671 )
672
673 ## Save simple FOM
674 save_cdc_hit_efficiency = refiners.save_fom(
675 ## \cond
676 name="{module.id}_subdetector_figures_of_merit",
677 title="Overview figures in {module.title}",
678 description="Hit efficiency in the subdetectors",
679 key="cdc hit efficiency",
680 select="mc_cdc_hit_efficiency",
681 aggregation=np.nanmean,
682 filter_on="is_matchedPrimary"
683 ## \endcond
684 )
685
686 ## Save simple FOM
687 save_hit_purity = refiners.save_fom(
688 ## \cond
689 name="{module.id}_subdetector_figures_of_merit",
690 title="Overview figures in {module.title}",
691 description="Hit purity in the subdetectors",
692 key="hit purity",
693 select="hit_purity",
694 aggregation=np.nanmean,
695 filter_on="is_matchedPrimary"
696 ## \endcond
697 )
698
699 ## Save simple FOM
700 save_pxd_hit_purity = refiners.save_fom(
701 ## \cond
702 name="{module.id}_subdetector_figures_of_merit",
703 title="Overview figures in {module.title}",
704 description="Hit purity in the subdetectors",
705 key="pxd hit purity",
706 select="pxd_hit_purity",
707 aggregation=np.nanmean,
708 filter_on="is_matchedPrimary"
709 ## \endcond
710 )
711
712 ## Save simple FOM
713 save_svd_hit_purity = refiners.save_fom(
714 ## \cond
715 name="{module.id}_subdetector_figures_of_merit",
716 title="Overview figures in {module.title}",
717 description="Hit purity in the subdetectors",
718 key="svd hit purity",
719 select="svd_hit_purity",
720 aggregation=np.nanmean,
721 filter_on="is_matchedPrimary"
722 ## \endcond
723 )
724
725 ## Save simple FOM
726 save_cdc_hit_purity = refiners.save_fom(
727 ## \cond
728 name="{module.id}_subdetector_figures_of_merit",
729 title="Overview figures in {module.title}",
730 description="Hit purity in the subdetectors",
731 key="cdc hit purity",
732 select="cdc_hit_purity",
733 aggregation=np.nanmean,
734 filter_on="is_matchedPrimary"
735 ## \endcond
736 )
737
738 ## Creates a distribution of p values from the Genfit track fit for match pr tracks.
739 save_p_value_histogram = refiners.save_histograms(
740 ## \cond
741 filter_on="is_matched",
742 select={"p_value": "Genfit p value"},
743 description="""
744 The distribution of p values from the Genfit track fit.
745 If all errors are propagated correctly the distribution should be flat.
746 Generally some peaking behavior towards zero is too be expected if the errors are underestimated.
747 """,
748 check="The distribution should be flat."
749 ## \endcond
750 )
751
752 ## Pull of seed omega
753 save_seed_omega_pull_analysis = refiners.save_pull_analysis(
754 ## \cond
755 filter_on="is_matched",
756 part_name="seed_omega",
757 quantity_name="seed #omega",
758 folder_name="pull_seed_omega",
759 truth_name="omega_truth",
760 unit="1/cm",
761 ## \endcond
762 )
763
764 ## Pull of seed tan(lambda)
765 save_seed_tan_lambda_pull_analysis = refiners.save_pull_analysis(
766 ## \cond
767 filter_on="is_matched",
768 part_name="seed_tan_lambda",
769 quantity_name="seed tan #lambda",
770 folder_name="pull_seed_tan_lambda",
771 truth_name="tan_lambda_truth",
772 ## \endcond
773 )
774
775 ## Pull of fitted omega
776 save_fitted_omega_pull_analysis = refiners.save_pull_analysis(
777 ## \cond
778 filter_on="is_matched",
779 part_name="omega",
780 quantity_name="#omega",
781 folder_name="pull_fitted_omega",
782 unit="1/cm",
783 ## \endcond
784 )
785
786 ## Pull of fitted tan(lambda)
787 save_fitted_tan_lambda_pull_analysis = refiners.save_pull_analysis(
788 ## \cond
789 filter_on="is_matched",
790 part_name="tan_lambda",
791 quantity_name="tan #lambda",
792 folder_name="pull_fitted_tan_lambda",
793 ## \endcond
794 )
795
796 ## Pull of fitted transverse momentum
797 save_fitted_pt_pull_analysis = refiners.save_pull_analysis(
798 ## \cond
799 filter_on="is_matched",
800 part_name="pt",
801 quantity_name="p_{t}",
802 folder_name="pull_fitted_p_t",
803 ## \endcond
804 )
805
806 ## Pull of fitted x coordinate grouped by true transverse momentum
807 save_fitted_x_pull_analysis = refiners.save_pull_analysis(
808 ## \cond
809 filter_on="is_matched",
810 part_name="x",
811 quantity_name="x",
812 folder_name="pull_fitted_x{groupby_addition}",
813 groupby=[None, ("pt_truth", [0.070, 0.250, 0.600])],
814 ## \endcond
815 )
816
817 ## Pull of fitted y coordinate grouped by true transverse momentum
818 save_fitted_y_pull_analysis = refiners.save_pull_analysis(
819 ## \cond
820 filter_on="is_matched",
821 part_name="y",
822 quantity_name="y",
823 folder_name="pull_fitted_y{groupby_addition}",
824 groupby=[None, ("pt_truth", [0.070, 0.250, 0.600])],
825 ## \endcond
826 )
827
828 ## Pull of fitted z coordinate grouped by true transverse momentum
829 save_fitted_z_pull_analysis = refiners.save_pull_analysis(
830 ## \cond
831 filter_on="is_matched",
832 part_name="z",
833 quantity_name="z",
834 folder_name="pull_fitted_z{groupby_addition}",
835 groupby=[None, ("pt_truth", [0.070, 0.250, 0.600])],
836 ## \endcond
837 )
838
839 ## Resolutions as a function of true p_t
840 save_resolutions_by_pt_profile = refiners.save_profiles(
841 ## \cond
842 filter_on="is_matched",
843 select={
844 "pt_truth": "true p_{t}",
845 "d0_variance": "#sigma(d_{0})",
846 "z0_variance": "#sigma(z_{0})",
847 "pt_resolution": "#sigma(p_{t}) / p_{t}",
848 },
849 y=[
850 "#sigma(d_{0})",
851 "#sigma(z_{0})",
852 "#sigma(p_{t}) / p_{t}",
853 ],
854 y_log=True,
855 ## \endcond
856 )
__init__(self, name, contact, output_file_name=None, reco_tracks_name='RecoTracks', mc_reco_tracks_name='MCRecoTracks', expert_level=None)