Belle II Software  release-05-01-25
B2A602-BestCandidateSelection.py
1 #!/usr/bin/env python3
2 
3 
26 
27 import basf2 as b2
28 import modularAnalysis as ma
29 import variables.collections as vc
30 import variables.utils as vu
31 import vertex as vx
32 import stdCharged as stdc
33 import variables as va
34 
35 # create path
36 my_path = b2.create_path()
37 
38 # load input ROOT file
39 ma.inputMdst(environmentType='default',
40  filename=b2.find_file('B2pi0D_D2hh_D2hhh_B2munu.root', 'examples', False),
41  path=my_path)
42 
43 # use standard final state particle lists
44 #
45 # creates "pi+:all" ParticleList (and c.c.)
46 stdc.stdPi('all', path=my_path)
47 # rank all pions of the event by momentum magnitude
48 # variable stored to extraInfo as pi_p_rank
49 ma.rankByLowest(particleList='pi+:all',
50  variable='p',
51  outputVariable='pi_p_rank',
52  path=my_path)
53 
54 va.variables.addAlias('pi_p_rank', 'extraInfo(pi_p_rank)')
55 
56 # creates "K+:loose" ParticleList (and c.c.)
57 stdc.stdK(listtype='loose', path=my_path)
58 
59 # keep only candidates with 1.8 < M(Kpi) < 1.9 GeV
60 ma.reconstructDecay(decayString='D0 -> K-:loose pi+:all',
61  cut='1.8 < M < 1.9',
62  path=my_path)
63 
64 # perform MC matching (MC truth association)
65 ma.matchMCTruth(list_name='D0', path=my_path)
66 
67 # perform D0 vertex fit
68 # keep only candidates passing C.L. value of the fit > conf_level
69 vx.treeFit(list_name='D0',
70  conf_level=0, # 0: keep only fit survivors, -1: keep all candidates; optimise this cut for your need
71  ipConstraint=True,
72  # pins the B0 PRODUCTION vertex to the IP (increases SIG and BKG rejection) use for better vertex resolution
73  updateAllDaughters=True, # update momenta of ALL particles
74  path=my_path)
75 
76 # smaller |M_rec - M| is better, add here a different output variable name, due to parentheses
77 ma.rankByLowest(particleList='D0',
78  variable='abs(dM)',
79  outputVariable='abs_dM_rank',
80  path=my_path)
81 
82 # maybe not the best idea, but might cut away candidates with failed fits
83 ma.rankByHighest(particleList='D0',
84  variable='chiProb',
85  path=my_path)
86 
87 # One can store quantities of candidates with specific ranks.
88 # Here, we look at the PID of the pion for the D0 candidates with rank 1 and 2 and the difference of those values.
89 # The second argument of getVariableByRank is the ordering variable of the previous ranking.
90 va.variables.addAlias('D0_rank1_pi_PIDpi', 'getVariableByRank(D0, chiProb, daughter(1, pionID), 1)')
91 va.variables.addAlias('D0_rank2_pi_PIDpi', 'getVariableByRank(D0, chiProb, daughter(1, pionID), 2)')
92 
93 # It makes sense to put these variables (or a combination of them) into an event-based ExtraInfo:
94 ma.variablesToEventExtraInfo('D0', {'formula(D0_rank1_pi_PIDpi - D0_rank2_pi_PIDpi)': 'D0_pi_PIDpi_r1_minus_r2'}, path=my_path)
95 va.variables.addAlias('D0_pi_PIDpi_r1_minus_r2', 'eventExtraInfo(D0_pi_PIDpi_r1_minus_r2)')
96 
97 # Now let's do mixed ranking:
98 # First, we want to rank D candidates by the momentum of the pions
99 # Second, we want to rank those D candidates that were built with the highest-p by the vertex Chi2
100 # This doesn't have any sense, but shows how to work with consecutive rankings
101 #
102 # Let's add alias for the momentum rank of pions in D
103 va.variables.addAlias('D1_pi_p_rank', 'daughter(1,pi_p_rank)')
104 # Ranking D candidates by this variable.
105 # Candidates built with the same pion get the same rank (allowMultiRank=True).
106 ma.rankByHighest(particleList='D0',
107  variable='D1_pi_p_rank',
108  allowMultiRank=True,
109  outputVariable="first_D_rank",
110  path=my_path)
111 va.variables.addAlias('first_D_rank', 'extraInfo(first_D_rank)')
112 # Now let's rank by chiProb only those candidates that are built with the highest momentum pi
113 # Other candidates will get this rank equal to -1
114 ma.rankByHighest(particleList="D0",
115  variable="chiProb",
116  cut="first_D_rank == 1",
117  outputVariable="second_D_rank",
118  path=my_path)
119 va.variables.addAlias('second_D_rank', 'extraInfo(second_D_rank)')
120 
121 # add rank variable aliases for easier use
122 va.variables.addAlias('dM_rank', 'extraInfo(abs_dM_rank)')
123 va.variables.addAlias('chiProb_rank', 'extraInfo(chiProb_rank)')
124 
125 # Select variables that we want to store to ntuple
126 fs_hadron_vars = vu.create_aliases_for_selected(list_of_variables=vc.mc_truth, decay_string='D0 -> ^K- ^pi+')
127 
128 d0_vars = vc.vertex + \
129  vc.mc_vertex + \
130  vc.mc_truth + \
131  fs_hadron_vars + \
132  ['dM', 'chiProb', 'dM_rank', 'chiProb_rank', 'D1_pi_p_rank', 'first_D_rank', 'second_D_rank', 'D0_pi_PIDpi_r1_minus_r2']
133 
134 
135 # Saving variables to ntuple
136 output_file = 'B2A602-BestCandidateSelection.root'
137 ma.variablesToNtuple(decayString='D0',
138  variables=d0_vars,
139  filename=output_file,
140  treename='D0',
141  path=my_path)
142 
143 
144 # Process the events
145 b2.process(my_path)
146 
147 # print out the summary
148 print(b2.statistics)
variables.utils
Definition: utils.py:1
variables.collections
Definition: collections.py:1