11 #include <analysis/variables/FlightInfoVariables.h>
12 #include <framework/logging/Logger.h>
13 #include <analysis/VariableManager/Manager.h>
14 #include <framework/database/DBObjPtr.h>
15 #include <mdst/dbobjects/BeamSpot.h>
16 #include <framework/utilities/Conversion.h>
17 #include <boost/algorithm/string.hpp>
18 #include <mdst/dataobjects/MCParticle.h>
20 #include <TMatrixFSym.h>
32 bool hasRAVEBeamConstrainedProductionVertex(
const Particle* particle)
34 bool hasRAVEProdVertex =
true;
35 std::vector<std::string> directions = {
"x",
"y",
"z"};
36 for (
auto ielement : directions) {
37 std::string prodVertPositionElement = boost::str(boost::format(
"prodVert%s") % boost::to_upper_copy(ielement));
38 hasRAVEProdVertex &= particle -> hasExtraInfo(prodVertPositionElement);
39 for (
auto jelement : directions) {
40 std::string prodVertCovarianceElement = boost::str(boost::format(
"prodVertS%s%s") % ielement % jelement);
41 hasRAVEProdVertex &= particle -> hasExtraInfo(prodVertCovarianceElement);
44 return hasRAVEProdVertex;
48 inline double getFlightInfoBtw(
const Particle* particle,
const Particle* daughter,
double& outErr,
const std::string& mode,
49 const bool motherToGranddaughter =
false)
51 if (!particle || !daughter) {
52 outErr = std::numeric_limits<float>::quiet_NaN();
53 return std::numeric_limits<float>::quiet_NaN();
56 if (!(particle->getParticleSource() == Particle::EParticleSourceObject::c_Composite) ||
57 !(daughter->getParticleSource() == Particle::EParticleSourceObject::c_Composite)) {
59 if (!(particle->getParticleSource() == Particle::EParticleSourceObject::c_V0) ||
60 !(daughter->getParticleSource() == Particle::EParticleSourceObject::c_V0)) {
61 B2WARNING(
"Attempting to calculate flight " << mode <<
" for neither composite particle nor V0");
62 outErr = std::numeric_limits<float>::quiet_NaN();
63 return std::numeric_limits<float>::quiet_NaN();
66 if (!(mode ==
"distance") && !(mode ==
"time")) {
67 B2WARNING(
"FlightInfo helper function called with mode '" << mode
68 <<
"'. Only 'distance' and 'time' are available.");
69 outErr = std::numeric_limits<float>::quiet_NaN();
70 return std::numeric_limits<float>::quiet_NaN();
75 if (!motherToGranddaughter) {
76 if (mode ==
"distance" &&
77 daughter->hasExtraInfo(
"decayLength") &&
78 daughter->hasExtraInfo(
"decayLengthErr")) {
79 outErr = daughter -> getExtraInfo(
"decayLengthErr");
80 return daughter -> getExtraInfo(
"decayLength");
83 daughter->hasExtraInfo(
"lifeTime") &&
84 daughter->hasExtraInfo(
"lifeTimeErr")) {
85 outErr = daughter -> getExtraInfo(
"lifeTimeErr");
86 return daughter -> getExtraInfo(
"lifeTime");
91 double mumvtxX = particle->getX();
92 double mumvtxY = particle->getY();
93 double mumvtxZ = particle->getZ();
94 if (particle == daughter) {
95 if (hasRAVEBeamConstrainedProductionVertex(particle)) {
96 mumvtxX = particle->getExtraInfo(
"prodVertX");
97 mumvtxY = particle->getExtraInfo(
"prodVertY");
98 mumvtxZ = particle->getExtraInfo(
"prodVertZ");
101 static DBObjPtr<BeamSpot> beamSpotDB;
102 mumvtxX = (beamSpotDB->getIPPosition()).X();
103 mumvtxY = (beamSpotDB->getIPPosition()).Y();
104 mumvtxZ = (beamSpotDB->getIPPosition()).Z();
108 double vtxX = daughter->getX();
109 double vtxY = daughter->getY();
110 double vtxZ = daughter->getZ();
112 double p = daughter->getP();
113 double pX = daughter->getPx();
114 double pY = daughter->getPy();
115 double pZ = daughter->getPz();
122 double lX = vtxX - mumvtxX;
123 double lY = vtxY - mumvtxY;
124 double lZ = vtxZ - mumvtxZ;
127 double fD = lX * nX + lY * nY + lZ * nZ;
133 TMatrixFSym dauCov = daughter->getMomentumVertexErrorMatrix();
134 TMatrixFSym mumCov = particle->getVertexErrorMatrix();
135 if (particle == daughter) {
136 if (hasRAVEBeamConstrainedProductionVertex(particle)) {
137 std::vector<std::string> directions = {
"x",
"y",
"z"};
138 for (
unsigned int i = 0; i < directions.size(); i++) {
139 for (
unsigned int j = 0; j < directions.size(); j++) {
140 mumCov[i][j] = particle->getExtraInfo(boost::str(boost::format(
"prodVertS%s%s") % directions[i] % directions[j]));
144 static DBObjPtr<BeamSpot> beamSpotDB;
145 mumCov = beamSpotDB->getCovVertex();
152 for (
int i = 0; i < 10; i++)
153 for (
int j = 0; j < 10; j++)
155 Cov[i][j] = dauCov[i][j];
156 else if (i > 6 && j > 6)
157 Cov[i][j] = mumCov[i - 7][j - 7];
161 if (mode ==
"distance") {
162 TMatrixF deriv(10, 1);
163 deriv[0][0] = (lX - nX * fD) / p;
164 deriv[1][0] = (lY - nY * fD) / p;
165 deriv[2][0] = (lZ - nZ * fD) / p;
176 tmp.Mult(Cov, deriv);
178 TMatrixF result(1, 1);
179 result.Mult(deriv.T(), tmp);
181 outErr = sqrt(result[0][0]);
184 if (mode ==
"time") {
185 TMatrixF deriv(10, 1);
199 tmp.Mult(Cov, deriv);
201 TMatrixF result(1, 1);
202 result.Mult(deriv.T(), tmp);
203 outErr = sqrt(result[0][0]);
206 outErr = std::numeric_limits<float>::quiet_NaN();
207 return std::numeric_limits<float>::quiet_NaN();
211 inline double getMCFlightInfoBtw(
const MCParticle* mcparticle,
const std::string& mode)
214 if (mcparticle ==
nullptr)
215 return std::numeric_limits<float>::quiet_NaN();
218 if (mode ==
"distance") {
219 TVector3 deltaVtx = mcparticle->getDecayVertex() - mcparticle->getProductionVertex();
220 double distance = deltaVtx.Mag();
222 B2WARNING(
"Negative true flight distance, it's forbidden -> something went wrong.");
227 if (mode ==
"time") {
228 double lifetime = mcparticle->getLifetime();
229 double mass = mcparticle->getMass();
230 double time = std::numeric_limits<float>::quiet_NaN();
232 B2WARNING(
"you are asking for the proper time of a massless particle which is not allowed, returning -99.");
234 double energy = mcparticle->getEnergy();
235 time = lifetime / energy * mass;
239 B2WARNING(
"Negative true proper time, it's forbidden -> something went wrong.");
244 B2WARNING(
"MCFlightInfo helper function called with mode '" << mode
245 <<
"'. Only 'distance' and 'time' are available.");
246 return std::numeric_limits<float>::quiet_NaN();
250 double flightDistance(
const Particle* part)
252 double flightDistanceError = std::numeric_limits<float>::quiet_NaN();
253 return getFlightInfoBtw(part, part, flightDistanceError,
"distance");
256 double flightTime(
const Particle* part)
258 double flightTimeError = std::numeric_limits<float>::quiet_NaN();
259 return getFlightInfoBtw(part, part, flightTimeError,
"time");
262 double flightDistanceErr(
const Particle* part)
264 double flightDistanceError = std::numeric_limits<float>::quiet_NaN();
265 getFlightInfoBtw(part, part, flightDistanceError,
"distance");
266 return flightDistanceError;
269 double flightTimeErr(
const Particle* part)
271 double flightTimeError = std::numeric_limits<float>::quiet_NaN();
272 getFlightInfoBtw(part, part, flightTimeError,
"time");
273 return flightTimeError;
276 inline double getVertexDistance(
const Particle* particle,
const Particle* daughter,
double& vertexDistanceErr,
277 bool prodVertIsIP =
false)
279 if (!particle || !daughter) {
280 vertexDistanceErr = std::numeric_limits<float>::quiet_NaN();
281 return std::numeric_limits<float>::quiet_NaN();
285 double prodVtxX = particle->getX();
286 double prodVtxY = particle->getY();
287 double prodVtxZ = particle->getZ();
288 if (particle == daughter || prodVertIsIP) {
289 if (particle->hasExtraInfo(
"prodVertX")) prodVtxX = particle->getExtraInfo(
"prodVertX");
290 if (particle->hasExtraInfo(
"prodVertY")) prodVtxY = particle->getExtraInfo(
"prodVertY");
291 if (particle->hasExtraInfo(
"prodVertZ")) prodVtxZ = particle->getExtraInfo(
"prodVertZ");
295 double vtxX = daughter->getX();
296 double vtxY = daughter->getY();
297 double vtxZ = daughter->getZ();
300 double lX = vtxX - prodVtxX;
301 double lY = vtxY - prodVtxY;
302 double lZ = vtxZ - prodVtxZ;
305 double lD = sqrt(lX * lX + lY * lY + lZ * lZ);
308 TMatrixFSym decCov = daughter->getVertexErrorMatrix();
309 TMatrixFSym prodCov = particle->getVertexErrorMatrix();
310 if (particle == daughter || prodVertIsIP) {
311 if (particle->hasExtraInfo(
"prodVertSxx")) prodCov[0][0] = particle->getExtraInfo(
"prodVertSxx");
312 if (particle->hasExtraInfo(
"prodVertSxy")) prodCov[0][1] = particle->getExtraInfo(
"prodVertSxy");
313 if (particle->hasExtraInfo(
"prodVertSxz")) prodCov[0][2] = particle->getExtraInfo(
"prodVertSxz");
314 if (particle->hasExtraInfo(
"prodVertSyx")) prodCov[1][0] = particle->getExtraInfo(
"prodVertSyx");
315 if (particle->hasExtraInfo(
"prodVertSyy")) prodCov[1][1] = particle->getExtraInfo(
"prodVertSyy");
316 if (particle->hasExtraInfo(
"prodVertSyz")) prodCov[1][2] = particle->getExtraInfo(
"prodVertSyz");
317 if (particle->hasExtraInfo(
"prodVertSzx")) prodCov[2][0] = particle->getExtraInfo(
"prodVertSzx");
318 if (particle->hasExtraInfo(
"prodVertSzy")) prodCov[2][1] = particle->getExtraInfo(
"prodVertSzy");
319 if (particle->hasExtraInfo(
"prodVertSzz")) prodCov[2][2] = particle->getExtraInfo(
"prodVertSzz");
326 for (
int i = 0; i < 6; i++)
327 for (
int j = 0; j < 6; j++)
329 Cov[i][j] = prodCov[i][j];
330 else if (i > 2 && j > 2)
331 Cov[i][j] = decCov[i - 3][j - 3];
335 TMatrixF deriv(6, 1);
336 deriv[0][0] = - lX / lD;
337 deriv[1][0] = - lY / lD;
338 deriv[2][0] = - lZ / lD;
339 deriv[3][0] = lX / lD;
340 deriv[4][0] = lY / lD;
341 deriv[5][0] = lZ / lD;
345 tmp.Mult(Cov, deriv);
347 TMatrixF result(1, 1);
348 result.Mult(deriv.T(), tmp);
350 vertexDistanceErr = sqrt(result[0][0]);
354 double vertexDistance(
const Particle* part)
356 double vertexDistanceError = std::numeric_limits<float>::quiet_NaN();
357 if (!part->hasExtraInfo(
"prodVertX") || !part->hasExtraInfo(
"prodVertY") || !part->hasExtraInfo(
"prodVertZ")) {
358 return std::numeric_limits<float>::quiet_NaN();
360 return getVertexDistance(part, part, vertexDistanceError);
363 double vertexDistanceErr(
const Particle* part)
365 double vertexDistanceError = std::numeric_limits<float>::quiet_NaN();
366 if (!part->hasExtraInfo(
"prodVertX") || !part->hasExtraInfo(
"prodVertY") || !part->hasExtraInfo(
"prodVertZ")) {
367 return std::numeric_limits<float>::quiet_NaN();
369 getVertexDistance(part, part, vertexDistanceError);
370 return vertexDistanceError;
373 double vertexDistanceSignificance(
const Particle* part)
375 double vertexDistanceError = std::numeric_limits<float>::quiet_NaN();
376 if (!part->hasExtraInfo(
"prodVertX") || !part->hasExtraInfo(
"prodVertY") || !part->hasExtraInfo(
"prodVertZ")) {
377 return std::numeric_limits<float>::quiet_NaN();
379 return getVertexDistance(part, part, vertexDistanceError) / vertexDistanceError;
384 int daughterNumber = -1;
385 int grandDaughterNumber = -1;
386 if (arguments.size() == 1 || arguments.size() == 2) {
388 daughterNumber = Belle2::convertString<int>(arguments[0]);
389 }
catch (std::invalid_argument&) {
390 B2WARNING(
"First argument of flightTimeOfDaughter function must be integer!");
394 if (arguments.size() == 2) {
396 grandDaughterNumber = Belle2::convertString<int>(arguments[1]);
397 }
catch (std::invalid_argument&) {
398 B2WARNING(
"Second argument of flightTimeOfDaughter function must be integer!");
402 if (daughterNumber > -1) {
403 auto func = [daughterNumber, grandDaughterNumber](
const Particle * particle) ->
double {
404 if (particle ==
nullptr)
405 return std::numeric_limits<float>::quiet_NaN();
406 if (daughterNumber >=
int(particle->getNDaughters()) && particle->getDaughter(daughterNumber))
407 return std::numeric_limits<float>::quiet_NaN();
408 const Particle* daughter = particle->getDaughter(daughterNumber);
409 double flightTimeErr = 0.0;
410 if (grandDaughterNumber > -1)
412 if (grandDaughterNumber < (
int)daughter->getNDaughters()) {
413 return getFlightInfoBtw(particle, daughter->getDaughter(grandDaughterNumber), flightTimeErr,
"time",
true);
416 return getFlightInfoBtw(particle, daughter, flightTimeErr,
"time");
418 return std::numeric_limits<float>::quiet_NaN();
428 int daughterNumber = -1;
429 int grandDaughterNumber = -1;
430 if (arguments.size() == 1 || arguments.size() == 2) {
432 daughterNumber = Belle2::convertString<int>(arguments[0]);
433 }
catch (std::invalid_argument&) {
434 B2WARNING(
"First argument of flightTimeOfDaughterErr function must be integer!");
438 if (arguments.size() == 2) {
440 grandDaughterNumber = Belle2::convertString<int>(arguments[1]);
441 }
catch (std::invalid_argument&) {
442 B2WARNING(
"Second argument of flightTimeOfDaughterErr function must be integer!");
446 if (daughterNumber > -1) {
447 auto func = [daughterNumber, grandDaughterNumber](
const Particle * particle) ->
double {
448 if (particle ==
nullptr)
449 return std::numeric_limits<float>::quiet_NaN();
450 if (daughterNumber >=
int(particle->getNDaughters()) && particle->getDaughter(daughterNumber))
451 return std::numeric_limits<float>::quiet_NaN();
452 const Particle* daughter = particle->getDaughter(daughterNumber);
453 double flightTimeErr = 0.0;
454 if (grandDaughterNumber > -1)
456 if (grandDaughterNumber < (
int)daughter->getNDaughters()) {
457 getFlightInfoBtw(particle, daughter->getDaughter(grandDaughterNumber), flightTimeErr,
"time",
true);
458 return flightTimeErr;
461 getFlightInfoBtw(particle, daughter, flightTimeErr,
"time");
462 return flightTimeErr;
464 return std::numeric_limits<float>::quiet_NaN();
473 int daughterNumber = -1;
474 int grandDaughterNumber = -1;
475 if (arguments.size() == 1 || arguments.size() == 2) {
477 daughterNumber = Belle2::convertString<int>(arguments[0]);
478 }
catch (std::invalid_argument&) {
479 B2WARNING(
"First argument of flightDistanceOfDaughter function must be integer!");
483 if (arguments.size() == 2) {
485 grandDaughterNumber = Belle2::convertString<int>(arguments[1]);
486 }
catch (std::invalid_argument&) {
487 B2WARNING(
"Second argument of flightDistanceOfDaughter function must be integer!");
491 if (daughterNumber > -1) {
492 auto func = [daughterNumber, grandDaughterNumber](
const Particle * particle) ->
double {
493 if (particle ==
nullptr)
494 return std::numeric_limits<float>::quiet_NaN();
495 if (daughterNumber >=
int(particle->getNDaughters()) && particle->getDaughter(daughterNumber))
496 return std::numeric_limits<float>::quiet_NaN();
497 const Particle* daughter = particle->getDaughter(daughterNumber);
498 double flightDistanceErr = 0.0;
499 if (grandDaughterNumber > -1)
501 if (grandDaughterNumber < (
int)daughter->getNDaughters()) {
502 return getFlightInfoBtw(particle, daughter->getDaughter(grandDaughterNumber), flightDistanceErr,
"distance",
true);
505 return getFlightInfoBtw(particle, daughter, flightDistanceErr,
"distance");
507 return std::numeric_limits<float>::quiet_NaN();
517 int daughterNumber = -1;
518 int grandDaughterNumber = -1;
519 if (arguments.size() == 1 || arguments.size() == 2) {
521 daughterNumber = Belle2::convertString<int>(arguments[0]);
522 }
catch (std::invalid_argument&) {
523 B2WARNING(
"First argument of flightDistanceOfDaughterErr function must be integer!");
527 if (arguments.size() == 2) {
529 grandDaughterNumber = Belle2::convertString<int>(arguments[1]);
530 }
catch (std::invalid_argument&) {
531 B2WARNING(
"Second argument of flightDistanceOfDaughterErr function must be integer!");
535 if (daughterNumber > -1) {
536 auto func = [daughterNumber, grandDaughterNumber](
const Particle * particle) ->
double {
537 if (particle ==
nullptr)
538 return std::numeric_limits<float>::quiet_NaN();
539 if (daughterNumber >=
int(particle->getNDaughters()) && particle->getDaughter(daughterNumber))
540 return std::numeric_limits<float>::quiet_NaN();
541 const Particle* daughter = particle->getDaughter(daughterNumber);
542 double flightDistanceErr = 0.0;
543 if (grandDaughterNumber > -1)
545 if (grandDaughterNumber < (
int)daughter->getNDaughters()) {
546 getFlightInfoBtw(particle, daughter->getDaughter(grandDaughterNumber), flightDistanceErr,
"distance",
true);
547 return flightDistanceErr;
550 getFlightInfoBtw(particle, daughter, flightDistanceErr,
"distance");
551 return flightDistanceErr;
553 return std::numeric_limits<float>::quiet_NaN();
563 int daughterNumber = -1;
564 bool prodVertIsIP =
true;
565 if (arguments.size() == 1 || arguments.size() == 2) {
567 daughterNumber = Belle2::convertString<int>(arguments[0]);
568 }
catch (std::invalid_argument&) {
569 B2WARNING(
"First argument of vertexDistanceOfDaughter function must be integer!");
573 if (arguments.size() == 2) {
574 prodVertIsIP =
false;
576 if (daughterNumber > -1) {
577 auto func = [daughterNumber, prodVertIsIP](
const Particle * particle) ->
double {
578 if (particle ==
nullptr)
579 return std::numeric_limits<float>::quiet_NaN();
580 if (daughterNumber >=
int(particle->getNDaughters()) && particle->getDaughter(daughterNumber))
581 return std::numeric_limits<float>::quiet_NaN();
582 const Particle* daughter = particle->getDaughter(daughterNumber);
583 double vertexDistanceErr = std::numeric_limits<float>::quiet_NaN();
584 return getVertexDistance(particle, daughter, vertexDistanceErr, prodVertIsIP);
594 int daughterNumber = -1;
595 bool prodVertIsIP =
true;
596 if (arguments.size() == 1 || arguments.size() == 2) {
598 daughterNumber = Belle2::convertString<int>(arguments[0]);
599 }
catch (std::invalid_argument&) {
600 B2WARNING(
"First argument of vertexDistanceOfDaughterErr function must be integer!");
604 if (arguments.size() == 2) {
605 prodVertIsIP =
false;
607 if (daughterNumber > -1) {
608 auto func = [daughterNumber, prodVertIsIP](
const Particle * particle) ->
double {
609 if (particle ==
nullptr)
610 return std::numeric_limits<float>::quiet_NaN();
611 if (daughterNumber >=
int(particle->getNDaughters()) && particle->getDaughter(daughterNumber))
612 return std::numeric_limits<float>::quiet_NaN();
613 const Particle* daughter = particle->getDaughter(daughterNumber);
614 double vertexDistanceErr = std::numeric_limits<float>::quiet_NaN();
615 getVertexDistance(particle, daughter, vertexDistanceErr, prodVertIsIP);
616 return vertexDistanceErr;
624 Manager::FunctionPtr vertexDistanceOfDaughterSignificance(
const std::vector<std::string>& arguments)
626 int daughterNumber = -1;
627 bool prodVertIsIP =
true;
628 if (arguments.size() == 1 || arguments.size() == 2) {
630 daughterNumber = Belle2::convertString<int>(arguments[0]);
631 }
catch (std::invalid_argument&) {
632 B2WARNING(
"First argument of vertexDistanceOfDaughterSignificance function must be integer!");
636 if (arguments.size() == 2) {
637 prodVertIsIP =
false;
639 if (daughterNumber > -1) {
640 auto func = [daughterNumber, prodVertIsIP](
const Particle * particle) ->
double {
641 if (particle ==
nullptr)
642 return std::numeric_limits<float>::quiet_NaN();
643 if (daughterNumber >=
int(particle->getNDaughters()) && particle->getDaughter(daughterNumber))
644 return std::numeric_limits<float>::quiet_NaN();
645 const Particle* daughter = particle->getDaughter(daughterNumber);
646 double vertexDistanceErr = 0.0;
647 return getVertexDistance(particle, daughter, vertexDistanceErr, prodVertIsIP) / vertexDistanceErr;
656 double mcFlightDistance(
const Particle* particle)
658 if (particle ==
nullptr)
659 return std::numeric_limits<float>::quiet_NaN();
661 const MCParticle* mcparticle = particle->getRelatedTo<MCParticle>();
663 if (mcparticle ==
nullptr)
664 return std::numeric_limits<float>::quiet_NaN();
666 return getMCFlightInfoBtw(mcparticle,
"distance");
669 double mcFlightTime(
const Particle* particle)
671 if (particle ==
nullptr)
672 return std::numeric_limits<float>::quiet_NaN();
674 const MCParticle* mcparticle = particle->getRelatedTo<MCParticle>();
676 if (mcparticle ==
nullptr)
677 return std::numeric_limits<float>::quiet_NaN();
680 return getMCFlightInfoBtw(mcparticle,
"time");
685 int daughterNumber = -1;
686 int grandDaughterNumber = -1;
687 if (arguments.size() == 1 || arguments.size() == 2) {
689 daughterNumber = Belle2::convertString<int>(arguments[0]);
690 }
catch (std::invalid_argument&) {
691 B2WARNING(
"First argument of mcFlightDistanceOfDaughter function must be integer!");
695 if (arguments.size() == 2) {
697 grandDaughterNumber = Belle2::convertString<int>(arguments[1]);
698 }
catch (std::invalid_argument&) {
699 B2WARNING(
"Second argument of mcFlightDistanceOfDaughter function must be integer!");
703 if (daughterNumber > -1) {
704 auto func = [daughterNumber, grandDaughterNumber](
const Particle * particle) ->
double {
705 if (particle ==
nullptr)
706 return std::numeric_limits<float>::quiet_NaN();
707 if (daughterNumber >=
int(particle->getNDaughters()) || !particle->getDaughter(daughterNumber))
708 return std::numeric_limits<float>::quiet_NaN();
709 const Particle* daughterReco = particle->getDaughter(daughterNumber);
711 const MCParticle* daughter = daughterReco->getRelatedTo<MCParticle>();
713 double flightDistanceMC = std::numeric_limits<float>::quiet_NaN();
714 if (grandDaughterNumber > -1 && grandDaughterNumber < (
int)daughterReco->getNDaughters())
719 if (gdaughter !=
nullptr)
720 flightDistanceMC = getMCFlightInfoBtw(gdaughter,
"distance");
723 if (daughter !=
nullptr)
724 flightDistanceMC = getMCFlightInfoBtw(daughter,
"distance");
726 return flightDistanceMC;
730 B2WARNING(
"Incorrect parameters of mcFlightDistanceOfDaughter!");
736 int daughterNumber = -1;
737 int grandDaughterNumber = -1;
738 if (arguments.size() == 1 || arguments.size() == 2) {
740 daughterNumber = Belle2::convertString<int>(arguments[0]);
741 }
catch (std::invalid_argument&) {
742 B2WARNING(
"First argument of flightTimeOfDaughter function must be integer!");
746 if (arguments.size() == 2) {
748 grandDaughterNumber = Belle2::convertString<int>(arguments[1]);
749 }
catch (std::invalid_argument&) {
750 B2WARNING(
"Second argument of mcFlightTimeOfDaughter function must be integer!");
754 if (daughterNumber > -1) {
755 auto func = [daughterNumber, grandDaughterNumber](
const Particle * particle) ->
double {
756 if (particle ==
nullptr)
757 return std::numeric_limits<float>::quiet_NaN();
758 if (daughterNumber >=
int(particle->getNDaughters()) || !particle->getDaughter(daughterNumber))
759 return std::numeric_limits<float>::quiet_NaN();
760 const Particle* daughterReco = particle->getDaughter(daughterNumber);
762 const MCParticle* daughter = daughterReco->getRelatedTo<MCParticle>();
765 double flightTimeMC = std::numeric_limits<float>::quiet_NaN();
766 if (grandDaughterNumber > -1 && grandDaughterNumber < (
int)daughterReco->getNDaughters())
769 if (gdaughter !=
nullptr)
770 flightTimeMC = getMCFlightInfoBtw(gdaughter,
"time");
772 if (daughter !=
nullptr)
773 flightTimeMC = getMCFlightInfoBtw(daughter,
"time");
779 B2WARNING(
"Incorrect parameters of mcFlightTimeOfDaughter!");
784 VARIABLE_GROUP(
"Flight Information");
785 REGISTER_VARIABLE(
"flightTime", flightTime,
786 "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.");
787 REGISTER_VARIABLE(
"flightDistance", flightDistance,
788 "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.");
789 REGISTER_VARIABLE(
"flightTimeErr", flightTimeErr,
790 "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.");
791 REGISTER_VARIABLE(
"flightDistanceErr", flightDistanceErr,
792 "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.");
794 REGISTER_VARIABLE(
"flightTimeOfDaughter(daughterN, gdaughterN = -1)", flightTimeOfDaughter,
795 "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).");
796 REGISTER_VARIABLE(
"flightTimeOfDaughterErr(daughterN, gdaughterN = -1)", flightTimeOfDaughterErr,
797 "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).");
798 REGISTER_VARIABLE(
"flightDistanceOfDaughter(daughterN, gdaughterN = -1)", flightDistanceOfDaughter,
799 "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).");
800 REGISTER_VARIABLE(
"flightDistanceOfDaughterErr(daughterN, gdaughterN = -1)", flightDistanceOfDaughterErr,
801 "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).");
803 REGISTER_VARIABLE(
"mcFlightDistance", mcFlightDistance,
804 "Returns the MC flight distance of the particle");
805 REGISTER_VARIABLE(
"mcFlightTime", mcFlightTime,
806 "Returns the MC flight time of the particle");
807 REGISTER_VARIABLE(
"mcFlightDistanceOfDaughter(daughterN, gdaughterN = -1)", mcFlightDistanceOfDaughter,
808 "Returns the MC flight distance between mother and daughter particle using generated info");
809 REGISTER_VARIABLE(
"mcFlightTimeOfDaughter(daughterN, gdaughterN = -1)", mcFlightTimeOfDaughter,
810 "Returns the MC flight time between mother and daughter particle using generated info");
812 REGISTER_VARIABLE(
"vertexDistance", vertexDistance,
813 "Returns the distance between the production and decay vertex of a particle. Returns NaN if particle has no production or decay vertex.");
814 REGISTER_VARIABLE(
"vertexDistanceErr", vertexDistanceErr,
815 "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.");
816 REGISTER_VARIABLE(
"vertexDistanceSignificance", vertexDistanceSignificance,
817 "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.");
818 REGISTER_VARIABLE(
"vertexDistanceOfDaughter(daughterN, option = '')", vertexDistanceOfDaughter,
819 "If any second argument is provided it returns the distance between the decay vertices of the particle and of its daughter with index daughterN.\n"
820 "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"
821 "Returns NaN in case anything goes wrong.");
822 REGISTER_VARIABLE(
"vertexDistanceOfDaughterErr(daughterN, option = '')", vertexDistanceOfDaughterErr,
823 "If any second argument is provided it returns the uncertainty on the distance between the decay vertices of the particle and of its daughter with index daughterN.\n"
824 "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"
825 "Returns NaN in case anything goes wrong.");
826 REGISTER_VARIABLE(
"vertexDistanceOfDaughterSignificance(daughterN, option = '')", vertexDistanceOfDaughterSignificance,
827 "If any second argument is provided 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"
828 "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.");