Belle II Software development
FlightInfoVariables.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/FlightInfoVariables.h>
11
12// include VariableManager
13#include <analysis/VariableManager/Manager.h>
14
15#include <framework/database/DBObjPtr.h>
16#include <framework/logging/Logger.h>
17
18#include <analysis/dataobjects/Particle.h>
19#include <mdst/dataobjects/MCParticle.h>
20#include <mdst/dbobjects/BeamSpot.h>
21
22#include <TMatrixF.h>
23
24#include <boost/algorithm/string.hpp>
25
26namespace Belle2 {
31
32 namespace Variable {
33
34 //Function to check if a beam constrained rave fit has been performed
35 bool hasRAVEBeamConstrainedProductionVertex(const Particle* particle)
36 {
37 bool hasRAVEProdVertex = true;
38 std::vector<std::string> directions = {"x", "y", "z"};
39 for (auto ielement : directions) {
40 std::string prodVertPositionElement = boost::str(boost::format("prodVert%s") % boost::to_upper_copy(ielement));
41 hasRAVEProdVertex &= particle -> hasExtraInfo(prodVertPositionElement);
42 for (auto jelement : directions) {
43 std::string prodVertCovarianceElement = boost::str(boost::format("prodVertS%s%s") % ielement % jelement);
44 hasRAVEProdVertex &= particle -> hasExtraInfo(prodVertCovarianceElement);
45 }
46 }
47 return hasRAVEProdVertex;
48 }
49
50 // Helper function for flight distance and its uncertainty (provided as it is)
51 inline double getFlightInfoBtw(const Particle* particle, const Particle* daughter, double& outErr, const std::string& mode,
52 const bool motherToGranddaughter = false)
53 {
54 if (!particle || !daughter) {
55 outErr = Const::doubleNaN;
56 return Const::doubleNaN;
57 }
58 // check if the particle source is a composite particle or a V0
59 if ((particle->getParticleSource() != Particle::EParticleSourceObject::c_Composite and
60 particle->getParticleSource() != Particle::EParticleSourceObject::c_V0) or
61 (daughter->getParticleSource() != Particle::EParticleSourceObject::c_Composite and
62 daughter->getParticleSource() != Particle::EParticleSourceObject::c_V0)) {
63 B2WARNING("Attempting to calculate flight " << mode << " for neither composite particle nor V0");
64 outErr = Const::doubleNaN;
65 return Const::doubleNaN;
66 }
67 if (!(mode == "distance") && !(mode == "time")) {
68 B2WARNING("FlightInfo helper function called with mode '" << mode
69 << "'. Only 'distance' and 'time' are available.");
70 outErr = Const::doubleNaN;
71 return Const::doubleNaN;
72 }
73 // get TreeFitter values if they exist.
74 // Bypass this in case the variables are requested for the granddaughter with respect to the mother as
75 // TreeFitter will return the values of the granddaughter with respect to the daughter
76 if (!motherToGranddaughter) {
77 if (mode == "distance" &&
78 daughter->hasExtraInfo("decayLength") &&
79 daughter->hasExtraInfo("decayLengthErr")) {
80 outErr = daughter -> getExtraInfo("decayLengthErr");
81 return daughter -> getExtraInfo("decayLength");
82 }
83 if (mode == "time" &&
84 daughter->hasExtraInfo("lifeTime") &&
85 daughter->hasExtraInfo("lifeTimeErr")) {
86 outErr = daughter -> getExtraInfo("lifeTimeErr");
87 return daughter -> getExtraInfo("lifeTime");
88 }
89 }
90
91
92 double mumvtxX = particle->getX();
93 double mumvtxY = particle->getY();
94 double mumvtxZ = particle->getZ();
95 if (particle == daughter) {
96 if (hasRAVEBeamConstrainedProductionVertex(particle)) {
97 mumvtxX = particle->getExtraInfo("prodVertX");
98 mumvtxY = particle->getExtraInfo("prodVertY");
99 mumvtxZ = particle->getExtraInfo("prodVertZ");
100 } else {
101 //if no production vertex assume the particle originated at the ip
102 static DBObjPtr<BeamSpot> beamSpotDB;
103 if (beamSpotDB.isValid()) {
104 mumvtxX = (beamSpotDB->getIPPosition()).X();
105 mumvtxY = (beamSpotDB->getIPPosition()).Y();
106 mumvtxZ = (beamSpotDB->getIPPosition()).Z();
107 }
108 }
109 }
110 //daughter vertex
111 double vtxX = daughter->getX();
112 double vtxY = daughter->getY();
113 double vtxZ = daughter->getZ();
114 // daughter MOMENTUM
115 double p = daughter->getP();
116 double pX = daughter->getPx();
117 double pY = daughter->getPy();
118 double pZ = daughter->getPz();
119
120 //versor of the daughter momentum
121 double nX = pX / p;
122 double nY = pY / p;
123 double nZ = pZ / p;
124 //mother vertex
125 double lX = vtxX - mumvtxX;
126 double lY = vtxY - mumvtxY;
127 double lZ = vtxZ - mumvtxZ;
128
129 //flight distance
130 double fD = lX * nX + lY * nY + lZ * nZ;
131 //flight time
132 double fT = daughter->getPDGMass() / Const::speedOfLight * fD / p;
133
134 //covariance matrix of momentum and vertex for the Dz
135 //ORDER = px,py,pz,E,x,y,z
136 TMatrixFSym dauCov = daughter->getMomentumVertexErrorMatrix();
137 TMatrixFSym mumCov = particle->getVertexErrorMatrix(); //order: x,y,z
138 if (particle == daughter) {
139 if (hasRAVEBeamConstrainedProductionVertex(particle)) {
140 std::vector<std::string> directions = {"x", "y", "z"};
141 for (unsigned int i = 0; i < directions.size(); i++) {
142 for (unsigned int j = 0; j < directions.size(); j++) {
143 mumCov[i][j] = particle->getExtraInfo(boost::str(boost::format("prodVertS%s%s") % directions[i] % directions[j]));
144 }
145 }
146 } else {
147 static DBObjPtr<BeamSpot> beamSpotDB;
148 if (beamSpotDB.isValid())
149 mumCov = beamSpotDB->getCovVertex();
150 }
151 }
152 //compute total covariance matrix
153 //ORDER = px dau, py dau, pz dau, E dau, x dau, y dau, z dau, x mum, y mum, z mum
154
155 TMatrixFSym Cov(10);
156 for (int i = 0; i < 10; i++)
157 for (int j = 0; j < 10; j++)
158 if (i < 7 && j < 7)
159 Cov[i][j] = dauCov[i][j];
160 else if (i > 6 && j > 6)
161 Cov[i][j] = mumCov[i - 7][j - 7];
162 else
163 Cov[i][j] = 0;
164
165 if (mode == "distance") {
166 TMatrixF deriv(10, 1);
167 deriv[0][0] = (lX - nX * fD) / p; //px Daughter
168 deriv[1][0] = (lY - nY * fD) / p; //py Daughter
169 deriv[2][0] = (lZ - nZ * fD) / p; //pz Daughter
170 deriv[3][0] = 0; //E Daughter
171 deriv[4][0] = nX; //vtxX Daughter
172 deriv[5][0] = nY; //vtxY Daughter
173 deriv[6][0] = nZ; //vtxZ Daughter
174 deriv[7][0] = - nX; //vtxX Mother
175 deriv[8][0] = - nY; //vtxY Mother
176 deriv[9][0] = - nZ; //vtxZ Mother
177
178
179 TMatrixF tmp(10, 1);
180 tmp.Mult(Cov, deriv);
181
182 TMatrixF result(1, 1);
183 result.Mult(deriv.T(), tmp);
184
185 outErr = sqrt(result[0][0]);
186 return fD;
187 }
188 if (mode == "time") {
189 TMatrixF deriv(10, 1);
190 deriv[0][0] = (daughter->getPDGMass() / Const::speedOfLight * lX - 2 * pX * fT) / p / p; //px Daughter
191 deriv[1][0] = (daughter->getPDGMass() / Const::speedOfLight * lY - 2 * pY * fT) / p / p; //py Daughter
192 deriv[2][0] = (daughter->getPDGMass() / Const::speedOfLight * lZ - 2 * pZ * fT) / p / p; //pz Daughter
193 deriv[3][0] = 0; //E Daughter
194 deriv[4][0] = daughter->getPDGMass() / Const::speedOfLight * pX / p / p; //vtxX Daughter
195 deriv[5][0] = daughter->getPDGMass() / Const::speedOfLight * pY / p / p; //vtxY Daughter
196 deriv[6][0] = daughter->getPDGMass() / Const::speedOfLight * pZ / p / p; //vtxZ Daughter
197 deriv[7][0] = - daughter->getPDGMass() / Const::speedOfLight * pX / p / p; //vtxX Mother
198 deriv[8][0] = - daughter->getPDGMass() / Const::speedOfLight * pY / p / p; //vtxY Mother
199 deriv[9][0] = - daughter->getPDGMass() / Const::speedOfLight * pZ / p / p; //vtxZ Mother
200
201
202 TMatrixF tmp(10, 1);
203 tmp.Mult(Cov, deriv);
204
205 TMatrixF result(1, 1);
206 result.Mult(deriv.T(), tmp);
207 outErr = sqrt(result[0][0]);
208 return fT;
209 }
210 outErr = Const::doubleNaN;
211 return Const::doubleNaN;
212 }
213
214 // Helper function for MC flight time and distance
215 inline double getMCFlightInfoBtw(const MCParticle* mcparticle, const std::string& mode)
216 {
217
218 if (mcparticle == nullptr)
219 return Const::doubleNaN;
220
221
222 if (mode == "distance") {
223 ROOT::Math::XYZVector deltaVtx = mcparticle->getDecayVertex() - mcparticle->getProductionVertex();
224 double distance = deltaVtx.R();
225 if (distance < 0)
226 B2WARNING("Negative true flight distance, it's forbidden -> something went wrong.");
227
228 return distance;
229 }
230
231 if (mode == "time") {
232 double lifetime = mcparticle->getLifetime();
233 double mass = mcparticle->getMass();
234 double time = Const::doubleNaN;
235 if (mass == 0)
236 B2WARNING("you are asking for the proper time of a massless particle which is not allowed, returning -99.");
237 else {
238 double energy = mcparticle->getEnergy();
239 time = lifetime / energy * mass;
240 }
241
242 if (time < 0)
243 B2WARNING("Negative true proper time, it's forbidden -> something went wrong.");
244
245 return time;
246
247 }
248 B2WARNING("MCFlightInfo helper function called with mode '" << mode
249 << "'. Only 'distance' and 'time' are available.");
250 return Const::doubleNaN;
251
252 }
253
254 double flightDistance(const Particle* part)
255 {
256 double flightDistanceError = Const::doubleNaN;
257 return getFlightInfoBtw(part, part, flightDistanceError, "distance");
258 }
259
260 double flightTime(const Particle* part)
261 {
262 double flightTimeError = Const::doubleNaN;
263 return getFlightInfoBtw(part, part, flightTimeError, "time");
264 }
265
266 double flightDistanceErr(const Particle* part)
267 {
268 double flightDistanceError = Const::doubleNaN;
269 getFlightInfoBtw(part, part, flightDistanceError, "distance");
270 return flightDistanceError;
271 }
272
273 double flightTimeErr(const Particle* part)
274 {
275 double flightTimeError = Const::doubleNaN;
276 getFlightInfoBtw(part, part, flightTimeError, "time");
277 return flightTimeError;
278 }
279
280 inline double getVertexDistance(const Particle* particle, const Particle* daughter, double& vertexDistanceErr,
281 bool prodVertIsIP = false)
282 {
283 if (!particle || !daughter) {
284 vertexDistanceErr = Const::doubleNaN;
285 return Const::doubleNaN;
286 }
287
288 // production vertex
289 double prodVtxX = particle->getX();
290 double prodVtxY = particle->getY();
291 double prodVtxZ = particle->getZ();
292 if (particle == daughter || prodVertIsIP) {
293 if (particle->hasExtraInfo("prodVertX")) prodVtxX = particle->getExtraInfo("prodVertX");
294 if (particle->hasExtraInfo("prodVertY")) prodVtxY = particle->getExtraInfo("prodVertY");
295 if (particle->hasExtraInfo("prodVertZ")) prodVtxZ = particle->getExtraInfo("prodVertZ");
296 }
297
298 // decay vertex
299 double vtxX = daughter->getX();
300 double vtxY = daughter->getY();
301 double vtxZ = daughter->getZ();
302
303 // difference between vertices
304 double lX = vtxX - prodVtxX;
305 double lY = vtxY - prodVtxY;
306 double lZ = vtxZ - prodVtxZ;
307
308 // vertex distance
309 double lD = sqrt(lX * lX + lY * lY + lZ * lZ);
310
311 // covariance matrix of both vertices
312 TMatrixFSym decCov = daughter->getVertexErrorMatrix();
313 TMatrixFSym prodCov = particle->getVertexErrorMatrix();
314 if (particle == daughter || prodVertIsIP) {
315 if (particle->hasExtraInfo("prodVertSxx")) prodCov[0][0] = particle->getExtraInfo("prodVertSxx");
316 if (particle->hasExtraInfo("prodVertSxy")) prodCov[0][1] = particle->getExtraInfo("prodVertSxy");
317 if (particle->hasExtraInfo("prodVertSxz")) prodCov[0][2] = particle->getExtraInfo("prodVertSxz");
318 if (particle->hasExtraInfo("prodVertSyx")) prodCov[1][0] = particle->getExtraInfo("prodVertSyx");
319 if (particle->hasExtraInfo("prodVertSyy")) prodCov[1][1] = particle->getExtraInfo("prodVertSyy");
320 if (particle->hasExtraInfo("prodVertSyz")) prodCov[1][2] = particle->getExtraInfo("prodVertSyz");
321 if (particle->hasExtraInfo("prodVertSzx")) prodCov[2][0] = particle->getExtraInfo("prodVertSzx");
322 if (particle->hasExtraInfo("prodVertSzy")) prodCov[2][1] = particle->getExtraInfo("prodVertSzy");
323 if (particle->hasExtraInfo("prodVertSzz")) prodCov[2][2] = particle->getExtraInfo("prodVertSzz");
324 }
325
326 // compute total covariance matrix
327 // ORDER = prod x, prod y, prod z, decay x, decay y, decay z
328
329 TMatrixFSym Cov(6);
330 for (int i = 0; i < 6; i++)
331 for (int j = 0; j < 6; j++)
332 if (i < 3 && j < 3)
333 Cov[i][j] = prodCov[i][j];
334 else if (i > 2 && j > 2)
335 Cov[i][j] = decCov[i - 3][j - 3];
336 else
337 Cov[i][j] = 0;
338
339 TMatrixF deriv(6, 1);
340 deriv[0][0] = - lX / lD; // prodVtxX
341 deriv[1][0] = - lY / lD; // prodVtxY
342 deriv[2][0] = - lZ / lD; // prodVtxZ
343 deriv[3][0] = lX / lD; // vtxX
344 deriv[4][0] = lY / lD; // vtxY
345 deriv[5][0] = lZ / lD; // vtxZ
346
347
348 TMatrixF tmp(6, 1);
349 tmp.Mult(Cov, deriv);
350
351 TMatrixF result(1, 1);
352 result.Mult(deriv.T(), tmp);
353
354 vertexDistanceErr = sqrt(result[0][0]);
355 return lD;
356 }
357
358 double vertexDistance(const Particle* part)
359 {
360 double vertexDistanceError = Const::doubleNaN;
361 if (!part->hasExtraInfo("prodVertX") || !part->hasExtraInfo("prodVertY") || !part->hasExtraInfo("prodVertZ")) {
362 return Const::doubleNaN;
363 }
364 return getVertexDistance(part, part, vertexDistanceError);
365 }
366
367 double vertexDistanceErr(const Particle* part)
368 {
369 double vertexDistanceError = Const::doubleNaN;
370 if (!part->hasExtraInfo("prodVertX") || !part->hasExtraInfo("prodVertY") || !part->hasExtraInfo("prodVertZ")) {
371 return Const::doubleNaN;
372 }
373 getVertexDistance(part, part, vertexDistanceError);
374 return vertexDistanceError;
375 }
376
377 double vertexDistanceSignificance(const Particle* part)
378 {
379 double vertexDistanceError = Const::doubleNaN;
380 if (!part->hasExtraInfo("prodVertX") || !part->hasExtraInfo("prodVertY") || !part->hasExtraInfo("prodVertZ")) {
381 return Const::doubleNaN;
382 }
383 return getVertexDistance(part, part, vertexDistanceError) / vertexDistanceError;
384 }
385
386 double flightTimeOfDaughter(const Particle* particle, const std::vector<double>& daughters)
387 {
388 if (!particle)
389 return Const::doubleNaN; // Initial particle is NULL
390
391 long daughterNumber = -1;
392 if (daughters.size() > 0) {
393 daughterNumber = std::lround(daughters[0]);
394 } else {
395 B2ERROR("At least one integer, the index of the daughter, must be provided to flightTimeOfDaughter!");
396 return Const::doubleNaN;
397 }
398 int nDaughters = static_cast<int>(particle->getNDaughters());
399 if (daughterNumber >= nDaughters) {
400 B2ERROR("The daughter index provided to flightTimeOfDaughter is larger than the number of daughters of this particle!");
401 return Const::doubleNaN;
402 }
403
404 long grandDaughterNumber = -1;
405 if (daughters.size() == 2) {
406 grandDaughterNumber = std::lround(daughters[1]);
407 }
408
409 const Particle* daughter = particle->getDaughter(daughterNumber);
410 double flightTimeError;
411 if (grandDaughterNumber > -1) {
412 if (grandDaughterNumber < (int)daughter->getNDaughters()) {
413 return getFlightInfoBtw(particle, daughter->getDaughter(grandDaughterNumber), flightTimeError, "time", true);
414 } else {
415 B2ERROR("The granddaughter index provided to flightTimeOfDaughter is too large!");
416 return Const::doubleNaN;
417 }
418 } else {
419 return getFlightInfoBtw(particle, daughter, flightTimeError, "time");
420 }
421 }
422
423 // Flight time uncertainty
424 double flightTimeOfDaughterErr(const Particle* particle, const std::vector<double>& daughters)
425 {
426 if (!particle)
427 return Const::doubleNaN; // Initial particle is NULL
428
429 long daughterNumber = -1;
430 if (daughters.size() > 0) {
431 daughterNumber = std::lround(daughters[0]);
432 } else {
433 B2ERROR("At least one integer, the index of the daughter, must be provided to flightTimeOfDaughterErr!");
434 return Const::doubleNaN;
435 }
436 int nDaughters = static_cast<int>(particle->getNDaughters());
437 if (daughterNumber >= nDaughters) {
438 B2ERROR("The daughter index provided to flightTimeOfDaughterErr is larger than the number of daughters of this particle!");
439 return Const::doubleNaN;
440 }
441
442 long grandDaughterNumber = -1;
443 if (daughters.size() == 2) {
444 grandDaughterNumber = std::lround(daughters[1]);
445 }
446
447 const Particle* daughter = particle->getDaughter(daughterNumber);
448 double flightTimeError = Const::doubleNaN;;
449 if (grandDaughterNumber > -1) {
450 if (grandDaughterNumber < (int)daughter->getNDaughters()) {
451 getFlightInfoBtw(particle, daughter->getDaughter(grandDaughterNumber), flightTimeError, "time", true);
452 } else {
453 B2ERROR("The granddaughter index provided to flightTimeOfDaughterErr is too large!");
454 }
455 } else {
456 getFlightInfoBtw(particle, daughter, flightTimeError, "time");
457 }
458 return flightTimeError;
459 }
460
461 double flightDistanceOfDaughter(const Particle* particle, const std::vector<double>& daughters)
462 {
463 if (!particle)
464 return Const::doubleNaN; // Initial particle is NULL
465
466 long daughterNumber = -1;
467 if (daughters.size() > 0) {
468 daughterNumber = std::lround(daughters[0]);
469 } else {
470 B2ERROR("At least one integer, the index of the daughter, must be provided to flightDistanceOfDaughter!");
471 return Const::doubleNaN;
472 }
473 int nDaughters = static_cast<int>(particle->getNDaughters());
474 if (daughterNumber >= nDaughters) {
475 B2ERROR("The daughter index provided to flightDistanceOfDaughter is larger than the number of daughters of this particle!");
476 return Const::doubleNaN;
477 }
478
479 long grandDaughterNumber = -1;
480 if (daughters.size() == 2) {
481 grandDaughterNumber = std::lround(daughters[1]);
482 }
483
484 const Particle* daughter = particle->getDaughter(daughterNumber);
485 double flightDistanceError;
486 if (grandDaughterNumber > -1) {
487 if (grandDaughterNumber < (int)daughter->getNDaughters()) {
488 return getFlightInfoBtw(particle, daughter->getDaughter(grandDaughterNumber), flightDistanceError, "distance", true);
489 } else {
490 B2ERROR("The granddaughter index provided to flightDistanceOfDaughter is too large!");
491 return Const::doubleNaN;
492 }
493 } else {
494 return getFlightInfoBtw(particle, daughter, flightDistanceError, "distance");
495 }
496 }
497
498 // Flight distance uncertainty
499 double flightDistanceOfDaughterErr(const Particle* particle, const std::vector<double>& daughters)
500 {
501 if (!particle)
502 return Const::doubleNaN; // Initial particle is NULL
503
504 long daughterNumber = -1;
505 if (daughters.size() > 0) {
506 daughterNumber = std::lround(daughters[0]);
507 } else {
508 B2ERROR("At least one integer, the index of the daughter, must be provided to flightDistanceOfDaughterErr!");
509 return Const::doubleNaN;
510 }
511 int nDaughters = static_cast<int>(particle->getNDaughters());
512 if (daughterNumber >= nDaughters) {
513 B2ERROR("The daughter index provided to flightDistanceOfDaughterErr is larger than the number of daughters of this particle!");
514 return Const::doubleNaN;
515 }
516
517 long grandDaughterNumber = -1;
518 if (daughters.size() == 2) {
519 grandDaughterNumber = std::lround(daughters[1]);
520 }
521
522 const Particle* daughter = particle->getDaughter(daughterNumber);
523 double flightDistanceError = Const::doubleNaN;
524 if (grandDaughterNumber > -1) {
525 if (grandDaughterNumber < (int)daughter->getNDaughters()) {
526 getFlightInfoBtw(particle, daughter->getDaughter(grandDaughterNumber), flightDistanceError, "distance", true);
527 } else {
528 B2ERROR("The granddaughter index provided to flightDistanceOfDaughterErr is too large!");
529 }
530 } else {
531 getFlightInfoBtw(particle, daughter, flightDistanceError, "distance");
532 }
533 return flightDistanceError;
534 }
535
536 // Distance between mother and daughter vertices
537 double vertexDistanceOfDaughter(const Particle* particle, const std::vector<double>& arguments)
538 {
539 if (!particle)
540 return Const::doubleNaN; // Initial particle is NULL
541 long daughterNumber = -1;
542 if (arguments.size() > 0) {
543 daughterNumber = std::lround(arguments[0]);
544 } else {
545 B2ERROR("At least one integer, the index of the daughter, must be provided to vertexDistanceOfDaughter!");
546 return Const::doubleNaN;
547 }
548 int nDaughters = static_cast<int>(particle->getNDaughters());
549 if (daughterNumber >= nDaughters) {
550 B2ERROR("The daughter index provided to vertexDistanceOfDaughter is larger than the number of daughters of this particle!");
551 return Const::doubleNaN;
552 }
553
554 bool prodVertIsIP = true;
555 if (arguments.size() == 2) {
556 prodVertIsIP = false;
557 }
558
559 const Particle* daughter = particle->getDaughter(daughterNumber);
560 double vertexDistanceError;
561 return getVertexDistance(particle, daughter, vertexDistanceError, prodVertIsIP);
562 }
563
564 // Uncertainty on distance between mother and daughter vertices
565 double vertexDistanceOfDaughterErr(const Particle* particle, const std::vector<double>& arguments)
566 {
567 if (!particle)
568 return Const::doubleNaN; // Initial particle is NULL
569 long daughterNumber = -1;
570 if (arguments.size() > 0) {
571 daughterNumber = std::lround(arguments[0]);
572 } else {
573 B2ERROR("At least one integer, the index of the daughter, must be provided to vertexDistanceOfDaughterErr!");
574 return Const::doubleNaN;
575 }
576 int nDaughters = static_cast<int>(particle->getNDaughters());
577 if (daughterNumber >= nDaughters) {
578 B2ERROR("The daughter index provided to vertexDistanceOfDaughterErr is larger than the number of daughters of this particle!");
579 return Const::doubleNaN;
580 }
581
582 bool prodVertIsIP = true;
583 if (arguments.size() == 2) {
584 prodVertIsIP = false;
585 }
586
587 const Particle* daughter = particle->getDaughter(daughterNumber);
588 double vertexDistanceError;
589 getVertexDistance(particle, daughter, vertexDistanceError, prodVertIsIP);
590 return vertexDistanceError;
591 }
592
593 // Significance of distance between mother and daughter vertices
594 double vertexDistanceOfDaughterSignificance(const Particle* particle, const std::vector<double>& arguments)
595 {
596 if (!particle)
597 return Const::doubleNaN; // Initial particle is NULL
598 long daughterNumber = -1;
599 if (arguments.size() > 0) {
600 daughterNumber = std::lround(arguments[0]);
601 } else {
602 B2ERROR("At least one integer, the index of the daughter, must be provided to vertexDistanceOfDaughterSignificance!");
603 return Const::doubleNaN;
604 }
605 int nDaughters = static_cast<int>(particle->getNDaughters());
606 if (daughterNumber >= nDaughters) {
607 B2ERROR("The daughter index provided to vertexDistanceOfDaughterSignificance is larger than the number of daughters of this particle!");
608 return Const::doubleNaN;
609 }
610
611 bool prodVertIsIP = true;
612 if (arguments.size() == 2) {
613 prodVertIsIP = false;
614 }
615
616 const Particle* daughter = particle->getDaughter(daughterNumber);
617 double vertexDistanceError;
618 return getVertexDistance(particle, daughter, vertexDistanceError, prodVertIsIP) / vertexDistanceError;
619 }
620
621 // MC variables
622
623 double mcFlightDistance(const Particle* particle)
624 {
625 if (particle == nullptr)
626 return Const::doubleNaN; // Initial particle is NULL
627
628 const MCParticle* mcparticle = particle->getMCParticle();
629
630 if (mcparticle == nullptr)
631 return Const::doubleNaN; // Initial particle is NULL
632
633 return getMCFlightInfoBtw(mcparticle, "distance");
634 }
635
636 double mcFlightTime(const Particle* particle)
637 {
638 if (particle == nullptr)
639 return Const::doubleNaN; // Initial particle is NULL
640
641 const MCParticle* mcparticle = particle->getMCParticle();
642
643 if (mcparticle == nullptr)
644 return Const::doubleNaN; // Initial particle is NULL
645
646
647 return getMCFlightInfoBtw(mcparticle, "time");
648 }
649
650 double mcFlightDistanceOfDaughter(const Particle* particle, const std::vector<double>& daughters)
651 {
652 if (!particle)
653 return Const::doubleNaN; // Initial particle is NULL
654
655 long daughterNumber = -1;
656 if (daughters.size() > 0) {
657 daughterNumber = std::lround(daughters[0]);
658 } else {
659 B2ERROR("At least one integer, the index of the daughter, must be provided to mcFlightDistanceOfDaughter!");
660 return Const::doubleNaN;
661 }
662 int nDaughters = static_cast<int>(particle->getNDaughters());
663 if (daughterNumber >= nDaughters) {
664 B2ERROR("The daughter index provided to mcFlightDistanceOfDaughter is larger than the number of daughters of this particle!");
665 return Const::doubleNaN;
666 }
667
668 long grandDaughterNumber = -1;
669 if (daughters.size() == 2) {
670 grandDaughterNumber = std::lround(daughters[1]);
671 }
672
673 const Particle* daughterReco = particle->getDaughter(daughterNumber);
674 //get the MC DAUGHTER
675 const MCParticle* daughter = daughterReco->getMCParticle();
676
677 double flightDistanceMC;
678 if (grandDaughterNumber > -1 && grandDaughterNumber < (int)daughterReco->getNDaughters()) {
679 // Compute value between mother and granddaughter
680 const MCParticle* gdaughter = daughterReco->getDaughter(grandDaughterNumber)->getMCParticle();
681 flightDistanceMC = getMCFlightInfoBtw(gdaughter, "distance");
682 } else {
683 // Compute value between mother and daughter
684 flightDistanceMC = getMCFlightInfoBtw(daughter, "distance");
685 }
686 return flightDistanceMC;
687 }
688
689 double mcFlightTimeOfDaughter(const Particle* particle, const std::vector<double>& daughters)
690 {
691 if (!particle)
692 return Const::doubleNaN; // Initial particle is NULL
693
694 long daughterNumber = -1;
695 if (daughters.size() > 0) {
696 daughterNumber = std::lround(daughters[0]);
697 } else {
698 B2ERROR("At least one integer, the index of the daughter, must be provided to mcFlightTimeOfDaughter!");
699 return Const::doubleNaN;
700 }
701 int nDaughters = static_cast<int>(particle->getNDaughters());
702 if (daughterNumber >= nDaughters) {
703 B2ERROR("The daughter index provided to mcFlightTimeOfDaughter is larger than the number of daughters of this particle!");
704 return Const::doubleNaN;
705 }
706
707 long grandDaughterNumber = -1;
708 if (daughters.size() == 2) {
709 grandDaughterNumber = std::lround(daughters[1]);
710 }
711
712 const Particle* daughterReco = particle->getDaughter(daughterNumber);
713 //get the MC DAUGHTER
714 const MCParticle* daughter = daughterReco->getMCParticle();
715
716 double flightTimeMC;
717 if (grandDaughterNumber > -1 && grandDaughterNumber < (int)daughterReco->getNDaughters()) {
718 // Compute value between mother and granddaughter
719 const MCParticle* gdaughter = daughterReco->getDaughter(grandDaughterNumber)->getMCParticle();
720 flightTimeMC = getMCFlightInfoBtw(gdaughter, "time");
721 } else {
722 flightTimeMC = getMCFlightInfoBtw(daughter, "time");
723 }
724 return flightTimeMC;
725 }
726
727
728 VARIABLE_GROUP("Flight Information");
729 REGISTER_VARIABLE("flightTime", flightTime,
730 "Returns the flight time of particle. If a treeFit has been performed the flight time calculated by TreeFitter is returned. Otherwise if a beam constrained rave fit has been performed the production vertex set by rave and the decay vertex are used to calculate the flight time. If neither fit has been performed the i.p. is taken to be the production vertex.\n\n",
731 "ns");
732 REGISTER_VARIABLE("flightDistance", flightDistance,
733 "Returns the flight distance of particle. If a treeFit has been performed the flight distance calculated by TreeFitter is returned. Otherwise if a beam constrained rave fit has been performed the production vertex set by rave and the decay vertex are used to calculate the flight distance. If neither fit has been performed the i.p. is taken to be the production vertex.\n\n",
734 "cm");
735 REGISTER_VARIABLE("flightTimeErr", flightTimeErr,
736 "Returns the flight time error of particle. If a treeFit has been performed the flight time error calculated by TreeFitter is returned. Otherwise if a beam constrained rave fit has been performed the production vertex set by rave and the decay vertex are used to calculate the flight time error. If neither fit has been performed the i.p. is taken to be the production vertex.\n\n",
737 "ns");
738 REGISTER_VARIABLE("flightDistanceErr", flightDistanceErr,
739 "Returns the flight distance error of particle. If a treeFit has been performed the flight distance error calculated by TreeFitter is returned. Otherwise if a beam constrained rave fit has been performed the production vertex set by rave and the decay vertex are used to calculate the flight distance error. If neither fit has been performed the i.p. is taken to be the production vertex.\n\n",
740 "cm");
741 // Daughters
742 REGISTER_VARIABLE("flightTimeOfDaughter(daughterN, gdaughterN = -1)", flightTimeOfDaughter,
743 "Returns the flight time between mother and daughter particle with daughterN index. If a treeFit has been performed the value calculated by treeFitter is returned. Otherwise the value is calculated using the decay vertices of the mother and daughter particle. If a second index granddaughterM is given the value is calculated between the mother and the Mth grandaughter (Mth daughter of Nth daughter).\n\n",
744 "ns");
745 REGISTER_VARIABLE("flightTimeOfDaughterErr(daughterN, gdaughterN = -1)", flightTimeOfDaughterErr,
746 "Returns the flight time error between mother and daughter particle with daughterN index. If a treeFit has been performed the value calculated by treeFitter is returned. Otherwise the value is calculated using the decay vertices of the mother and daughter particle. If a second index granddaughterM is given the value is calculated between the mother and the Mth grandaughter (Mth daughter of Nth daughter).\n\n",
747 "ns");
748 REGISTER_VARIABLE("flightDistanceOfDaughter(daughterN, gdaughterN = -1)", flightDistanceOfDaughter,
749 "Returns the flight distance between mother and daughter particle with daughterN index. If a treeFit has been performed the value calculated by treeFitter is returned. Otherwise the value is calculated using the decay vertices of the mother and daughter particle. If a second index granddaughterM is given the value is calculated between the mother and the Mth grandaughter (Mth daughter of Nth daughter).\n\n",
750 "cm");
751 REGISTER_VARIABLE("flightDistanceOfDaughterErr(daughterN, gdaughterN = -1)", flightDistanceOfDaughterErr,
752 "Returns the flight distance error between mother and daughter particle with daughterN index. If a treeFit has been performed the value calculated by treeFitter is returned. Otherwise the value is calculated using the decay vertices of the mother and daughter particle. If a second index granddaughterM is given the value is calculated between the mother and the Mth grandaughter (Mth daughter of Nth daughter).\n\n",
753 "cm");
754 // MC Info
755 REGISTER_VARIABLE("mcFlightDistance", mcFlightDistance,
756 "Returns the MC flight distance of the particle\n\n", "cm");
757 REGISTER_VARIABLE("mcFlightTime", mcFlightTime,
758 "Returns the MC flight time of the particle\n\n", "ns");
759 REGISTER_VARIABLE("mcFlightDistanceOfDaughter(daughterN, gdaughterN = -1)", mcFlightDistanceOfDaughter,
760 "Returns the MC flight distance between mother and daughter particle using generated info\n\n", "cm");
761 REGISTER_VARIABLE("mcFlightTimeOfDaughter(daughterN, gdaughterN = -1)", mcFlightTimeOfDaughter,
762 "Returns the MC flight time between mother and daughter particle using generated info\n\n", "ns");
763 //Vertex Distance
764 REGISTER_VARIABLE("vertexDistance", vertexDistance,
765 "Returns the distance between the production and decay vertex of a particle. Returns NaN if particle has no production or decay vertex.\n\n",
766 "cm");
767 REGISTER_VARIABLE("vertexDistanceErr", vertexDistanceErr,
768 "Returns the uncertainty on the distance between the production and decay vertex of a particle. Returns NaN if particle has no production or decay vertex.\n\n",
769 "cm");
770 REGISTER_VARIABLE("vertexDistanceSignificance", vertexDistanceSignificance,
771 "Returns the distance between the production and decay vertex of a particle in units of the uncertainty on this value, i.e. the significance of the vertex separation.");
772 REGISTER_VARIABLE("vertexDistanceOfDaughter(daughterN[, option])", vertexDistanceOfDaughter,
773 "If any integer is provided as second argument it returns the distance between the decay vertices of the particle and of its daughter with index daughterN.\n"
774 "Otherwise, it is assumed that the particle has a production vertex (typically the IP) which is used to calculate the distance to the daughter's decay vertex.\n"
775 "Returns NaN in case anything goes wrong.\n\n", "cm");
776 REGISTER_VARIABLE("vertexDistanceOfDaughterErr(daughterN[, option])", vertexDistanceOfDaughterErr,
777 "If any integer is provided as second argument it returns the uncertainty on the distance between the decay vertices of the particle and of its daughter with index daughterN.\n"
778 "Otherwise, it is assumed that the particle has a production vertex (typically the IP) with a corresponding covariance matrix to calculate the uncertainty on the distance to the daughter's decay vertex.\n"
779 "Returns NaN in case anything goes wrong.\n\n", "cm");
780 REGISTER_VARIABLE("vertexDistanceOfDaughterSignificance(daughterN[, option)", vertexDistanceOfDaughterSignificance,
781 "If any integer is provided as second argument it returns the distance between the decay vertices of the particle and of its daughter with index daughterN in units of the uncertainty on this value.\n"
782 "Otherwise, it is assumed that the particle has a production vertex (typically the IP) with a corresponding covariance matrix and the significance of the separation to this vertex is calculated.");
783 }
785} // Belle2 namespace
static const double speedOfLight
[cm/ns]
Definition Const.h:695
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.