Belle II Software development
BelleVariables.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9// Own header.
10#include <analysis/variables/BelleVariables.h>
11
12// include VariableManager
13#include <analysis/VariableManager/Manager.h>
14
15#include <analysis/dataobjects/Particle.h>
16#include <analysis/variables/Variables.h>
17#include <analysis/variables/VertexVariables.h>
18#include <analysis/variables/ECLVariables.h>
19#include <analysis/variables/V0DaughterTrackVariables.h>
20#include <mdst/dataobjects/Track.h>
21
22#include <framework/logging/Logger.h>
23#include <framework/gearbox/Const.h>
24
25#include <b2bii/dataobjects/BelleTrkExtra.h>
26
27#include <TVectorF.h>
28
29namespace Belle2 {
34 namespace Variable {
35 bool goodBelleKshort(const Particle* KS)
36 {
37 // check input
38 if (KS->getNDaughters() != 2) {
39 B2WARNING("goodBelleKshort is only defined for a particle with two daughters");
40 return false;
41 }
42 const Particle* d0 = KS->getDaughter(0);
43 const Particle* d1 = KS->getDaughter(1);
44 if ((d0->getCharge() == 0) || (d1->getCharge() == 0)) {
45 B2WARNING("goodBelleKshort is only defined for a particle with charged daughters");
46 return false;
47 }
48 if (abs(KS->getPDGCode()) != Const::Kshort.getPDGCode())
49 B2WARNING("goodBelleKshort is being applied to a candidate with PDG " << KS->getPDGCode());
50
51 // If goodKs exists, return the value
52 if (KS->hasExtraInfo("goodKs")) {
53 return bool(KS->getExtraInfo("goodKs"));
54 }
55
56 // Belle selection
57 double p = particleP(KS);
58 double fl = particleDRho(KS);
59 double dphi = acos(((particleDX(KS) * particlePx(KS)) + (particleDY(KS) * particlePy(KS))) / (fl * sqrt(particlePx(KS) * particlePx(
60 KS) + particlePy(KS) * particlePy(KS))));
61 // particleDRho returns track d0 relative to IP for tracks
62 double dr = std::min(abs(particleDRho(d0)), abs(particleDRho(d1)));
63 double zdist = v0DaughterZ0Diff(KS);
64
65 bool low = p < 0.5 && abs(zdist) < 0.8 && dr > 0.05 && dphi < 0.3;
66 bool mid = p < 1.5 && p > 0.5 && abs(zdist) < 1.8 && dr > 0.03 && dphi < 0.1 && fl > .08;
67 bool high = p > 1.5 && abs(zdist) < 2.4 && dr > 0.02 && dphi < 0.03 && fl > .22;
68
69 if (low || mid || high) {
70 return true;
71 } else
72 return false;
73 }
74
75
76 double goodBelleLambda(const Particle* Lambda)
77 {
78 if (Lambda->getNDaughters() != 2) {
79 B2WARNING("goodBelleLambda is only defined for a particle with two daughters");
80 return 0.;
81 }
82 const Particle* d0 = Lambda->getDaughter(0);
83 const Particle* d1 = Lambda->getDaughter(1);
84 if ((d0->getCharge() == 0) || (d1->getCharge() == 0)) {
85 B2WARNING("goodBelleLambda is only defined for a particle with charged daughters");
86 return 0.;
87 }
88 if (abs(Lambda->getPDGCode()) != Const::Lambda.getPDGCode()) {
89 B2WARNING("goodBelleLambda is being applied to a candidate with PDG " << Lambda->getPDGCode());
90 }
91
92 if (Lambda->hasExtraInfo("goodLambda"))
93 return Lambda->getExtraInfo("goodLambda");
94
95 double p = particleP(Lambda);
96 double dr = std::min(abs(particleDRho(d0)), abs(particleDRho(d1)));
97 double zdist = v0DaughterZ0Diff(Lambda);
98 double dphi = acos(cosAngleBetweenMomentumAndVertexVectorInXYPlane(Lambda));
99 // Flight distance of Lambda0 in xy plane
100 double fl = particleDRho(Lambda);
101
102 // goodBelleLambda == 1 (optimized for proton PID > 0.6)
103 bool high1 = p >= 1.5 && abs(zdist) < 12.9 && dr > 0.008 && dphi < 0.09 && fl > 0.22;
104 bool mid1 = p >= 0.5 && p < 1.5 && abs(zdist) < 9.8 && dr > 0.01 && dphi < 0.18 && fl > 0.16;
105 bool low1 = p < 0.5 && abs(zdist) < 2.4 && dr > 0.027 && dphi < 1.2 && fl > 0.11;
106
107 // goodBelleLambda == 2 (optimized without PID selection)
108 bool high2 = p >= 1.5 && abs(zdist) < 7.7 && dr > 0.018 && dphi < 0.07 && fl > 0.35;
109 bool mid2 = p >= 0.5 && p < 1.5 && abs(zdist) < 2.1 && dr > 0.033 && dphi < 0.10 && fl > 0.24;
110 bool low2 = p < 0.5 && abs(zdist) < 1.9 && dr > 0.059 && dphi < 0.6 && fl > 0.17;
111
112 if (low2 || mid2 || high2) {
113 return 2.0;
114 } else if (low1 || mid1 || high1) {
115 return 1.0;
116 } else {
117 return 0.0;
118 }
119 }
120
121
122 bool isGoodBelleGamma(int region, double energy)
123 {
124 bool goodGammaRegion1, goodGammaRegion2, goodGammaRegion3;
125 goodGammaRegion1 = region == 1 && energy > 0.100;
126 goodGammaRegion2 = region == 2 && energy > 0.050;
127 goodGammaRegion3 = region == 3 && energy > 0.150;
128
129 return goodGammaRegion1 || goodGammaRegion2 || goodGammaRegion3;
130 }
131
132 bool goodBelleGamma(const Particle* particle)
133 {
134 double energy = eclClusterE(particle);
135 int region = eclClusterDetectionRegion(particle);
136
137 return isGoodBelleGamma(region, energy);
138 }
139
140 BelleTrkExtra* getBelleTrkExtraInfoFromParticle(Particle const* particle)
141 {
142 const Track* track = particle->getTrack();
143 if (!track) {
144 return nullptr;
145 }
146 auto belleTrkExtra = track->getRelatedTo<BelleTrkExtra>();
147 if (!belleTrkExtra) {
148 return nullptr;
149 }
150 return belleTrkExtra;
151 }
152
153 double BelleFirstCDCHitX(const Particle* particle)
154 {
155 auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
156 if (!belleTrkExtra) {
157 B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
158 return Const::doubleNaN;
159 }
160 return belleTrkExtra->getTrackFirstX();
161 }
162
163 double BelleFirstCDCHitY(const Particle* particle)
164 {
165 auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
166 if (!belleTrkExtra) {
167 B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
168 return Const::doubleNaN;
169 }
170 return belleTrkExtra->getTrackFirstY();
171 }
172
173 double BelleFirstCDCHitZ(const Particle* particle)
174 {
175 auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
176 if (!belleTrkExtra) {
177 B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
178 return Const::doubleNaN;
179 }
180 return belleTrkExtra->getTrackFirstZ();
181 }
182
183 double BelleLastCDCHitX(const Particle* particle)
184 {
185 auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
186 if (!belleTrkExtra) {
187 B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
188 return Const::doubleNaN;
189 }
190 return belleTrkExtra->getTrackLastX();
191 }
192
193 double BelleLastCDCHitY(const Particle* particle)
194 {
195 auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
196 if (!belleTrkExtra) {
197 B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
198 return Const::doubleNaN;
199 }
200 return belleTrkExtra->getTrackLastY();
201 }
202
203 double BelleLastCDCHitZ(const Particle* particle)
204 {
205 auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
206 if (!belleTrkExtra) {
207 B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
208 return Const::doubleNaN;
209 }
210 return belleTrkExtra->getTrackLastZ();
211 }
212
213 double BellePi0InvariantMassSignificance(const Particle* particle)
214 {
215 TMatrixFSym covarianceMatrix(Particle::c_DimMomentum);
216 for (auto daughter : particle->getDaughters()) {
217 covarianceMatrix += daughter->getMomentumErrorMatrix();
218 }
219
220 TVectorF jacobian(Particle::c_DimMomentum);
221 jacobian[0] = -1.0 * particle->getPx() / particle->getMass();
222 jacobian[1] = -1.0 * particle->getPy() / particle->getMass();
223 jacobian[2] = -1.0 * particle->getPz() / particle->getMass();
224 jacobian[3] = 1.0 * particle->getEnergy() / particle->getMass();
225
226 double massErrSquared = jacobian * (covarianceMatrix * jacobian);
227
228 if (massErrSquared < 0.0)
229 return Const::doubleNaN;
230
231 double invMass = particleInvariantMassFromDaughters(particle);
232 double nomMass = particle->getPDGMass();
233
234 return (invMass - nomMass) / sqrt(massErrSquared);
235 }
236
237 double BelleTof(const Particle* particle)
238 {
239 auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
240 if (!belleTrkExtra) {
241 B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
242 return Const::doubleNaN;
243 }
244 return belleTrkExtra->getTof();
245 }
246
247 double BelleTofQuality(const Particle* particle)
248 {
249 auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
250 if (!belleTrkExtra) {
251 B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
252 return Const::doubleNaN;
253 }
254 return belleTrkExtra->getTofQuality();
255 }
256
257 double BelleTofSigma(const Particle* particle)
258 {
259 auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
260 if (!belleTrkExtra) {
261 B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
262 return Const::doubleNaN;
263 }
264 return belleTrkExtra->getTofSigma();
265 }
266
267 double BellePathLength(const Particle* particle)
268 {
269 auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
270 if (!belleTrkExtra) {
271 B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
272 return Const::doubleNaN;
273 }
274 return belleTrkExtra->getPathLength();
275 }
276
277 double BelleTofMass(const Particle* particle)
278 {
279 auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
280 if (!belleTrkExtra) {
281 B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
282 return Const::doubleNaN;
283 }
284 double time = belleTrkExtra->getTof();
285 double length = belleTrkExtra->getPathLength();
286 double p = particle->getP(); //3-momentum
287 double tofbeta = length / time / Belle2::Const::speedOfLight;
288 double tofmass = p * sqrt(1. / (tofbeta * tofbeta) - 1.); //(GeV)
289
290 return tofmass;
291 }
292
293 double BelledEdx(const Particle* particle)
294 {
295 auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
296 if (!belleTrkExtra) {
297 B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
298 return Const::doubleNaN;
299 }
300 return belleTrkExtra->getdEdx();
301 }
302
303 double BelledEdxQuality(const Particle* particle)
304 {
305 auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
306 if (!belleTrkExtra) {
307 B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
308 return Const::doubleNaN;
309 }
310 return belleTrkExtra->getdEdxQuality();
311 }
312
313 double BelleACCnPe(const Particle* particle)
314 {
315 auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
316 if (!belleTrkExtra) {
317 B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
318 return Const::doubleNaN;
319 }
320 return belleTrkExtra->getACCPe();
321 }
322
323 double BelleACCQuality(const Particle* particle)
324 {
325 auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
326 if (!belleTrkExtra) {
327 B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
328 return Const::doubleNaN;
329 }
330 return belleTrkExtra->getACCQuality();
331 }
332
333
334
335 VARIABLE_GROUP("Belle Variables");
336
337 REGISTER_VARIABLE("goodBelleKshort", goodBelleKshort, R"DOC(
338[Legacy] GoodKs Returns true if a :math:`K_{S}^0\to\pi\pi` candidate passes the Belle algorithm:
339a momentum-binned selection including requirements on impact parameter of, and
340angle between the daughter pions as well as separation from the vertex and
341flight distance in the transverse plane.
342
343.. seealso:: `BELLE2-NOTE-PH-2018-017 <https://docs.belle2.org/record/957>`_
344)DOC");
345
346 REGISTER_VARIABLE("goodBelleLambda", goodBelleLambda, R"DOC(
347[Legacy] Returns 2.0, 1.0, 0.0 as an indication of goodness of :math:`\Lambda^0` candidates,
348based on:
349
350* The distance of the two daughter tracks at their interception at z axis,
351* the minimum distance of the daughter tracks and the IP in xy plane,
352* the difference of the azimuthal angle of the vertex vector and the momentum vector,
353* and the flight distance of the Lambda0 candidates in xy plane.
354
355It reproduces the ``goodLambda()`` function in Belle.
356
357``goodBelleLambda`` selection 1 (selected with: ``goodBelleLambda>0``) maximizes the signal significance after applying
358``atcPIDBelle(4,2) > 0.6``, while ``goodBelleLambda`` selection 2 (``goodBelleLambda>1``) is tighter and maximizes the signal
359significance of a :math:`\Lambda^0` sample without any proton PID cut. However, it might still be beneficial to apply a proton PID
360cut on top of it. Which combination of proton PID cut and ``goodBelleLambda`` selection scenario is ideal, is probably
361analysis-dependent.
362
363.. warning:: ``goodBelleLambda`` is not optimized or tested on Belle II data.
364
365See Also:
366 * `BN-684`_ Lambda selection at Belle. K F Chen et al.
367 * The ``FindLambda`` class can be found at ``/belle_legacy/findLambda/findLambda.h``
368
369.. _BN-684: https://belle.kek.jp/secured/belle_note/gn684/bn684.ps.gz
370
371)DOC");
372
373 REGISTER_VARIABLE("goodBelleGamma", goodBelleGamma, R"DOC(
374[Legacy] Returns 1.0 if the photon candidate passes the simple region dependent
375energy selection for Belle data and MC.
376
377.. math::
378
379 E > 50 \textrm{ MeV; barrel}\\
380 E > 100 \textrm{ MeV; forward endcap}\\
381 E > 150 \textrm{ MeV; backward endcap}
382)DOC");
383
384 REGISTER_VARIABLE("BelleFirstCDCHitX", BelleFirstCDCHitX, R"DOC(
385[Legacy] Returns x component of starting point of the track near the 1st SVD or CDC hit for SVD1 data (exp. 7 - 27) or the 1st CDC hit for SVD2 data (from exp. 31). (Belle only, originally stored in mdst_trk_fit.)
386
387)DOC","cm");
388
389 REGISTER_VARIABLE("BelleFirstCDCHitY", BelleFirstCDCHitY, R"DOC(
390[Legacy] Returns y component of starting point of the track near the 1st SVD or CDC hit for SVD1 data (exp. 7 - 27) or the 1st CDC hit for SVD2 data (from exp. 31). (Belle only, originally stored in mdst_trk_fit.)
391
392)DOC","cm");
393
394 REGISTER_VARIABLE("BelleFirstCDCHitZ", BelleFirstCDCHitZ, R"DOC(
395[Legacy] Returns z component of starting point of the track near the 1st SVD or CDC hit for SVD1 data (exp. 7 - 27) or the 1st CDC hit for SVD2 data (from exp. 31). (Belle only, originally stored in mdst_trk_fit.)
396
397)DOC","cm");
398
399 REGISTER_VARIABLE("BelleLastCDCHitX", BelleLastCDCHitX, R"DOC(
400[Legacy] Returns x component of end point of the track near the last CDC hit. (Belle only, originally stored in mdst_trk_fit.)
401
402)DOC","cm");
403
404 REGISTER_VARIABLE("BelleLastCDCHitY", BelleLastCDCHitY, R"DOC(
405[Legacy] Returns y component of end point of the track near the last CDC hit. (Belle only, originally stored in mdst_trk_fit.)
406
407)DOC","cm");
408
409 REGISTER_VARIABLE("BelleLastCDCHitZ", BelleLastCDCHitZ, R"DOC(
410[Legacy] Returns z component of end point of the track near the last CDC hit. (Belle only, originally stored in mdst_trk_fit.)
411
412)DOC","cm");
413
414 REGISTER_VARIABLE("BellePi0SigM", BellePi0InvariantMassSignificance, R"DOC(
415[Legacy] Returns the significance of the :math:`\pi^0` mass used in the FEI for B2BII.
416The significance is calculated as the difference between the reconstructed and the nominal mass divided by the mass uncertainty:
417
418.. math::
419 \frac{m_{\gamma\gamma} - m_{\pi^0}^\textrm{PDG}}{\sigma_{m_{\gamma\gamma}}}
420
421Since the :math:`\pi^0`'s covariance matrix for B2BII is empty, the latter is calculated using the photon daughters' covariance matrices.
422 )DOC");
423
424 REGISTER_VARIABLE("BelleTof", BelleTof, R"DOC(
425[Legacy] Returns the time of flight of a track. (Belle only).
426
427)DOC", "ns");
428
429 REGISTER_VARIABLE("BelleTofQuality", BelleTofQuality, R"DOC(
430[Legacy] Returns the quality flag of the time of flight of a track. Original description from the panther table: 0 if consistency between z of hit by charge Q and corrected times, 1 if zhit from Q NOT consistent with zhit from and correct times. (Belle only).
431)DOC");
432
433 REGISTER_VARIABLE("BelleTofSigma", BelleTofSigma, R"DOC(
434[Legacy] Returns the expected resolution on the time of flight of a track. (Belle only).
435
436)DOC", "ns");
437
438 REGISTER_VARIABLE("BellePathLength", BellePathLength, R"DOC(
439[Legacy] Returns the track path length. This is defined from the closest point to the z-axis up to TOF counter. (Belle only).
440
441)DOC", "cm");
442
443 REGISTER_VARIABLE("BelleTofMass", BelleTofMass, R"DOC(
444[Legacy] Returns the TOF mass calculated from the time of flight and path length. (Belle only).
445)DOC", "GeV/:math:`\\text{c}^2`");
446
447 REGISTER_VARIABLE("BelledEdx", BelledEdx, R"DOC(
448[Legacy] Returns the dE/dx measured in the CDC. (Belle only).
449
450)DOC", "keV/cm");
451
452 REGISTER_VARIABLE("BelledEdxQuality", BelledEdxQuality, R"DOC(
453[Legacy] Returns the quality flag of the dE/dx measured in the CDC. Sadly no information about the code meaning is given in the original panther tables. (Belle only).
454)DOC");
455
456 REGISTER_VARIABLE("BelleACCnPe", BelleACCnPe, R"DOC(
457[Legacy] Returns the number of photo-electrons associated to the track in the ACC. (Belle only).
458)DOC");
459
460 REGISTER_VARIABLE("BelleACCQuality", BelleACCQuality, R"DOC(
461[Legacy] Returns the ACC quality flag. Original definition in the panther tables: if 0 normal, if 1 the track is out of ACC acceptance. (Belle only).
462)DOC");
463
464
465 // this is defined in ECLVariables.{h,cc}
466 REGISTER_VARIABLE("clusterBelleQuality", eclClusterDeltaL, R"DOC(
467[Legacy] Returns ECL cluster's quality indicating a good cluster in GSIM (stored in deltaL of ECL cluster object).
468Belle analysis typically used clusters with quality == 0 in their :math:`E_{\text{extra ECL}}` (Belle only).
469)DOC");
470 }
472}
int getPDGCode() const
PDG code.
Definition: Const.h:473
static const ParticleType Lambda
Lambda particle.
Definition: Const.h:679
static const double speedOfLight
[cm/ns]
Definition: Const.h:695
static const ParticleType Kshort
K^0_S particle.
Definition: Const.h:677
static const double doubleNaN
quiet_NaN
Definition: Const.h:703
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.