10#include <analysis/variables/PIDVariables.h>
12#include <analysis/dataobjects/Particle.h>
13#include <analysis/utility/ReferenceFrame.h>
14#include <mdst/dataobjects/PIDLikelihood.h>
17#include <framework/logging/Logger.h>
18#include <framework/utilities/Conversion.h>
19#include <framework/gearbox/Const.h>
22#include <analysis/utility/PIDCalibrationWeightUtil.h>
23#include <analysis/utility/PIDNeuralNetwork.h>
25#include <boost/algorithm/string.hpp>
44 Const::ChargedStable hypothesisConversion(
const int hypothesis)
66 for (std::string val : arguments) {
69 else if (val ==
"svd") result += Const::SVD;
70 else if (val ==
"cdc") result += Const::CDC;
71 else if (val ==
"top") result += Const::TOP;
72 else if (val ==
"arich") result += Const::ARICH;
73 else if (val ==
"ecl") result += Const::ECL;
74 else if (val ==
"klm") result += Const::KLM;
75 else B2ERROR(
"Unknown detector component: " << val);
84 for (std::string val : arguments) {
87 else if (val ==
"ecl") result += Const::ECL;
88 else B2ERROR(
"Invalid detector component: " << val <<
" for charged BDT.");
99 double particleID(
const Particle* p)
101 int pdg = abs(p->getPDGCode());
103 else if (pdg ==
Const::muon.getPDGCode())
return muonID(p);
104 else if (pdg ==
Const::pion.getPDGCode())
return pionID(p);
105 else if (pdg ==
Const::kaon.getPDGCode())
return kaonID(p);
106 else if (pdg ==
Const::proton.getPDGCode())
return protonID(p);
111 bool isPIDAvailable(
const Particle* part)
113 const auto* pid = part->getPIDLikelihood();
114 if (not pid)
return false;
115 return pid->isAvailable();
121 auto func = [detectorSet](
const Particle * part) ->
bool {
122 const auto* pid = part->getPIDLikelihood();
123 if (not pid)
return false;
124 return pid->isAvailable(detectorSet);
131 if (arguments.size() < 2) {
132 B2ERROR(
"Need at least two arguments to pidLogLikelihoodValueExpert");
137 pdgCode = Belle2::convertString<int>(arguments[0]);
138 }
catch (std::invalid_argument& e) {
139 B2ERROR(
"First argument of pidLogLikelihoodValueExpert must be a PDG code");
142 std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
145 auto hypType = Const::ChargedStable(abs(pdgCode));
147 auto func = [hypType, detectorSet](
const Particle * part) ->
double {
148 const PIDLikelihood* pid = part->getPIDLikelihood();
154 return pid->getLogL(hypType, detectorSet);
160 Manager::FunctionPtr pidDeltaLogLikelihoodValueExpert(
const std::vector<std::string>& arguments)
162 if (arguments.size() < 3) {
163 B2ERROR(
"Need at least three arguments to pidDeltaLogLikelihoodValueExpert");
166 int pdgCodeHyp, pdgCodeTest;
168 pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
169 }
catch (std::invalid_argument& e) {
170 B2ERROR(
"First argument of pidDeltaLogLikelihoodValueExpert must be a PDG code");
174 pdgCodeTest = Belle2::convertString<int>(arguments[1]);
175 }
catch (std::invalid_argument& e) {
176 B2ERROR(
"Second argument of pidDeltaLogLikelihoodValueExpert must be a PDG code");
180 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
182 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
183 auto testType = Const::ChargedStable(abs(pdgCodeTest));
185 auto func = [hypType, testType, detectorSet](
const Particle * part) ->
double {
186 const PIDLikelihood* pid = part->getPIDLikelihood();
191 return pid->getDeltaLogL(hypType, testType, detectorSet);
199 if (arguments.size() < 3) {
200 B2ERROR(
"Need at least three arguments to pidPairProbabilityExpert");
203 int pdgCodeHyp = 0, pdgCodeTest = 0;
205 pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
206 }
catch (std::invalid_argument& e) {
207 B2ERROR(
"First argument of pidPairProbabilityExpert must be PDG code");
211 pdgCodeTest = Belle2::convertString<int>(arguments[1]);
212 }
catch (std::invalid_argument& e) {
213 B2ERROR(
"Second argument of pidPairProbabilityExpert must be PDG code");
217 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
220 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
221 auto testType = Const::ChargedStable(abs(pdgCodeTest));
222 auto func = [hypType, testType, detectorSet](
const Particle * part) ->
double {
223 const PIDLikelihood* pid = part->getPIDLikelihood();
228 return pid->getProbability(hypType, testType, detectorSet);
236 if (arguments.size() < 2) {
237 B2ERROR(
"Need at least two arguments for pidProbabilityExpert");
242 pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
243 }
catch (std::invalid_argument& e) {
244 B2ERROR(
"First argument of pidProbabilityExpert must be PDG code");
248 std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
250 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
255 for (
double& i : frac) i = 1.0;
257 auto func = [hypType, frac, detectorSet](
const Particle * part) ->
double {
258 const PIDLikelihood* pid = part->getPIDLikelihood();
263 return pid->getProbability(hypType, frac, detectorSet);
271 if (arguments.size() < 2) {
272 B2ERROR(
"Need at least two arguments for pidLogarithmicProbabilityExpert");
277 pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
278 }
catch (std::invalid_argument& e) {
279 B2ERROR(
"First argument of pidLogarithmicProbabilityExpert must be PDG code");
283 std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
285 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
290 for (
double& i : frac) i = 1.0;
292 auto func = [hypType, frac, detectorSet](
const Particle * part) ->
double {
293 const auto* pid = part->getPIDLikelihood();
296 return pid->getLogarithmicProbability(hypType, frac, detectorSet);
304 if (arguments.size() < 1) {
305 B2ERROR(
"Need at least one argument to pidMissingProbabilityExpert");
309 std::vector<std::string> detectors(arguments.begin(), arguments.end());
312 auto func = [detectorSet](
const Particle * part) ->
double {
313 const PIDLikelihood* pid = part->getPIDLikelihood();
315 if (not pid->areAllAvailable(detectorSet))
return 1;
321 Manager::FunctionPtr pidWeightedLogLikelihoodValueExpert(
const std::vector<std::string>& arguments)
323 if (arguments.size() < 3) {
324 B2ERROR(
"Need at least three arguments to pidWeightedLogLikelihoodValueExpert");
327 std::string matrixName = arguments[0];
331 pdgCode = Belle2::convertString<int>(arguments[1]);
332 }
catch (std::invalid_argument& e) {
333 B2ERROR(
"Second argument of pidWeightedLogLikelihoodValueExpert must be a PDG code");
336 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
338 auto hypType = Const::ChargedStable(abs(pdgCode));
340 auto func = [hypType, detectorSet, matrixName](
const Particle * part) ->
double {
341 PIDCalibrationWeightUtil weightMatrix(matrixName);
342 const PIDLikelihood* pid = part->getPIDLikelihood();
349 auto mom = frame.getMomentum(part);
351 auto theta = mom.Theta();
356 if (detectorSet.contains(detector))
357 LogL += pid->getLogL(hypType, detector) * weightMatrix.getWeight(hypType.getPDGCode(), detector, p, theta);
367 if (arguments.size() < 3) {
368 B2ERROR(
"Need at least three arguments for pidWeightedProbabilityExpert");
371 std::string matrixName = arguments[0];
375 pdgCodeHyp = Belle2::convertString<int>(arguments[1]);
376 }
catch (std::invalid_argument& e) {
377 B2ERROR(
"Second argument of pidWeightedProbabilityExpert must be PDG code");
381 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
383 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
385 auto func = [hypType, detectorSet, matrixName](
const Particle * part) ->
double {
386 PIDCalibrationWeightUtil weightMatrix(matrixName);
387 const PIDLikelihood* pid = part->getPIDLikelihood();
393 auto mom = frame.getMomentum(part);
395 auto theta = mom.Theta();
402 const int index_pdg = pdgIter.getIndex();
406 if (detectorSet.contains(detector))
407 LogL[index_pdg] += pid->getLogL(pdgIter, detector) * weightMatrix.getWeight(pdgIter.getPDGCode(), detector, p, theta);
410 if (!hasMax || (LogL[index_pdg] > LogL_max)) {
411 LogL_max = LogL[index_pdg];
417 for (
auto LogL_i : LogL)
418 norm += exp(LogL_i - LogL_max);
421 return exp(LogL[hypType.getIndex()] - LogL_max) / norm;
431 if (arguments.size() == 0) {
432 B2ERROR(
"Need pdg code for pidNeuralNetworkValueExpert");
435 if (arguments.size() > 2) {
436 B2ERROR(
"pidNeuralNetworkValueExpert expects at most two arguments, i.e. the pdg code and the pidNeuralNetworkName");
441 pdgCode = abs(Belle2::convertString<int>(arguments[0]));
442 }
catch (std::invalid_argument& e) {
443 B2ERROR(
"First argument of pidNeuralNetworkValueExpert must be a PDG code");
447 std::shared_ptr<PIDNeuralNetwork> neuralNetworkPtr;
448 if (arguments.size() == 2) {
449 std::string parameterSetName = arguments[1];
450 neuralNetworkPtr = std::make_shared<PIDNeuralNetwork>(parameterSetName);
452 neuralNetworkPtr = std::make_shared<PIDNeuralNetwork>();
455 neuralNetworkPtr->hasPdgCode(pdgCode,
true);
457 auto func = [neuralNetworkPtr, pdgCode](
const Particle * part) ->
double {
458 const auto& extraInfoName = neuralNetworkPtr->getExtraInfoName(pdgCode);
459 if (part->hasExtraInfo(extraInfoName))
460 return part->getExtraInfo(extraInfoName);
462 const PIDLikelihood* pid = part->getPIDLikelihood();
467 std::vector<float> inputsNN;
468 inputsNN.reserve(neuralNetworkPtr->getInputSize());
469 for (
const auto& inputName : neuralNetworkPtr->getInputBasf2Names())
472 const auto probabilities = neuralNetworkPtr->predict(inputsNN);
475 for (
const auto element : probabilities)
477 const auto [pdgCodeElement, probability] = element;
478 const_cast<Particle*
>(part)->addExtraInfo(neuralNetworkPtr->getExtraInfoName(pdgCodeElement), probability);
481 return probabilities.at(pdgCode);
488 Manager::FunctionPtr pidWeightedPairProbabilityExpert(
const std::vector<std::string>& arguments)
490 if (arguments.size() < 4) {
491 B2ERROR(
"Need at least four arguments to pidWeightedPairProbabilityExpert");
494 std::string matrixName = arguments[0];
496 int pdgCodeHyp = 0, pdgCodeTest = 0;
498 pdgCodeHyp = Belle2::convertString<int>(arguments[1]);
499 }
catch (std::invalid_argument& e) {
500 B2ERROR(
"Second argument of pidWeightedPairProbabilityExpert must be PDG code");
504 pdgCodeTest = Belle2::convertString<int>(arguments[2]);
505 }
catch (std::invalid_argument& e) {
506 B2ERROR(
"Third argument of pidWeightedPairProbabilityExpert must be PDG code");
510 std::vector<std::string> detectors(arguments.begin() + 3, arguments.end());
513 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
514 auto testType = Const::ChargedStable(abs(pdgCodeTest));
516 auto func = [hypType, testType, detectorSet, matrixName](
const Particle * part) ->
double {
517 PIDCalibrationWeightUtil weightMatrix(matrixName);
519 const PIDLikelihood* pid = part->getPIDLikelihood();
525 auto mom = frame.getMomentum(part);
527 auto theta = mom.Theta();
529 double LogL_hypType(0), LogL_testType(0);
532 if (detectorSet.contains(detector)) {
533 LogL_hypType += pid->getLogL(hypType, detector) * weightMatrix.getWeight(hypType.getPDGCode(), detector, p, theta);
534 LogL_testType += pid->getLogL(testType, detector) * weightMatrix.getWeight(testType.getPDGCode(), detector, p, theta);
538 double deltaLogL = LogL_testType - LogL_hypType;
542 double eLogL = exp(deltaLogL);
543 res = 1. / (1. + eLogL);
546 double eLogL = exp(-deltaLogL);
547 res = eLogL / (1.0 + eLogL);
550 if (std::isfinite(res))
558 double electronID(
const Particle* part)
561 pidProbabilityExpert({
"11",
"ALL"});
562 return std::get<double>(pidFunction(part));
565 double muonID(
const Particle* part)
568 pidProbabilityExpert({
"13",
"ALL"});
569 return std::get<double>(pidFunction(part));
572 double pionID(
const Particle* part)
575 pidProbabilityExpert({
"211",
"ALL"});
576 return std::get<double>(pidFunction(part));
579 double kaonID(
const Particle* part)
582 pidProbabilityExpert({
"321",
"ALL"});
583 return std::get<double>(pidFunction(part));
586 double protonID(
const Particle* part)
589 pidProbabilityExpert({
"2212",
"ALL"});
590 return std::get<double>(pidFunction(part));
593 double deuteronID(
const Particle* part)
596 pidProbabilityExpert({
"1000010020",
"ALL"});
597 return std::get<double>(pidFunction(part));
600 double binaryPID(
const Particle* part,
const std::vector<double>& arguments)
602 if (arguments.size() != 2) {
603 B2ERROR(
"The variable binaryPID needs exactly two arguments: the PDG codes of two hypotheses.");
606 int pdgCodeHyp = std::abs(
int(std::lround(arguments[0])));
607 int pdgCodeTest = std::abs(
int(std::lround(arguments[1])));
608 return std::get<double>(
Manager::Instance().getVariable(
"pidPairProbabilityExpert(" + std::to_string(
609 pdgCodeHyp) +
", " + std::to_string(
610 pdgCodeTest) +
", ALL)")->function(part));
613 double electronID_noSVD(
const Particle* part)
617 pidProbabilityExpert({
"11",
"CDC",
"TOP",
"ARICH",
"ECL",
"KLM"});
618 return std::get<double>(pidFunction(part));
621 double muonID_noSVD(
const Particle* part)
625 pidProbabilityExpert({
"13",
"CDC",
"TOP",
"ARICH",
"ECL",
"KLM"});
626 return std::get<double>(pidFunction(part));
629 double pionID_noSVD(
const Particle* part)
633 pidProbabilityExpert({
"211",
"CDC",
"TOP",
"ARICH",
"ECL",
"KLM"});
634 return std::get<double>(pidFunction(part));
637 double kaonID_noSVD(
const Particle* part)
641 pidProbabilityExpert({
"321",
"CDC",
"TOP",
"ARICH",
"ECL",
"KLM"});
642 return std::get<double>(pidFunction(part));
645 double protonID_noSVD(
const Particle* part)
649 pidProbabilityExpert({
"2212",
"CDC",
"TOP",
"ARICH",
"ECL",
"KLM"});
650 return std::get<double>(pidFunction(part));
653 double deuteronID_noSVD(
const Particle* part)
657 pidProbabilityExpert({
"1000010020",
"CDC",
"TOP",
"ARICH",
"ECL",
"KLM"});
658 return std::get<double>(pidFunction(part));
661 double binaryPID_noSVD(
const Particle* part,
const std::vector<double>& arguments)
664 if (arguments.size() != 2) {
665 B2ERROR(
"The variable binaryPID_noSVD needs exactly two arguments: the PDG codes of two hypotheses.");
668 int pdgCodeHyp = std::abs(
int(std::lround(arguments[0])));
669 int pdgCodeTest = std::abs(
int(std::lround(arguments[1])));
670 return std::get<double>(
Manager::Instance().getVariable(
"pidPairProbabilityExpert(" + std::to_string(
671 pdgCodeHyp) +
", " + std::to_string(
672 pdgCodeTest) +
", CDC, TOP, ARICH, ECL, KLM)")->function(part));
675 double electronID_noTOP(
const Particle* part)
679 pidProbabilityExpert({
"11",
"SVD",
"CDC",
"ARICH",
"ECL",
"KLM"});
680 return std::get<double>(pidFunction(part));
683 double binaryElectronID_noTOP(
const Particle* part,
const std::vector<double>& arguments)
686 if (arguments.size() != 1) {
687 B2ERROR(
"The variable binaryElectronID_noTOP needs exactly one argument: the PDG code of the test hypothesis.");
692 int pdgCodeTest = std::abs(
int(std::lround(arguments[0])));
694 const auto var =
"pidPairProbabilityExpert(" + std::to_string(pdgCodeHyp) +
", " +
695 std::to_string(pdgCodeTest) +
", SVD, CDC, ARICH, ECL, KLM)";
700 double electronID_noSVD_noTOP(
const Particle* part)
704 pidProbabilityExpert({
"11",
"CDC",
"ARICH",
"ECL",
"KLM"});
705 return std::get<double>(pidFunction(part));
708 double binaryElectronID_noSVD_noTOP(
const Particle* part,
const std::vector<double>& arguments)
711 if (arguments.size() != 1) {
712 B2ERROR(
"The variable binaryElectronID_noSVD_noTOP needs exactly one argument: the PDG code of the test hypothesis.");
717 int pdgCodeTest = std::abs(
int(std::lround(arguments[0])));
719 const auto var =
"pidPairProbabilityExpert(" + std::to_string(pdgCodeHyp) +
", " +
720 std::to_string(pdgCodeTest) +
", CDC, ARICH, ECL, KLM)";
726 double pionID_noARICHwoECL(
const Particle* part)
729 const ECLCluster* cluster = part->getECLCluster();
731 const PIDLikelihood* pid = part->getPIDLikelihood();
735 pidProbabilityExpert({
"211",
"SVD",
"CDC",
"TOP",
"ECL",
"KLM"});
736 return std::get<double>(pidFunction(part));
743 double kaonID_noARICHwoECL(
const Particle* part)
746 const ECLCluster* cluster = part->getECLCluster();
748 const PIDLikelihood* pid = part->getPIDLikelihood();
752 pidProbabilityExpert({
"321",
"SVD",
"CDC",
"TOP",
"ECL",
"KLM"});
753 return std::get<double>(pidFunction(part));
760 double binaryPID_noARICHwoECL(
const Particle* part,
const std::vector<double>& arguments)
763 if (arguments.size() != 2) {
764 B2ERROR(
"The variable binaryPID_noARICHwoECL needs exactly two arguments: the PDG codes of two hypotheses.");
767 int pdgCodeHyp = std::abs(
int(std::lround(arguments[0])));
768 int pdgCodeTest = std::abs(
int(std::lround(arguments[1])));
769 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
770 auto testType = Const::ChargedStable(abs(pdgCodeTest));
772 const ECLCluster* cluster = part->getECLCluster();
774 const PIDLikelihood* pid = part->getPIDLikelihood();
776 double lkhdiff = pid->getDeltaLogL(hypType, testType, Const::ARICH);
777 if ((lkhdiff > 0 && pdgCodeHyp > pdgCodeTest) || (lkhdiff < 0 && pdgCodeHyp < pdgCodeTest)) {
778 std::string varName =
"pidPairProbabilityExpert(" +
779 std::to_string(pdgCodeHyp) +
", " + std::to_string(pdgCodeTest) +
", SVD, CDC, TOP, ECL, KLM)";
780 return std::get<double>(
Manager::Instance().getVariable(varName)->function(part));
784 return binaryPID(part, arguments);
790 double antineutronID(
const Particle* particle)
792 if (particle->hasExtraInfo(
"nbarID")) {
793 return particle->getExtraInfo(
"nbarID");
796 B2WARNING(
"The extraInfo nbarID is not registered! \n"
797 "Please use function getNbarIDMVA in modularAnalysis.");
805 if (arguments.size() != 2) {
806 B2ERROR(
"Need exactly two arguments for pidChargedBDTScore: pdgCodeHyp, detector");
812 hypPdgId = Belle2::convertString<int>(arguments.at(0));
813 }
catch (std::invalid_argument& e) {
814 B2ERROR(
"First argument of pidChargedBDTScore must be an integer (PDG code).");
817 Const::ChargedStable hypType = Const::ChargedStable(hypPdgId);
819 std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
822 auto func = [hypType, detectorSet](
const Particle * part) ->
double {
823 auto name =
"pidChargedBDTScore_" + std::to_string(hypType.getPDGCode());
826 name +=
"_" + std::to_string(detector);
828 return (part->hasExtraInfo(name)) ? part->getExtraInfo(name) :
Const::doubleNaN;
835 if (arguments.size() != 3) {
836 B2ERROR(
"Need exactly three arguments for pidPairChargedBDTScore: pdgCodeHyp, pdgCodeTest, detector.");
840 int hypPdgId, testPdgId;
842 hypPdgId = Belle2::convertString<int>(arguments.at(0));
843 }
catch (std::invalid_argument& e) {
844 B2ERROR(
"First argument of pidPairChargedBDTScore must be an integer (PDG code).");
848 testPdgId = Belle2::convertString<int>(arguments.at(1));
849 }
catch (std::invalid_argument& e) {
850 B2ERROR(
"First argument of pidPairChargedBDTScore must be an integer (PDG code).");
853 Const::ChargedStable hypType = Const::ChargedStable(hypPdgId);
854 Const::ChargedStable testType = Const::ChargedStable(testPdgId);
856 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
859 auto func = [hypType, testType, detectorSet](
const Particle * part) ->
double {
860 auto name =
"pidPairChargedBDTScore_" + std::to_string(hypType.getPDGCode()) +
"_VS_" + std::to_string(testType.getPDGCode());
863 name +=
"_" + std::to_string(detector);
865 return (part->hasExtraInfo(name)) ? part->getExtraInfo(name) :
Const::doubleNaN;
870 double mostLikelyPDG(
const Particle* part,
const std::vector<double>& arguments)
877 if (arguments.size() == 0) {
880 copy(arguments.begin(), arguments.end(), prob);
883 auto* pid = part->getPIDLikelihood();
885 return pid->getMostLikely(prob).getPDGCode();
888 bool isMostLikely(
const Particle* part,
const std::vector<double>& arguments)
894 return mostLikelyPDG(part, arguments) == abs(part->getPDGCode());
900 if (arguments.size() == 0) {
901 varName =
"pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 11, ALL)";
902 }
else if (arguments.size() == 1) {
903 varName =
"pidWeightedProbabilityExpert(" + arguments[0] +
", 11, ALL)";
905 B2ERROR(
"Need zero or one argument for weightedElectronID");
910 auto func = [var](
const Particle * particle) ->
double {
911 return std::get<double>(var->function(particle));
919 if (arguments.size() == 0) {
920 varName =
"pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 13, ALL)";
921 }
else if (arguments.size() == 1) {
922 varName =
"pidWeightedProbabilityExpert(" + arguments[0] +
", 13, ALL)";
924 B2ERROR(
"Need zero or one argument for weightedMuonID");
929 auto func = [var](
const Particle * particle) ->
double {
930 return std::get<double>(var->function(particle));
938 if (arguments.size() == 0) {
939 varName =
"pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 211, ALL)";
940 }
else if (arguments.size() == 1) {
941 varName =
"pidWeightedProbabilityExpert(" + arguments[0] +
", 211, ALL)";
943 B2ERROR(
"Need zero or one argument for weightedPionID");
948 auto func = [var](
const Particle * particle) ->
double {
949 return std::get<double>(var->function(particle));
957 if (arguments.size() == 0) {
958 varName =
"pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 321, ALL)";
959 }
else if (arguments.size() == 1) {
960 varName =
"pidWeightedProbabilityExpert(" + arguments[0] +
", 321, ALL)";
962 B2ERROR(
"Need zero or one argument for weightedKaonID");
967 auto func = [var](
const Particle * particle) ->
double {
968 return std::get<double>(var->function(particle));
976 if (arguments.size() == 0) {
977 varName =
"pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 2212, ALL)";
978 }
else if (arguments.size() == 1) {
979 varName =
"pidWeightedProbabilityExpert(" + arguments[0] +
", 2212, ALL)";
981 B2ERROR(
"Need zero or one argument for weightedProtonID");
986 auto func = [var](
const Particle * particle) ->
double {
987 return std::get<double>(var->function(particle));
995 if (arguments.size() == 0) {
996 varName =
"pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 1000010020, ALL)";
997 }
else if (arguments.size() == 1) {
998 varName =
"pidWeightedProbabilityExpert(" + arguments[0] +
", 1000010020, ALL)";
1000 B2ERROR(
"Need zero or one argument for weightedDeuteronID");
1005 auto func = [var](
const Particle * particle) ->
double {
1006 return std::get<double>(var->function(particle));
1012 double electronIDNN(
const Particle* particle)
1014 if (particle->hasExtraInfo(
"pidNeuralNetworkValueExpert(11)"))
1015 return particle->getExtraInfo(
"pidNeuralNetworkValueExpert(11)");
1016 static auto func = pidNeuralNetworkValueExpert({
"11"});
1017 return std::get<double>(func(particle));
1020 double muonIDNN(
const Particle* particle)
1022 if (particle->hasExtraInfo(
"pidNeuralNetworkValueExpert(13)"))
1023 return particle->getExtraInfo(
"pidNeuralNetworkValueExpert(13)");
1024 static auto func = pidNeuralNetworkValueExpert({
"13"});
1025 return std::get<double>(func(particle));
1028 double pionIDNN(
const Particle* particle)
1030 if (particle->hasExtraInfo(
"pidNeuralNetworkValueExpert(211)"))
1031 return particle->getExtraInfo(
"pidNeuralNetworkValueExpert(211)");
1032 static auto func = pidNeuralNetworkValueExpert({
"211"});
1033 return std::get<double>(func(particle));
1036 double kaonIDNN(
const Particle* particle)
1038 if (particle->hasExtraInfo(
"pidNeuralNetworkValueExpert(321)"))
1039 return particle->getExtraInfo(
"pidNeuralNetworkValueExpert(321)");
1040 static auto func = pidNeuralNetworkValueExpert({
"321"});
1041 return std::get<double>(func(particle));
1044 double protonIDNN(
const Particle* particle)
1046 if (particle->hasExtraInfo(
"pidNeuralNetworkValueExpert(2212)"))
1047 return particle->getExtraInfo(
"pidNeuralNetworkValueExpert(2212)");
1048 static auto func = pidNeuralNetworkValueExpert({
"2212"});
1049 return std::get<double>(func(particle));
1052 double deuteronIDNN(
const Particle* particle)
1054 if (particle->hasExtraInfo(
"pidNeuralNetworkValueExpert(1000010020)"))
1055 return particle->getExtraInfo(
"pidNeuralNetworkValueExpert(1000010020)");
1056 static auto func = pidNeuralNetworkValueExpert({
"1000010020"});
1057 return std::get<double>(func(particle));
1061 double klmMuonIDDNN(
const Particle* part)
1063 const PIDLikelihood* pid = part->getPIDLikelihood();
1065 double klmMuonIDDNNvalue = pid->getPreOfficialLikelihood(
"klmMuonIDDNN");
1068 return klmMuonIDDNNvalue;
1075 double muIDBelle(
const Particle* particle)
1077 const PIDLikelihood* pid = particle->getPIDLikelihood();
1078 if (!pid)
return 0.5;
1080 if (pid->isAvailable(Const::KLM))
1081 return exp(pid->getLogL(
Const::muon, Const::KLM));
1086 double muIDBelleQuality(
const Particle* particle)
1088 const PIDLikelihood* pid = particle->getPIDLikelihood();
1091 return pid->isAvailable(Const::KLM);
1094 double atcPIDBelle(
const Particle* particle,
const std::vector<double>& sigAndBkgHyp)
1096 int sigHyp = int(std::lround(sigAndBkgHyp[0]));
1097 int bkgHyp = int(std::lround(sigAndBkgHyp[1]));
1099 const PIDLikelihood* pid = particle->getPIDLikelihood();
1100 if (!pid)
return 0.5;
1104 double acc_sig = exp(pid->getLogL(hypothesisConversion(sigHyp), set));
1105 double acc_bkg = exp(pid->getLogL(hypothesisConversion(bkgHyp), set));
1107 if (acc_sig + acc_bkg > 0.0)
1108 acc = acc_sig / (acc_sig + acc_bkg);
1112 double tof_sig = exp(pid->getLogL(hypothesisConversion(sigHyp), set));
1113 double tof_bkg = exp(pid->getLogL(hypothesisConversion(bkgHyp), set));
1115 double tof_all = tof_sig + tof_bkg;
1117 tof = tof_sig / tof_all;
1118 if (tof < 0.001) tof = 0.001;
1119 if (tof > 0.999) tof = 0.999;
1124 double cdc_sig = exp(pid->getLogL(hypothesisConversion(sigHyp), set));
1125 double cdc_bkg = exp(pid->getLogL(hypothesisConversion(bkgHyp), set));
1127 double cdc_all = cdc_sig + cdc_bkg;
1129 cdc = cdc_sig / cdc_all;
1130 if (cdc < 0.001) cdc = 0.001;
1131 if (cdc > 0.999) cdc = 0.999;
1135 double pid_sig = acc * tof * cdc;
1136 double pid_bkg = (1. - acc) * (1. - tof) * (1. - cdc);
1138 return pid_sig / (pid_sig + pid_bkg);
1142 double eIDBelle(
const Particle* part)
1144 const PIDLikelihood* pid = part->getPIDLikelihood();
1145 if (!pid)
return 0.5;
1153 VARIABLE_GROUP(
"PID");
1154 REGISTER_VARIABLE(
"particleID", particleID,
1155 "the particle identification probability under the particle's own hypothesis, using info from all available detectors");
1156 REGISTER_VARIABLE(
"isPIDAvailable", isPIDAvailable,
1157 "True if PID is available (for at least one of the PID detectors");
1158 REGISTER_METAVARIABLE(
"isPIDAvailableFrom(detectorList)", isPIDAvailableFrom,
1159 "True if PID is available for at least one of the detectors in the list)",
1160 Manager::VariableDataType::c_bool);
1161 REGISTER_VARIABLE(
"electronID", electronID,
1162 "electron identification probability defined as :math:`\\mathcal{L}_e/(\\mathcal{L}_e+\\mathcal{L}_\\mu+\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+\\mathcal{L}_d)`, using info from all available detectors");
1163 REGISTER_VARIABLE(
"muonID", muonID,
1164 "muon identification probability defined as :math:`\\mathcal{L}_\\mu/(\\mathcal{L}_e+\\mathcal{L}_\\mu+\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+\\mathcal{L}_d)`, using info from all available detectors");
1165 REGISTER_VARIABLE(
"pionID", pionID,
1166 "pion identification probability defined as :math:`\\mathcal{L}_\\pi/(\\mathcal{L}_e+\\mathcal{L}_\\mu+\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+\\mathcal{L}_d)`, using info from all available detectors");
1167 REGISTER_VARIABLE(
"kaonID", kaonID,
1168 "kaon identification probability defined as :math:`\\mathcal{L}_K/(\\mathcal{L}_e+\\mathcal{L}_\\mu+\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+\\mathcal{L}_d)`, using info from all available detectors");
1169 REGISTER_VARIABLE(
"protonID", protonID,
1170 "proton identification probability defined as :math:`\\mathcal{L}_p/(\\mathcal{L}_e+\\mathcal{L}_\\mu+\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+\\mathcal{L}_d)`, using info from all available detectors");
1171 REGISTER_VARIABLE(
"deuteronID", deuteronID,
1172 "deuteron identification probability defined as :math:`\\mathcal{L}_d/(\\mathcal{L}_e+\\mathcal{L}_\\mu+\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+\\mathcal{L}_d)`, using info from all available detectors");
1173 REGISTER_METAVARIABLE(
"binaryPID(pdgCode1, pdgCode2)", binaryPID,
1174 "Returns the binary probability for the first provided mass hypothesis with respect to the second mass hypothesis using all detector components",
1175 Manager::VariableDataType::c_double);
1176 REGISTER_METAVARIABLE(
"pidChargedBDTScore(pdgCodeHyp, detector)", pidChargedBDTScore,
1177 "Returns the charged Pid BDT score for a certain mass hypothesis with respect to all other charged stable particle hypotheses. The second argument specifies which BDT training to use: based on 'ALL' PID detectors (NB: 'SVD' is currently excluded), or 'ECL' only. The choice depends on the ChargedPidMVAMulticlassModule's configuration.",
1178 Manager::VariableDataType::c_double);
1179 REGISTER_METAVARIABLE(
"pidPairChargedBDTScore(pdgCodeHyp, pdgCodeTest, detector)", pidPairChargedBDTScore,
1180 "Returns the charged Pid BDT score for a certain mass hypothesis with respect to an alternative hypothesis. The second argument specifies which BDT training to use: based on 'ALL' PID detectors (NB: 'SVD' is currently excluded), or 'ECL' only. The choice depends on the ChargedPidMVAModule's configuration.",
1181 Manager::VariableDataType::c_double);
1182 REGISTER_VARIABLE(
"nbarID", antineutronID, R
"DOC(
1183Returns MVA classifier for antineutron PID.
1185- 1 signal(antineutron) like
1187- -1 invalid using this PID due to some ECL variables used unavailable
1189This PID is only for antineutron. Neutron is also considered as background.
1190The variables used are `clusterPulseShapeDiscriminationMVA`, `clusterE`, `clusterLAT`, `clusterE1E9`, `clusterE9E21`,
1191`clusterAbsZernikeMoment40`, `clusterAbsZernikeMoment51`, `clusterZernikeMVA`.)DOC");
1194 REGISTER_VARIABLE(
"electronID_noSVD", electronID_noSVD,
1195 "**(SPECIAL (TEMP) variable)** electron identification probability defined as :math:`\\mathcal{L}_e/(\\mathcal{L}_e+\\mathcal{L}_\\mu+\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+\\mathcal{L}_d)`, using info from all available detectors *excluding the SVD*");
1196 REGISTER_VARIABLE(
"muonID_noSVD", muonID_noSVD,
1197 "**(SPECIAL (TEMP) variable)** muon identification probability defined as :math:`\\mathcal{L}_\\mu/(\\mathcal{L}_e+\\mathcal{L}_\\mu+\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+\\mathcal{L}_d)`, using info from all available detectors *excluding the SVD*");
1198 REGISTER_VARIABLE(
"pionID_noSVD", pionID_noSVD,
1199 "**(SPECIAL (TEMP) variable)** pion identification probability defined as :math:`\\mathcal{L}_\\pi/(\\mathcal{L}_e+\\mathcal{L}_\\mu+\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+\\mathcal{L}_d)`, using info from all available detectors *excluding the SVD*");
1200 REGISTER_VARIABLE(
"kaonID_noSVD", kaonID_noSVD,
1201 "**(SPECIAL (TEMP) variable)** kaon identification probability defined as :math:`\\mathcal{L}_K/(\\mathcal{L}_e+\\mathcal{L}_\\mu+\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+\\mathcal{L}_d)`, using info from all available detectors *excluding the SVD*");
1202 REGISTER_VARIABLE(
"protonID_noSVD", protonID_noSVD,
1203 "**(SPECIAL (TEMP) variable)** proton identification probability defined as :math:`\\mathcal{L}_p/(\\mathcal{L}_e+\\mathcal{L}_\\mu+\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+\\mathcal{L}_d)`, using info from all available detectors *excluding the SVD*");
1204 REGISTER_VARIABLE(
"deuteronID_noSVD", deuteronID_noSVD,
1205 "**(SPECIAL (TEMP) variable)** deuteron identification probability defined as :math:`\\mathcal{L}_d/(\\mathcal{L}_e+\\mathcal{L}_\\mu+\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+\\mathcal{L}_d)`, using info from all available detectors *excluding the SVD*");
1206 REGISTER_METAVARIABLE(
"binaryPID_noSVD(pdgCode1, pdgCode2)", binaryPID_noSVD,
1207 "Returns the binary probability for the first provided mass hypothesis with respect to the second mass hypothesis using all detector components, *excluding the SVD*.",
1208 Manager::VariableDataType::c_double);
1209 REGISTER_VARIABLE(
"electronID_noTOP", electronID_noTOP,
1210 "**(SPECIAL (TEMP) variable)** electron identification probability defined as :math:`\\mathcal{L}_e/(\\mathcal{L}_e+\\mathcal{L}_\\mu+\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+\\mathcal{L}_d)`, using info from all available detectors *excluding the TOP*. *NB:* this variable must be used in place of `electronID` when analysing data (MC) processed (simulated) in *release 6*");
1211 REGISTER_METAVARIABLE(
"binaryElectronID_noTOP(pdgCodeTest)", binaryElectronID_noTOP,
1212 "**(SPECIAL (TEMP) variable)** Returns the binary probability for the electron mass hypothesis with respect to another mass hypothesis using all detector components, *excluding the TOP*. *NB:* this variable must be used in place of `binaryPID` (``pdgCode1=11``) when analysing data (MC) processed (simulated) in **release 6**",
1213 Manager::VariableDataType::c_double);
1214 REGISTER_VARIABLE(
"electronID_noSVD_noTOP", electronID_noSVD_noTOP,
1215 "**(SPECIAL (TEMP) variable)** electron identification probability defined as :math:`\\mathcal{L}_e/(\\mathcal{L}_e+\\mathcal{L}_\\mu+\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+\\mathcal{L}_d)`, using info from all available detectors *excluding the SVD and the TOP*. *NB:* this variable must be used in place of `electronID` when analysing data (MC) processed (simulated) in *release 5*");
1216 REGISTER_METAVARIABLE(
"binaryElectronID_noSVD_noTOP(pdgCodeTest)", binaryElectronID_noSVD_noTOP,
1217 "**(SPECIAL (TEMP) variable)** Returns the binary probability for the electron mass hypothesis with respect to another mass hypothesis using all detector components, *excluding the SVD and the TOP*. *NB:* this variable must be used in place of `binaryPID` (``pdgCode1=11``) when analysing data (MC) processed (simulated) in **release 5**",
1218 Manager::VariableDataType::c_double);
1219 REGISTER_VARIABLE(
"pionID_noARICHwoECL", pionID_noARICHwoECL,
1220 "**(SPECIAL (TEMP) variable)** pion identification probability defined as :math:`\\mathcal{L}_\\pi/(\\mathcal{L}_e+\\mathcal{L}_\\mu+\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+\\mathcal{L}_d)`, using info from all available detectors but ARICH info excluded for tracks without associated ECL cluster");
1221 REGISTER_VARIABLE(
"kaonID_noARICHwoECL", kaonID_noARICHwoECL,
1222 "**(SPECIAL (TEMP) variable)** kaon identification probability defined as :math:`\\mathcal{L}_K/(\\mathcal{L}_e+\\mathcal{L}_\\mu+\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+\\mathcal{L}_d)`, using info from all available detectors but ARICH info excluded for tracks without associated ECL cluster");
1223 REGISTER_METAVARIABLE(
"binaryPID_noARICHwoECL(pdgCode1, pdgCode2)", binaryPID_noARICHwoECL,
1224 "Returns the binary probability for the first provided mass hypothesis with respect to the second mass hypothesis using all detector components, but ARICH info excluded for tracks without associated ECL cluster",
1225 Manager::VariableDataType::c_double);
1228 REGISTER_METAVARIABLE(
"weightedElectronID(weightMatrixName)", weightedElectronID,
1230weighted electron identification probability defined as :math:`\frac{\mathcal{\tilde{L}}_e}{\sum_{i=e,\mu,\pi,K,p,d} \mathcal{\tilde{L}}_i}`,
1231where :math:`\mathcal{\tilde{L}}_i` is defined as :math:`\log\mathcal{\tilde{L}}_i = \sum_{j={\mathrm{SVD, CDC, TOP, ARICH, ECL, KLM}}} \mathcal{w}_{ij}\log\mathcal{L}_{ij}`.
1232The :math:`\mathcal{L}_{ij}` is the original likelihood and :math:`\mathcal{w}_{ij}` is the PID calibration weight of i-th particle type and j-th detector.
1233One can provide the name of the weight matrix as the argument.
1235 Manager::VariableDataType::c_double);
1236 REGISTER_METAVARIABLE("weightedMuonID(weightMatrixName)", weightedMuonID,
1238weighted muon identification probability defined as :math:`\frac{\mathcal{\tilde{L}}_\mu}{\sum_{i=e,\mu,\pi,K,p,d} \mathcal{\tilde{L}}_i}`,
1239where :math:`\mathcal{\tilde{L}}_i` is defined as :math:`\log\mathcal{\tilde{L}}_i = \sum_{j={\mathrm{SVD, CDC, TOP, ARICH, ECL, KLM}}} \mathcal{w}_{ij}\log\mathcal{L}_{ij}`.
1240The :math:`\mathcal{L}_{ij}` is the original likelihood and :math:`\mathcal{w}_{ij}` is the PID calibration weight of i-th particle type and j-th detector.
1241One can provide the name of the weight matrix as the argument.
1243 Manager::VariableDataType::c_double);
1244 REGISTER_METAVARIABLE("weightedPionID(weightMatrixName)", weightedPionID,
1246weighted pion identification probability defined as :math:`\frac{\mathcal{\tilde{L}}_\pi}{\sum_{i=e,\mu,\pi,K,p,d} \mathcal{\tilde{L}}_i}`,
1247where :math:`\mathcal{\tilde{L}}_i` is defined as :math:`\log\mathcal{\tilde{L}}_i = \sum_{j={\mathrm{SVD, CDC, TOP, ARICH, ECL, KLM}}} \mathcal{w}_{ij}\log\mathcal{L}_{ij}`.
1248The :math:`\mathcal{L}_{ij}` is the original likelihood and :math:`\mathcal{w}_{ij}` is the PID calibration weight of i-th particle type and j-th detector.
1249One can provide the name of the weight matrix as the argument.
1251 Manager::VariableDataType::c_double);
1252 REGISTER_METAVARIABLE("weightedKaonID(weightMatrixName)", weightedKaonID,
1254weighted kaon identification probability defined as :math:`\frac{\mathcal{\tilde{L}}_K}{\sum_{i=e,\mu,\pi,K,p,d} \mathcal{\tilde{L}}_i}`,
1255where :math:`\mathcal{\tilde{L}}_i` is defined as :math:`\log\mathcal{\tilde{L}}_i = \sum_{j={\mathrm{SVD, CDC, TOP, ARICH, ECL, KLM}}} \mathcal{w}_{ij}\log\mathcal{L}_{ij}`.
1256The :math:`\mathcal{L}_{ij}` is the original likelihood and :math:`\mathcal{w}_{ij}` is the PID calibration weight of i-th particle type and j-th detector.
1257One can provide the name of the weight matrix as the argument.
1259 Manager::VariableDataType::c_double);
1260 REGISTER_METAVARIABLE("weightedProtonID(weightMatrixName)", weightedProtonID,
1262weighted proton identification probability defined as :math:`\frac{\mathcal{\tilde{L}}_p}{\sum_{i=e,\mu,\pi,K,p,d} \mathcal{\tilde{L}}_i}`,
1263where :math:`\mathcal{\tilde{L}}_i` is defined as :math:`\log\mathcal{\tilde{L}}_i = \sum_{j={\mathrm{SVD, CDC, TOP, ARICH, ECL, KLM}}} \mathcal{w}_{ij}\log\mathcal{L}_{ij}`.
1264The :math:`\mathcal{L}_{ij}` is the original likelihood and :math:`\mathcal{w}_{ij}` is the PID calibration weight of i-th particle type and j-th detector.
1265One can provide the name of the weight matrix as the argument.
1267 Manager::VariableDataType::c_double);
1268 REGISTER_METAVARIABLE("weightedDeuteronID(weightMatrixName)", weightedDeuteronID,
1270weighted deuteron identification probability defined as :math:`\frac{\mathcal{\tilde{L}}_d}{\sum_{i=e,\mu,\pi,K,p,d} \mathcal{\tilde{L}}_i}`,
1271where :math:`\mathcal{\tilde{L}}_i` is defined as :math:`\log\mathcal{\tilde{L}}_i = \sum_{j={\mathrm{SVD, CDC, TOP, ARICH, ECL, KLM}}} \mathcal{w}_{ij}\log\mathcal{L}_{ij}`.
1272The :math:`\mathcal{L}_{ij}` is the original likelihood and :math:`\mathcal{w}_{ij}` is the PID calibration weight of i-th particle type and j-th detector.
1273One can provide the name of the weight matrix as the argument.
1275 Manager::VariableDataType::c_double);
1278 REGISTER_VARIABLE("electronIDNN", electronIDNN,
1280electron identification probability as calculated from the PID neural network.
1281Requires global tag 'pid_nn_<release>' with the correct data <release>.
1283 REGISTER_VARIABLE("muonIDNN", muonIDNN,
1285muon identification probability as calculated from the PID neural network.
1286Requires global tag 'pid_nn_<release>' with the correct data <release>.
1288 REGISTER_VARIABLE("pionIDNN", pionIDNN,
1290pion identification probability as calculated from the PID neural network.
1291Requires global tag 'pid_nn_<release>' with the correct data <release>.
1293 REGISTER_VARIABLE("kaonIDNN", kaonIDNN,
1295kaon identification probability as calculated from the PID neural network.
1296Requires global tag 'pid_nn_<release>' with the correct data <release>.
1298 REGISTER_VARIABLE("protonIDNN", protonIDNN,
1300proton identification probability as calculated from the PID neural network.
1301Requires global tag 'pid_nn_<release>' with the correct data <release>.
1303 REGISTER_VARIABLE("deuteronIDNN", deuteronIDNN,
1305deuteron identification probability as calculated from the PID neural network.
1306Requires global tag 'pid_nn_<release>' with the correct data <release>.
1311 VARIABLE_GROUP(
"PID_expert");
1312 REGISTER_METAVARIABLE(
"pidLogLikelihoodValueExpert(pdgCode, detectorList)", pidLogLikelihoodValueExpert,
1313 "returns the log likelihood value of for a specific mass hypothesis and set of detectors.", Manager::VariableDataType::c_double);
1314 REGISTER_METAVARIABLE(
"pidDeltaLogLikelihoodValueExpert(pdgCode1, pdgCode2, detectorList)", pidDeltaLogLikelihoodValueExpert,
1315 "returns LogL(hyp1) - LogL(hyp2) (aka DLL) for two mass hypotheses and a set of detectors.", Manager::VariableDataType::c_double);
1316 REGISTER_METAVARIABLE(
"pidPairProbabilityExpert(pdgCodeHyp, pdgCodeTest, detectorList)", pidPairProbabilityExpert,
1317 "Pair (or binary) probability for the pdgCodeHyp mass hypothesis respect to the pdgCodeTest one, using an arbitrary set of detectors. :math:`\\mathcal{L}_{hyp}/(\\mathcal{L}_{test}+\\mathcal{L}_{hyp})`",
1318 Manager::VariableDataType::c_double);
1319 REGISTER_METAVARIABLE(
"pidProbabilityExpert(pdgCodeHyp, detectorList)", pidProbabilityExpert,
1320 "probability for the pdgCodeHyp mass hypothesis respect to all the other ones, using an arbitrary set of detectors :math:`\\mathcal{L}_{hyp}/(\\Sigma_{\\text{all~hyp}}\\mathcal{L}_{i})`. ",
1321 Manager::VariableDataType::c_double);
1322 REGISTER_METAVARIABLE(
"pidLogarithmicProbabilityExpert(pdgCodeHyp, detectorList)", pidLogarithmicProbabilityExpert,
1323 "logarithmic equivalent of pidProbability (p) defined as log(p/(1-p)), which gives a smooth peak-like distribution",
1324 Manager::VariableDataType::c_double);
1325 REGISTER_METAVARIABLE(
"pidMissingProbabilityExpert(detectorList)", pidMissingProbabilityExpert,
1326 "returns 1 if PID is missing for at least one of the detectors in the list, otherwise 0. ",
1327 Manager::VariableDataType::c_double);
1328 REGISTER_VARIABLE(
"pidMostLikelyPDG(ePrior=1/6, muPrior=1/6, piPrior=1/6, KPrior=1/6, pPrior=1/6, dPrior=1/6)", mostLikelyPDG,
1330Returns PDG code of the largest PID likelihood, or NaN if PID information is not available.
1331This function accepts either no arguments, or 6 floats as priors for the charged particle hypotheses
1332following the order shown in the metavariable's declaration. Flat priors are assumed as default.)DOC");
1333 REGISTER_VARIABLE("pidIsMostLikely(ePrior=1/6, muPrior=1/6, piPrior=1/6, KPrior=1/6, pPrior=1/6, dPrior=1/6)", isMostLikely, R
"DOC(
1334Returns True if the largest PID likelihood of a given particle corresponds to its particle hypothesis.
1335This function accepts either no arguments, or 6 floats as priors for the charged particle hypotheses
1336following the order shown in the metavariable's declaration. Flat priors are assumed as default.)DOC");
1338 REGISTER_METAVARIABLE("pidWeightedLogLikelihoodValueExpert(weightMatrixName, pdgCode, detectorList)",
1339 pidWeightedLogLikelihoodValueExpert,
1340 "returns the weighted log likelihood value of for a specific mass hypothesis and set of detectors, "
1341 ":math:`\\log\\mathcal{\\tilde{L}}_{hyp} = \\sum_{j\\in\\mathrm{detectorList}} \\mathcal{w}_{hyp,j}\\log\\mathcal{L}_{hyp,j}`. "
1342 "The :math:`\\mathcal{L}_{ij}` is the original likelihood and :math:`\\mathcal{w}_{ij}` is the PID calibration weight of i-th particle type and j-th detector.",
1343 Manager::VariableDataType::c_double);
1344 REGISTER_METAVARIABLE(
"pidWeightedPairProbabilityExpert(weightMatrixName, pdgCodeHyp, pdgCodeTest, detectorList)",
1345 pidWeightedPairProbabilityExpert,
1346 "Weighted pair (or binary) probability for the pdgCodeHyp mass hypothesis with respect to the pdgCodeTest one, using an arbitrary set of detectors, "
1347 ":math:`\\mathcal{\\tilde{L}}_{hyp}/(\\mathcal{\\tilde{L}}_{test}+\\mathcal{\\tilde{L}}_{hyp})` where :math:`\\mathcal{\\tilde{L}}_{i}` is defined as "
1348 ":math:`\\log\\mathcal{\\tilde{L}}_{i} = \\sum_{j\\in\\mathrm{detectorList}} \\mathcal{w}_{i,j}\\log\\mathcal{L}_{i,j}`. "
1349 "The :math:`\\mathcal{L}_{ij}` is the original likelihood and :math:`\\mathcal{w}_{ij}` is the PID calibration weight of i-th particle type and j-th detector.",
1350 Manager::VariableDataType::c_double);
1351 REGISTER_METAVARIABLE(
"pidWeightedProbabilityExpert(weightMatrixName, pdgCodeHyp, detectorList)",
1352 pidWeightedProbabilityExpert,
1353 "Weighted probability for the pdgCodeHyp mass hypothesis with respect to all the other ones, using an arbitrary set of detectors, "
1354 ":math:`\\mathcal{\\tilde{L}}_{hyp}/\\sum_{i=e,\\mu,\\pi,K,p,d} \\mathcal{\\tilde{L}}_i` where :math:`\\mathcal{\\tilde{L}}_{i}` is defined as "
1355 ":math:`\\log\\mathcal{\\tilde{L}}_{i} = \\sum_{j\\in\\mathrm{detectorList}} \\mathcal{w}_{i,j}\\log\\mathcal{L}_{i,j}`. "
1356 "The :math:`\\mathcal{L}_{ij}` is the original likelihood and :math:`\\mathcal{w}_{ij}` is the PID calibration weight of i-th particle type and j-th detector.",
1357 Manager::VariableDataType::c_double);
1358 REGISTER_METAVARIABLE(
"pidNeuralNetworkValueExpert(pdgCodeHyp, PIDNeuralNetworkName)",
1359 pidNeuralNetworkValueExpert,
1360 "Probability for the particle hypothesis pdgCodeHype calculated from a neural network, which uses high-level information as inputs, "
1361 "such as the likelihood from the 6 subdetectors for PID for all 6 hypotheses, "
1362 ":math:`\\mathcal{\\tilde{L}}_{hyp}^{det}`, or the track momentum and charge",
1363 Manager::VariableDataType::c_double);
1364 REGISTER_VARIABLE(
"klmMuonIDDNN", klmMuonIDDNN,
1365 "Muon probability calculated from Neural Network with KLM information (expert use only)");
1368 VARIABLE_GROUP(
"Belle PID variables");
1369 REGISTER_METAVARIABLE(
"atcPIDBelle(i,j)", atcPIDBelle, R
"DOC(
1370[Legacy] Returns Belle's PID atc variable: ``atc_pid(3,1,5,i,j).prob()``.
1371Parameters i,j are signal and background hypothesis: (0 = electron, 1 = muon, 2 = pion, 3 = kaon, 4 = proton)
1372Returns 0.5 in case there is no likelihood found and a factor of 0.5 will appear in the product if any of the subdetectors don't report a likelihood (Belle behaviour).
1374.. warning:: The behaviour is different from Belle II PID variables which typically return NaN in case of error.
1375 )DOC", Manager::VariableDataType::c_double);
1376 REGISTER_VARIABLE("muIDBelle", muIDBelle, R
"DOC(
1377[Legacy] Returns Belle's PID ``Muon_likelihood()`` variable.
1378Returns 0.5 in case there is no likelihood found and returns zero if the muon likelihood is not usable (Belle behaviour).
1380.. warning:: The behaviour is different from Belle II PID variables which typically return NaN in case of error.
1382 REGISTER_VARIABLE("muIDBelleQuality", muIDBelleQuality, R
"DOC(
1383[Legacy] Returns true if Belle's PID ``Muon_likelihood()`` is usable (reliable).
1384Returns zero/false if not usable or if there is no PID found.
1386 REGISTER_VARIABLE("eIDBelle", eIDBelle, R
"DOC(
1387[Legacy] Returns Belle's electron ID ``eid(3,-1,5).prob()`` variable.
1388Returns 0.5 in case there is no likelihood found (Belle behaviour).
1390.. warning:: The behaviour is different from Belle II PID variables which typically return NaN in case of error.
static const unsigned int c_SetSize
Number of elements (for use in array bounds etc.)
static DetectorSet set()
Accessor function for the set of valid detectors.
int getPDGCode() const
PDG code.
static DetectorSet set()
Accessor for the set of valid detector IDs.
static const ParticleType neutron
neutron particle
static const ChargedStable muon
muon particle
RestrictedDetectorSet< PIDDetectors > PIDDetectorSet
Typedef for set of PID detectors.
static const ParticleSet chargedStableSet
set of charged stable particles
EDetector
Enum for identifying the detector components (detector and subdetector).
static const ChargedStable pion
charged pion particle
static const ChargedStable proton
proton particle
static const double doubleNaN
quiet_NaN
static const ChargedStable kaon
charged kaon particle
static const ChargedStable electron
electron particle
static const ChargedStable deuteron
deuteron particle
static const ReferenceFrame & GetCurrent()
Get current rest frame.
std::function< VarVariant(const Particle *)> FunctionPtr
functions stored take a const Particle* and return VarVariant.
const Var * getVariable(std::string name)
Get the variable belonging to the given key.
static Manager & Instance()
get singleton instance.
Abstract base class for different kinds of events.
FunctionPtr function
Pointer to function.