Belle II Software  release-05-01-25
BelleVariables.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2019 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Minakshi Nayak, Sam Cunliffe *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 #include <analysis/variables/BelleVariables.h>
12 
13 #include <analysis/dataobjects/Particle.h>
14 #include <analysis/variables/Variables.h>
15 #include <analysis/variables/VertexVariables.h>
16 #include <analysis/variables/ECLVariables.h>
17 #include <analysis/variables/TrackVariables.h>
18 #include <mdst/dataobjects/Track.h>
19 #include <mdst/dataobjects/TrackFitResult.h>
20 #include <analysis/variables/ParameterVariables.h>
21 #include <analysis/variables/VertexVariables.h>
22 
23 #include <framework/logging/Logger.h>
24 #include <framework/gearbox/Const.h>
25 
26 #include <framework/database/DBObjPtr.h>
27 #include <mdst/dbobjects/BeamSpot.h>
28 
29 #include <framework/datastore/StoreArray.h>
30 #include <b2bii/dataobjects/BelleTrkExtra.h>
31 
32 #include <TVectorF.h>
33 
34 #include <limits>
35 
36 namespace Belle2 {
41  namespace Variable {
42  double goodBelleKshort(const Particle* KS)
43  {
44  // check input
45  if (KS->getNDaughters() != 2) {
46  B2WARNING("goodBelleKshort is only defined for a particle with two daughters");
47  return 0.0;
48  }
49  const Particle* d0 = KS->getDaughter(0);
50  const Particle* d1 = KS->getDaughter(1);
51  if ((d0->getCharge() == 0) || (d1->getCharge() == 0)) {
52  B2WARNING("goodBelleKshort is only defined for a particle with charged daughters");
53  return 0.0;
54  }
55  if (abs(KS->getPDGCode()) != Const::Kshort.getPDGCode())
56  B2WARNING("goodBelleKshort is being applied to a candidate with PDG " << KS->getPDGCode());
57 
58  // If goodKs exists, return the value
59  if (KS->hasExtraInfo("goodKs")) {
60  return KS->getExtraInfo("goodKs");
61  }
62 
63  // Belle selection
64  double p = particleP(KS);
65  double fl = particleDRho(KS);
66  double dphi = acos(((particleDX(KS) * particlePx(KS)) + (particleDY(KS) * particlePy(KS))) / (fl * sqrt(particlePx(KS) * particlePx(
67  KS) + particlePy(KS) * particlePy(KS))));
68  // particleDRho returns track d0 relative to IP for tracks
69  double dr = std::min(abs(particleDRho(d0)), abs(particleDRho(d1)));
70  double zdist = v0DaughterZ0Diff(KS);
71 
72  bool low = p < 0.5 && abs(zdist) < 0.8 && dr > 0.05 && dphi < 0.3;
73  bool mid = p < 1.5 && p > 0.5 && abs(zdist) < 1.8 && dr > 0.03 && dphi < 0.1 && fl > .08;
74  bool high = p > 1.5 && abs(zdist) < 2.4 && dr > 0.02 && dphi < 0.03 && fl > .22;
75 
76  if (low || mid || high) {
77  return 1.0;
78  } else
79  return 0.0;
80  }
81 
82 
83  double goodBelleLambda(const Particle* Lambda)
84  {
85  if (Lambda->getNDaughters() != 2) {
86  B2WARNING("goodBelleLambda is only defined for a particle with two daughters");
87  return 0.;
88  }
89  const Particle* d0 = Lambda->getDaughter(0);
90  const Particle* d1 = Lambda->getDaughter(1);
91  if ((d0->getCharge() == 0) || (d1->getCharge() == 0)) {
92  B2WARNING("goodBelleLambda is only defined for a particle with charged daughters");
93  return 0.;
94  }
95  if (abs(Lambda->getPDGCode()) != Const::Lambda.getPDGCode()) {
96  B2WARNING("goodBelleLambda is being applied to a candidate with PDG " << Lambda->getPDGCode());
97  }
98 
99  if (Lambda->hasExtraInfo("goodLambda"))
100  return Lambda->getExtraInfo("goodLambda");
101 
102  double p = particleP(Lambda);
103  double dr = std::min(abs(particleDRho(d0)), abs(particleDRho(d1)));
104  double zdist = v0DaughterZ0Diff(Lambda);
105  double dphi = acos(cosAngleBetweenMomentumAndVertexVectorInXYPlane(Lambda));
106  // Flight distance of Lambda0 in xy plane
107  double fl = particleDRho(Lambda);
108 
109  // goodBelleLambda == 1 (optimized for proton PID > 0.6)
110  bool high1 = p >= 1.5 && abs(zdist) < 12.9 && dr > 0.008 && dphi < 0.09 && fl > 0.22;
111  bool mid1 = p >= 0.5 && p < 1.5 && abs(zdist) < 9.8 && dr > 0.01 && dphi < 0.18 && fl > 0.16;
112  bool low1 = p < 0.5 && abs(zdist) < 2.4 && dr > 0.027 && dphi < 1.2 && fl > 0.11;
113 
114  // goodBelleLambda == 2 (optimized without PID selection)
115  bool high2 = p >= 1.5 && abs(zdist) < 7.7 && dr > 0.018 && dphi < 0.07 && fl > 0.35;
116  bool mid2 = p >= 0.5 && p < 1.5 && abs(zdist) < 2.1 && dr > 0.033 && dphi < 0.10 && fl > 0.24;
117  bool low2 = p < 0.5 && abs(zdist) < 1.9 && dr > 0.059 && dphi < 0.6 && fl > 0.17;
118 
119  if (low2 || mid2 || high2) {
120  return 2.0;
121  } else if (low1 || mid1 || high1) {
122  return 1.0;
123  } else {
124  return 0.0;
125  }
126  }
127 
128 
129  bool isGoodBelleGamma(int region, double energy)
130  {
131  bool goodGammaRegion1, goodGammaRegion2, goodGammaRegion3;
132  goodGammaRegion1 = region == 1 && energy > 0.100;
133  goodGammaRegion2 = region == 2 && energy > 0.050;
134  goodGammaRegion3 = region == 3 && energy > 0.150;
135 
136  return goodGammaRegion1 || goodGammaRegion2 || goodGammaRegion3;
137  }
138 
139  double goodBelleGamma(const Particle* particle)
140  {
141  double energy = eclClusterE(particle);
142  int region = eclClusterDetectionRegion(particle);
143 
144  return (double) isGoodBelleGamma(region, energy);
145  }
146 
147  BelleTrkExtra* getBelleTrkExtraInfoFromParticle(Particle const* particle)
148  {
149  const Track* track = particle->getTrack();
150  if (!track) {
151  return nullptr;
152  }
153  auto belleTrkExtra = track->getRelatedTo<BelleTrkExtra>();
154  if (!belleTrkExtra) {
155  return nullptr;
156  }
157  return belleTrkExtra;
158  }
159 
160  double BelleFirstCDCHitX(const Particle* particle)
161  {
162  auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
163  if (!belleTrkExtra) {
164  B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
165  return std::numeric_limits<double>::quiet_NaN();
166  }
167  return belleTrkExtra->getTrackFirstX();
168  }
169 
170  double BelleFirstCDCHitY(const Particle* particle)
171  {
172  auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
173  if (!belleTrkExtra) {
174  B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
175  return std::numeric_limits<double>::quiet_NaN();
176  }
177  return belleTrkExtra->getTrackFirstY();
178  }
179 
180  double BelleFirstCDCHitZ(const Particle* particle)
181  {
182  auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
183  if (!belleTrkExtra) {
184  B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
185  return std::numeric_limits<double>::quiet_NaN();
186  }
187  return belleTrkExtra->getTrackFirstZ();
188  }
189 
190  double BelleLastCDCHitX(const Particle* particle)
191  {
192  auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
193  if (!belleTrkExtra) {
194  B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
195  return std::numeric_limits<double>::quiet_NaN();
196  }
197  return belleTrkExtra->getTrackLastX();
198  }
199 
200  double BelleLastCDCHitY(const Particle* particle)
201  {
202  auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
203  if (!belleTrkExtra) {
204  B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
205  return std::numeric_limits<double>::quiet_NaN();
206  }
207  return belleTrkExtra->getTrackLastY();
208  }
209 
210  double BelleLastCDCHitZ(const Particle* particle)
211  {
212  auto belleTrkExtra = getBelleTrkExtraInfoFromParticle(particle);
213  if (!belleTrkExtra) {
214  B2WARNING("Cannot find BelleTrkExtra, did you forget to enable BelleTrkExtra during the conversion?");
215  return std::numeric_limits<double>::quiet_NaN();
216  }
217  return belleTrkExtra->getTrackLastZ();
218  }
219 
220  double BellePi0InvariantMassSignificance(const Particle* particle)
221  {
222  TMatrixFSym covarianceMatrix(Particle::c_DimMomentum);
223  for (auto daughter : particle->getDaughters()) {
224  covarianceMatrix += daughter->getMomentumErrorMatrix();
225  }
226 
227  TVectorF jacobian(Particle::c_DimMomentum);
228  jacobian[0] = -1.0 * particle->getPx() / particle->getMass();
229  jacobian[1] = -1.0 * particle->getPy() / particle->getMass();
230  jacobian[2] = -1.0 * particle->getPz() / particle->getMass();
231  jacobian[3] = 1.0 * particle->getEnergy() / particle->getMass();
232 
233  double massErrSquared = jacobian * (covarianceMatrix * jacobian);
234 
235  if (massErrSquared < 0.0)
236  return std::numeric_limits<double>::quiet_NaN();
237 
238  double invMass = particleInvariantMassFromDaughters(particle);
239  double nomMass = particle->getPDGMass();
240 
241  return (invMass - nomMass) / sqrt(massErrSquared);
242  }
243 
244  VARIABLE_GROUP("Belle Variables");
245 
246  REGISTER_VARIABLE("goodBelleKshort", goodBelleKshort, R"DOC(
247 [Legacy] GoodKs Returns 1.0 if a :math:`K_{S}^0\to\pi\pi` candidate passes the Belle algorithm:
248 a momentum-binned selection including requirements on impact parameter of, and
249 angle between the daughter pions as well as separation from the vertex and
250 flight distance in the transverse plane.
251 )DOC");
252 
253  REGISTER_VARIABLE("goodBelleLambda", goodBelleLambda, R"DOC(
254 [Legacy] Returns 2.0, 1.0, 0.0 as an indication of goodness of :math:`\Lambda^0` candidates,
255 based on:
256 
257  * The distance of the two daughter tracks at their interception at z axis,
258  * the minimum distance of the daughter tracks and the IP in xy plane,
259  * the difference of the azimuthal angle of the vertex vector and the momentum vector,
260  * and the flight distance of the Lambda0 candidates in xy plane.
261 
262 It reproduces the ``goodLambda()`` function in Belle.
263 
264 ``goodBelleLambda`` selection 1 (selected with: ``goodBelleLambda>0``) should be used with ``atcPIDBelle(4,2) > 0.6``,
265 and ``goodBelleLambda`` selecton 2 (``goodBelleLambda>1``) can be used without a proton PID cut.
266 The former cut is looser than the latter.".
267 
268 .. warning:: ``goodBelleLambda`` is not optimized or tested on Belle II data.
269 
270 See Also:
271  * `BN-684`_ Lambda selection at Belle. K F Chen et al.
272  * The ``FindLambda`` class can be found at ``/belle_legacy/findLambda/findLambda.h``
273 
274 .. _BN-684: https://belle.kek.jp/secured/belle_note/gn684/bn684.ps.gz
275 
276 )DOC");
277 
278  REGISTER_VARIABLE("goodBelleGamma", goodBelleGamma, R"DOC(
279 [Legacy] Returns 1.0 if photon candidate passes simple region dependent
280 energy selection for Belle data and MC (50/100/150 MeV).
281 )DOC");
282 
283  REGISTER_VARIABLE("BelleFirstCDCHitX", BelleFirstCDCHitX, R"DOC(
284 [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.)
285 )DOC");
286 
287  REGISTER_VARIABLE("BelleFirstCDCHitY", BelleFirstCDCHitY, R"DOC(
288 [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.)
289 )DOC");
290 
291  REGISTER_VARIABLE("BelleFirstCDCHitZ", BelleFirstCDCHitZ, R"DOC(
292 [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.)
293 )DOC");
294 
295  REGISTER_VARIABLE("BelleLastCDCHitX", BelleLastCDCHitX, R"DOC(
296 [Legacy] Returns x component of end point of the track near the last CDC hit. (Belle only, originally stored in mdst_trk_fit.)
297 )DOC");
298 
299  REGISTER_VARIABLE("BelleLastCDCHitY", BelleLastCDCHitY, R"DOC(
300 [Legacy] Returns y component of end point of the track near the last CDC hit. (Belle only, originally stored in mdst_trk_fit.)
301 )DOC");
302 
303  REGISTER_VARIABLE("BelleLastCDCHitZ", BelleLastCDCHitZ, R"DOC(
304 [Legacy] Returns z component of end point of the track near the last CDC hit. (Belle only, originally stored in mdst_trk_fit.)
305 )DOC");
306 
307  REGISTER_VARIABLE("BellePi0SigM", BellePi0InvariantMassSignificance, R"DOC(
308  [Legacy] Returns the significance of the pi0 mass used in the FEI for B2BII.
309  The significance is calculated as the difference between the reconstructed and the nominal mass divided by the mass uncertainty.
310  Since the pi0's covariance matrix for B2BII is empty, the latter is calculated using the photon daughters' covariance matrices.
311  )DOC");
312 
313  // this is defined in ECLVariables.{h,cc}
314  REGISTER_VARIABLE("clusterBelleQuality", eclClusterDeltaL, R"DOC(
315 [Legacy] Returns ECL cluster's quality indicating a good cluster in GSIM (stored in deltaL of ECL cluster object).
316 Belle analysis typically used clusters with quality == 0 in their :math:`E_{\text{extra ECL}}` (Belle only).
317 )DOC");
318  }
320 }
Belle2::Const::Kshort
static const ParticleType Kshort
K^0_S particle.
Definition: Const.h:550
Belle2::Const::ParticleType::getPDGCode
int getPDGCode() const
PDG code.
Definition: Const.h:349
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::Const::Lambda
static const ParticleType Lambda
Lambda particle.
Definition: Const.h:552