Belle II Software light-2604-jellyfish
stdV0s.py
1#!/usr/bin/env python3
2
3
10
11import b2bii
12from basf2 import B2ERROR, B2WARNING
13import modularAnalysis as ma
14from stdCharged import stdPi, stdPr
15import vertex
16
17
18def stdKshorts(
19 prioritiseV0=True,
20 fitter="TreeFit",
21 path=None,
22 updateAllDaughters=False,
23 writeOut=False,
24 addSuffix=False,
25):
26 """
27 Load a combined list of the Kshorts list from V0 objects merged with
28 a list of particles combined using the analysis ParticleCombiner module.
29
30 The ParticleList is named ``K_S0:merged`` by default. If ``addSuffix`` is set to True,
31 then a suffix of form ``_<fitter>`` is added depending on the chosen fitter.
32 A vertex fit is performed and only candidates with an invariant mass in the
33 range :math:`0.450 < M < 0.550~GeV` after the vertex fit,
34 and for which the vertex fit did not fail, are kept.
35
36 The vertex fitter can be selected among ``TreeFit``, ``KFit``, and ``Rave``.
37
38 Parameters:
39 prioritiseV0 (bool): should the V0 mdst objects be prioritised when merging?
40 fitter (str): vertex fitter name, valid options are ``TreeFit``, ``KFit``, and ``Rave``.
41 path (basf2.Path): the path to load the modules
42 updateAllDaughters (bool): see the ``updateAllDaughters`` parameter of `vertex.treeFit`
43 or the ``daughtersUpdate`` parameter of `vertex.kFit` / `vertex.raveFit`.
44
45 .. warning:: The momenta of the daughters are updated only if ``updateAllDaughters`` is set
46 to ``True`` (i.e. **not** by default). Some variables, e.g. `daughterAngle`, will only
47 return meaningful results if the daughters momenta are updated.
48
49 This happens because variables like `daughterAngle` assume the direction of the
50 daughers momenta *at the Ks vertex* to be provided, while non-updated daughters will
51 provide their momenta direction at the point-of-closest-approach (POCA) to the beam axis.
52
53 writeOut (bool): whether RootOutput module should save the created ParticleList
54 addSuffix (bool): whether to add a suffix of form ``_<fitter>`` to the ParticleList name
55 depending on the chosen fitter
56 """
57 suffix = ""
58 if addSuffix:
59 suffix = f"_{fitter}"
60 # Fill one list from V0
61 ma.fillParticleList(
62 f"K_S0:V0_ToFit{suffix} -> pi+ pi-", "", writeOut=writeOut, path=path
63 )
64 # Perform vertex fit and apply tighter mass window
65 if fitter == "TreeFit":
67 f"K_S0:V0_ToFit{suffix}",
68 conf_level=0.0,
69 path=path,
70 updateAllDaughters=updateAllDaughters,
71 )
72 elif fitter == "KFit":
74 f"K_S0:V0_ToFit{suffix}",
75 conf_level=0.0,
76 path=path,
77 daughtersUpdate=updateAllDaughters,
78 )
79 elif fitter == "Rave":
81 f"K_S0:V0_ToFit{suffix}",
82 conf_level=0.0,
83 path=path,
84 silence_warning=True,
85 daughtersUpdate=updateAllDaughters,
86 )
87 else:
88 B2ERROR(
89 "Valid fitter options for Kshorts are 'TreeFit', 'KFit', and 'Rave'. However, the latter is not recommended."
90 )
91 ma.applyCuts(f"K_S0:V0_ToFit{suffix}", "0.450 < M < 0.550", path=path)
92 # Reconstruct a second list
93 stdPi("all", path=path, writeOut=writeOut) # no quality cuts
94 ma.reconstructDecay(
95 f"K_S0:RD{suffix} -> pi+:all pi-:all",
96 "0.3 < M < 0.7",
97 1,
98 writeOut=writeOut,
99 path=path,
100 )
101 # Again perform vertex fit and apply tighter mass window
102 if fitter == "TreeFit":
104 f"K_S0:RD{suffix}",
105 conf_level=0.0,
106 path=path,
107 updateAllDaughters=updateAllDaughters,
108 )
109 elif fitter == "KFit":
111 f"K_S0:RD{suffix}",
112 conf_level=0.0,
113 path=path,
114 daughtersUpdate=updateAllDaughters,
115 )
116 elif fitter == "Rave":
118 f"K_S0:RD{suffix}",
119 conf_level=0.0,
120 path=path,
121 silence_warning=True,
122 daughtersUpdate=updateAllDaughters,
123 )
124 ma.applyCuts(f"K_S0:RD{suffix}", "0.450 < M < 0.550", path=path)
125 # Create merged list based on provided priority
126 ma.mergeListsWithBestDuplicate(
127 f"K_S0:merged{suffix}",
128 [f"K_S0:V0_ToFit{suffix}", f"K_S0:RD{suffix}"],
129 variable="particleSource",
130 preferLowest=prioritiseV0,
131 path=path,
132 )
133
134
135def goodBelleKshort(path):
136 """
137 Load the Belle goodKshort list. Creates a ParticleList named
138 ``K_S0:legacyGoodKS``. A vertex fit is performed and only candidates that
139 satisfy the :b2:var:`goodBelleKshort` criteria, with an invariant mass in the range
140 :math:`0.468 < M < 0.528~GeV` after the vertex fit, and for which the vertex fit did not fail, are kept.
141
142 Parameters:
143 path (basf2.Path): the path to load the modules
144 """
145 B2WARNING(
146 "The standard K_S0 list 'K_S0:legacyGoodKS' is deprecated "
147 "and will be removed at the end of 2026. "
148 "Please update your analysis accordingly."
149 )
150 if b2bii.isB2BII():
151 ma.cutAndCopyList(
152 "K_S0:legacyGoodKS", "K_S0:mdst", "0.3 < M < 0.7", writeOut=True, path=path
153 )
154 else:
155 ma.fillParticleList(
156 "K_S0:legacyGoodKS -> pi+ pi-", "0.3 < M < 0.7", writeOut=True, path=path
157 )
158 vertex.kFit("K_S0:legacyGoodKS", conf_level=0.0, path=path)
159 ma.applyCuts(
160 "K_S0:legacyGoodKS", "0.468 < M < 0.528 and goodBelleKshort==1", path=path
161 )
162
163
164def scaleErrorKshorts(
165 prioritiseV0=True,
166 fitter="TreeFit",
167 scaleFactors_V0=[1.125927, 1.058803, 1.205928, 1.066734, 1.047513],
168 scaleFactorsNoPXD_V0=[1.125927, 1.058803, 1.205928, 1.066734, 1.047513],
169 d0Resolution_V0=[0.001174, 0.000779],
170 z0Resolution_V0=[0.001350, 0.000583],
171 d0MomThr_V0=0.500000,
172 z0MomThr_V0=0.00000,
173 scaleFactors_RD=[1.149631, 1.085547, 1.151704, 1.096434, 1.086659],
174 scaleFactorsNoPXD_RD=[1.149631, 1.085547, 1.151704, 1.096434, 1.086659],
175 d0Resolution_RD=[0.00115328, 0.00134704],
176 z0Resolution_RD=[0.00124327, 0.0013272],
177 d0MomThr_RD=0.500000,
178 z0MomThr_RD=0.500000,
179 addSuffix=False,
180 path=None,
181):
182 """
183 Reconstruct K_S0 applying helix error correction to K_S0 daughters given by ``modularAnalysis.scaleError``.
184 The ParticleList is named ``K_S0:scaled`` by default. If ``addSuffix`` is set to True,
185 then a suffix of form ``_<fitter>`` is added.
186
187 Considering the difference of multiple scattering through the beam pipe,
188 different parameter sets are used for K_S0 decaying outside/inside the beam pipe (``K_S0:V0/RD``).
189
190 Only for TDCPV analysis.
191
192 @param prioritiseV0 If True K_S0 from V0 object is prioritised over RD when merged.
193 @param fitter Vertex fitter option. Choose from ``TreeFit``, ``KFit`` and ``Rave``.
194 @param scaleFactors_V0 List of five constants to be multiplied to each of helix errors (for tracks with a PXD hit)
195 @param scaleFactorsNoPXD_V0 List of five constants to be multiplied to each of helix errors (for tracks without a PXD hit)
196 @param d0Resolution_V0 List of two parameters, (a [cm], b [cm/(GeV/c)]),
197 defining d0 best resolution as sqrt{ a**2 + (b / (p*beta*sinTheta**1.5))**2 }
198 @param z0Resolution_V0 List of two parameters, (a [cm], b [cm/(GeV/c)]),
199 defining z0 best resolution as sqrt{ a**2 + (b / (p*beta*sinTheta**2.5))**2 }
200 @param d0MomThr_V0 d0 best resolution is kept constant below this momentum
201 @param z0MomThr_V0 z0 best resolution is kept constant below this momentum
202 @param scaleFactors_RD List of five constants to be multiplied to each of helix errors (for tracks with a PXD hit)
203 @param scaleFactorsNoPXD_RD List of five constants to be multiplied to each of helix errors (for tracks without a PXD hit)
204 @param d0Resolution_RD List of two parameters, (a [cm], b [cm/(GeV/c)]),
205 defining d0 best resolution as sqrt{ a**2 + (b / (p*beta*sinTheta**1.5))**2 }
206 @param z0Resolution_RD List of two parameters, (a [cm], b [cm/(GeV/c)]),
207 defining z0 best resolution as sqrt{ a**2 + (b / (p*beta*sinTheta**2.5))**2 }
208 @param d0MomThr_RD d0 best resolution is kept constant below this momentum
209 @param z0MomThr_RD z0 best resolution is kept constant below this momentum
210 @param addSuffix Whether to add a suffix of form ``_<fitter>`` to the ParticleList name
211 depending on the chosen fitter
212
213 """
214 from basf2 import register_module
215
216 suffix = ""
217 if addSuffix:
218 suffix = f"_{fitter}"
219
220 # Load K_S0 from V0 and apply helix error correction to V0 daughters
221 ma.fillParticleList(f"K_S0:V0{suffix} -> pi+ pi-", "", True, path=path)
222 scaler_V0 = register_module("HelixErrorScaler")
223 scaler_V0.set_name("ScaleError_" + f"K_S0:V0{suffix}")
224 scaler_V0.param("inputListName", f"K_S0:V0{suffix}")
225 scaler_V0.param("outputListName", f"K_S0:V0_scaled{suffix}")
226 scaler_V0.param("scaleFactors_PXD", scaleFactors_V0)
227 scaler_V0.param("scaleFactors_noPXD", scaleFactorsNoPXD_V0)
228 scaler_V0.param("d0ResolutionParameters", d0Resolution_V0)
229 scaler_V0.param("z0ResolutionParameters", z0Resolution_V0)
230 scaler_V0.param("d0MomentumThreshold", d0MomThr_V0)
231 scaler_V0.param("z0MomentumThreshold", z0MomThr_V0)
232 path.add_module(scaler_V0)
233
234 # Perform vertex fit and apply tighter mass window
235 if fitter == "TreeFit":
236 vertex.treeFit(f"K_S0:V0_scaled{suffix}", conf_level=0.0, path=path)
237 elif fitter == "KFit":
238 vertex.kFit(f"K_S0:V0_scaled{suffix}", conf_level=0.0, path=path)
239 elif fitter == "Rave":
241 f"K_S0:V0_scaled{suffix}", conf_level=0.0, path=path, silence_warning=True
242 )
243 else:
244 B2ERROR(
245 "Valid fitter options for Kshorts are 'TreeFit', 'KFit', and 'Rave'. However, the latter is not recommended."
246 )
247 ma.applyCuts(f"K_S0:V0_scaled{suffix}", "0.450 < M < 0.550", path=path)
248
249 # Reconstruct a second list
250 stdPi("all", path=path)
251 ma.scaleError(
252 "pi+:scaled",
253 "pi+:all",
254 scaleFactors=scaleFactors_RD,
255 scaleFactorsNoPXD=scaleFactorsNoPXD_RD,
256 d0Resolution=d0Resolution_RD,
257 z0Resolution=z0Resolution_RD,
258 d0MomThr=d0MomThr_RD,
259 z0MomThr=z0MomThr_RD,
260 path=path,
261 )
262
263 ma.reconstructDecay(
264 f"K_S0:RD_scaled{suffix} -> pi+:scaled pi-:scaled", "0.3 < M < 0.7", 1, True, path=path
265 )
266 # Again perform vertex fit and apply tighter mass window
267 if fitter == "TreeFit":
268 vertex.treeFit(f"K_S0:RD_scaled{suffix}", conf_level=0.0, path=path)
269 elif fitter == "KFit":
270 vertex.kFit(f"K_S0:RD_scaled{suffix}", conf_level=0.0, path=path)
271 elif fitter == "Rave":
273 f"K_S0:RD_scaled{suffix}", conf_level=0.0, path=path, silence_warning=True
274 )
275 ma.applyCuts(f"K_S0:RD_scaled{suffix}", "0.450 < M < 0.550", path=path)
276 # Create merged list based on provided priority
277 ma.mergeListsWithBestDuplicate(
278 f"K_S0:scaled{suffix}",
279 [f"K_S0:V0_scaled{suffix}", f"K_S0:RD_scaled{suffix}"],
280 variable="particleSource",
281 preferLowest=prioritiseV0,
282 path=path,
283 )
284
285
286def stdLambdas(
287 prioritiseV0=True,
288 fitter="TreeFit",
289 path=None,
290 updateAllDaughters=False,
291 writeOut=False,
292 addSuffix=False,
293):
294 """
295 Load a combined list of the Lambda list from V0 objects merged with
296 a list of particles combined using the analysis ParticleCombiner module.
297
298 The ParticleList is named ``Lambda0:merged`` by default. If ``addSuffix`` is set to True,
299 then a suffix of form ``_<fitter>`` is added depending on the chosen fitter.
300 A vertex fit is performed and only candidates with an invariant mass in the
301 range :math:`1.10 < M < 1.13~GeV` after the vertex fit,
302 and for which the vertex fit did not fail, are kept.
303
304 The vertex fitter can be selected among ``TreeFit``, ``KFit``, and ``Rave``.
305
306 Parameters:
307 prioritiseV0 (bool): should the V0 mdst objects be prioritised when merging?
308 fitter (str): vertex fitter name, valid options are ``TreeFit``, ``KFit``, and ``Rave``.
309 path (basf2.Path): the path to load the modules
310 updateAllDaughters (bool): see the ``updateAllDaughters`` parameter of `vertex.treeFit`
311 or the ``daughtersUpdate`` parameter of `vertex.kFit` / `vertex.raveFit`.
312
313 .. warning:: The momenta of the daughters are updated only if ``updateAllDaughters`` is set
314 to ``True`` (i.e. **not** by default). Some variables, e.g. `daughterAngle`, will only
315 return meaningful results if the daughters momenta are updated.
316
317 This happens because variables like `daughterAngle` assume the direction of the
318 daughers momenta *at the Lambda vertex* to be provided, while non-updated daughters
319 will provide their momenta direction at the point-of-closest-approach (POCA) to the
320 beam axis.
321
322 writeOut (bool): whether RootOutput module should save the created ParticleList
323 addSuffix (bool): whether to add a suffix of form ``_<fitter>`` to the ParticleList name
324 depending on the chosen fitter
325 """
326 suffix = ""
327 if addSuffix:
328 suffix = f"_{fitter}"
329 if f"PListMerger_Lambda0:merged{suffix}" in [m.name() for m in path.modules()]:
330 return
331 # Fill one list from V0
332 ma.fillParticleList(
333 f"Lambda0:V0_ToFit{suffix} -> p+ pi-", "", writeOut=writeOut, path=path
334 )
335 # Perform vertex fit and apply tighter mass window
336 if fitter == "TreeFit":
338 f"Lambda0:V0_ToFit{suffix}",
339 conf_level=0.0,
340 path=path,
341 updateAllDaughters=updateAllDaughters,
342 )
343 elif fitter == "KFit":
345 f"Lambda0:V0_ToFit{suffix}",
346 conf_level=0.0,
347 path=path,
348 daughtersUpdate=updateAllDaughters,
349 )
350 elif fitter == "Rave":
352 f"Lambda0:V0_ToFit{suffix}",
353 conf_level=0.0,
354 path=path,
355 silence_warning=True,
356 daughtersUpdate=updateAllDaughters,
357 )
358 else:
359 B2ERROR(
360 "Valid fitter options for Lambdas are 'TreeFit', 'KFit', and 'Rave'. However, the latter is not recommended."
361 )
362 ma.applyCuts(f"Lambda0:V0_ToFit{suffix}", "1.10 < M < 1.13", path=path)
363 # Find V0 duplicate with better vertex fit quality
364 ma.markDuplicate(f"Lambda0:V0_ToFit{suffix}", False, path=path)
365 ma.applyCuts(f"Lambda0:V0_ToFit{suffix}", "extraInfo(highQualityVertex)", path=path)
366 # Reconstruct a second list
367 stdPi("all", path=path, writeOut=writeOut) # no quality cuts
368 stdPr("all", path=path, writeOut=writeOut) # no quality cuts
369 ma.reconstructDecay(
370 f"Lambda0:RD{suffix} -> p+:all pi-:all",
371 "0.9 < M < 1.3",
372 1,
373 writeOut=writeOut,
374 path=path,
375 )
376 # Again perform vertex fit and apply tighter mass window
377 if fitter == "TreeFit":
379 f"Lambda0:RD{suffix}",
380 conf_level=0.0,
381 path=path,
382 updateAllDaughters=updateAllDaughters,
383 )
384 elif fitter == "KFit":
386 f"Lambda0:RD{suffix}",
387 conf_level=0.0,
388 path=path,
389 daughtersUpdate=updateAllDaughters,
390 )
391 elif fitter == "Rave":
393 f"Lambda0:RD{suffix}",
394 conf_level=0.0,
395 path=path,
396 silence_warning=True,
397 daughtersUpdate=updateAllDaughters,
398 )
399 ma.applyCuts(f"Lambda0:RD{suffix}", "1.10 < M < 1.13", path=path)
400 # Find RD duplicate with better vertex fit quality
401 ma.markDuplicate(f"Lambda0:RD{suffix}", False, path=path)
402 ma.applyCuts(f"Lambda0:RD{suffix}", "extraInfo(highQualityVertex)", path=path)
403 ma.mergeListsWithBestDuplicate(
404 f"Lambda0:merged{suffix}",
405 [f"Lambda0:V0_ToFit{suffix}", f"Lambda0:RD{suffix}"],
406 variable="particleSource",
407 preferLowest=prioritiseV0,
408 path=path,
409 )
isB2BII()
Definition b2bii.py:14
treeFit(list_name, conf_level=0.001, massConstraint=[], ipConstraint=False, updateAllDaughters=False, massConstraintDecayString='', massConstraintMassValues=[], customOriginConstraint=False, customOriginVertex=[0.001, 0, 0.0116], customOriginCovariance=[0.0048, 0, 0, 0, 0.003567, 0, 0, 0, 0.0400], originDimension=3, treatAsInvisible='', ignoreFromVertexFit='', path=None)
Definition vertex.py:237
raveFit(list_name, conf_level, fit_type='vertex', decay_string='', constraint='', daughtersUpdate=False, path=None, silence_warning=False)
Definition vertex.py:168
kFit(list_name, conf_level, fit_type='vertex', constraint='', daughtersUpdate=False, decay_string='', massConstraint=[], recoilMass=0, smearing=0, path=None)
Definition vertex.py:126