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>
23 #include <analysis/dbobjects/PIDCalibrationWeight.h>
24 #include <analysis/utility/PIDCalibrationWeightUtil.h>
26 #include <boost/algorithm/string.hpp>
48 Const::ChargedStable hypothesisConversion(
const int hypothesis)
52 return Const::electron;
67 Const::PIDDetectorSet parseDetectors(
const std::vector<std::string>& arguments)
69 Const::PIDDetectorSet result;
70 for (std::string val : arguments) {
72 if (val ==
"all")
return Const::PIDDetectors::set();
73 else if (val ==
"svd") result += Const::SVD;
74 else if (val ==
"cdc") result += Const::CDC;
75 else if (val ==
"top") result += Const::TOP;
76 else if (val ==
"arich") result += Const::ARICH;
77 else if (val ==
"ecl") result += Const::ECL;
78 else if (val ==
"klm") result += Const::KLM;
79 else B2ERROR(
"Unknown detector component: " << val);
85 Const::PIDDetectorSet parseDetectorsChargedBDT(
const std::vector<std::string>& arguments)
87 Const::PIDDetectorSet result;
88 for (std::string val : arguments) {
90 if (val ==
"all")
return Const::PIDDetectors::set();
91 else if (val ==
"ecl") result += Const::ECL;
92 else B2ERROR(
"Invalid detector component: " << val <<
" for charged BDT.");
103 double particleID(
const Particle* p)
105 int pdg = abs(p->getPDGCode());
106 if (pdg == Const::electron.getPDGCode())
return electronID(p);
107 else if (pdg == Const::muon.getPDGCode())
return muonID(p);
108 else if (pdg == Const::pion.getPDGCode())
return pionID(p);
109 else if (pdg == Const::kaon.getPDGCode())
return kaonID(p);
110 else if (pdg == Const::proton.getPDGCode())
return protonID(p);
111 else if (pdg == Const::deuteron.getPDGCode())
return deuteronID(p);
112 else return std::numeric_limits<float>::quiet_NaN();
115 Manager::FunctionPtr pidLogLikelihoodValueExpert(
const std::vector<std::string>& arguments)
117 if (arguments.size() < 2) {
118 B2ERROR(
"Need at least two arguments to pidLogLikelihoodValueExpert");
123 pdgCode = Belle2::convertString<int>(arguments[0]);
124 }
catch (std::invalid_argument& e) {
125 B2ERROR(
"First argument of pidLogLikelihoodValueExpert must be a PDG code");
128 std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
130 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
131 auto hypType = Const::ChargedStable(abs(pdgCode));
133 auto func = [hypType, detectorSet](
const Particle * part) ->
double {
134 const PIDLikelihood* pid = part->getPIDLikelihood();
136 return std::numeric_limits<float>::quiet_NaN();
138 if (pid->getLogL(hypType, detectorSet) == 0)
139 return std::numeric_limits<float>::quiet_NaN();
141 return pid->getLogL(hypType, detectorSet);
148 Manager::FunctionPtr pidDeltaLogLikelihoodValueExpert(
const std::vector<std::string>& arguments)
150 if (arguments.size() < 3) {
151 B2ERROR(
"Need at least three arguments to pidDeltaLogLikelihoodValueExpert");
154 int pdgCodeHyp, pdgCodeTest;
156 pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
157 }
catch (std::invalid_argument& e) {
158 B2ERROR(
"First argument of pidDeltaLogLikelihoodValueExpert must be a PDG code");
162 pdgCodeTest = Belle2::convertString<int>(arguments[1]);
163 }
catch (std::invalid_argument& e) {
164 B2ERROR(
"Second argument of pidDeltaLogLikelihoodValueExpert must be a PDG code");
168 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
169 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
170 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
171 auto testType = Const::ChargedStable(abs(pdgCodeTest));
173 auto func = [hypType, testType, detectorSet](
const Particle * part) ->
double {
174 const PIDLikelihood* pid = part->getPIDLikelihood();
175 if (!pid)
return std::numeric_limits<float>::quiet_NaN();
177 if (pid->getLogL(hypType, detectorSet) == 0)
178 return std::numeric_limits<float>::quiet_NaN();
180 return (pid->getLogL(hypType, detectorSet) - pid->getLogL(testType, detectorSet));
186 Manager::FunctionPtr pidPairProbabilityExpert(
const std::vector<std::string>& arguments)
188 if (arguments.size() < 3) {
189 B2ERROR(
"Need at least three arguments to pidPairProbabilityExpert");
192 int pdgCodeHyp = 0, pdgCodeTest = 0;
194 pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
195 }
catch (std::invalid_argument& e) {
196 B2ERROR(
"First argument of pidPairProbabilityExpert must be PDG code");
200 pdgCodeTest = Belle2::convertString<int>(arguments[1]);
201 }
catch (std::invalid_argument& e) {
202 B2ERROR(
"Second argument of pidPairProbabilityExpert must be PDG code");
206 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
208 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
209 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
210 auto testType = Const::ChargedStable(abs(pdgCodeTest));
211 auto func = [hypType, testType, detectorSet](
const Particle * part) ->
double {
212 const PIDLikelihood* pid = part->getPIDLikelihood();
213 if (!pid)
return std::numeric_limits<float>::quiet_NaN();
215 if (pid->getLogL(hypType, detectorSet) == 0)
216 return std::numeric_limits<float>::quiet_NaN();
218 return pid->getProbability(hypType, testType, detectorSet);
224 Manager::FunctionPtr pidProbabilityExpert(
const std::vector<std::string>& arguments)
226 if (arguments.size() < 2) {
227 B2ERROR(
"Need at least two arguments for pidProbabilityExpert");
232 pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
233 }
catch (std::invalid_argument& e) {
234 B2ERROR(
"First argument of pidProbabilityExpert must be PDG code");
238 std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
239 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
240 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
243 const unsigned int n = Const::ChargedStable::c_SetSize;
245 for (
double& i : frac) i = 1.0;
247 auto func = [hypType, frac, detectorSet](
const Particle * part) ->
double {
248 const PIDLikelihood* pid = part->getPIDLikelihood();
249 if (!pid)
return std::numeric_limits<float>::quiet_NaN();
251 if (pid->getLogL(hypType, detectorSet) == 0)
252 return std::numeric_limits<float>::quiet_NaN();
254 return pid->getProbability(hypType, frac, detectorSet);
260 Manager::FunctionPtr pidMissingProbabilityExpert(
const std::vector<std::string>& arguments)
262 if (arguments.size() < 1) {
263 B2ERROR(
"Need at least one argument to pidMissingProbabilityExpert");
267 std::vector<std::string> detectors(arguments.begin(), arguments.end());
268 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
270 auto func = [detectorSet](
const Particle * part) ->
double {
271 const PIDLikelihood* pid = part->getPIDLikelihood();
272 if (!pid)
return std::numeric_limits<double>::quiet_NaN();
273 if (not pid->isAvailable(detectorSet))
280 Manager::FunctionPtr pidWeightedLogLikelihoodValueExpert(
const std::vector<std::string>& arguments)
282 if (arguments.size() < 3) {
283 B2ERROR(
"Need at least three arguments to pidWeightedLogLikelihoodValueExpert");
286 std::string matrixName = arguments[0];
290 pdgCode = Belle2::convertString<int>(arguments[1]);
291 }
catch (std::invalid_argument& e) {
292 B2ERROR(
"Second argument of pidWeightedLogLikelihoodValueExpert must be a PDG code");
295 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
296 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
297 auto hypType = Const::ChargedStable(abs(pdgCode));
299 auto func = [hypType, detectorSet, matrixName](
const Particle * part) ->
double {
300 PIDCalibrationWeightUtil weightMatrix(matrixName);
301 const PIDLikelihood* pid = part->getPIDLikelihood();
303 return std::numeric_limits<float>::quiet_NaN();
305 if (pid->getLogL(hypType, detectorSet) == 0)
306 return std::numeric_limits<float>::quiet_NaN();
308 const auto& frame = ReferenceFrame::GetCurrent();
309 auto mom = frame.getMomentum(part);
311 auto theta = mom.Theta();
314 for (
const Const::EDetector& detector : Const::PIDDetectorSet::set())
316 if (detectorSet.contains(detector))
317 LogL += pid->getLogL(hypType, detector) * weightMatrix.getWeight(hypType.getPDGCode(), detector, p, theta);
325 Manager::FunctionPtr pidWeightedProbabilityExpert(
const std::vector<std::string>& arguments)
327 if (arguments.size() < 3) {
328 B2ERROR(
"Need at least three arguments for pidWeightedProbabilityExpert");
331 std::string matrixName = arguments[0];
335 pdgCodeHyp = Belle2::convertString<int>(arguments[1]);
336 }
catch (std::invalid_argument& e) {
337 B2ERROR(
"Second argument of pidWeightedProbabilityExpert must be PDG code");
341 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
342 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
343 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
345 auto func = [hypType, detectorSet, matrixName](
const Particle * part) ->
double {
346 PIDCalibrationWeightUtil weightMatrix(matrixName);
347 const PIDLikelihood* pid = part->getPIDLikelihood();
348 if (!pid)
return std::numeric_limits<float>::quiet_NaN();
350 if (pid->getLogL(hypType, detectorSet) == 0)
351 return std::numeric_limits<float>::quiet_NaN();
353 const auto& frame = ReferenceFrame::GetCurrent();
354 auto mom = frame.getMomentum(part);
356 auto theta = mom.Theta();
358 double LogL[Const::ChargedStable::c_SetSize];
361 for (
const auto& pdgIter : Const::chargedStableSet)
363 const int index_pdg = pdgIter.getIndex();
366 for (
const Const::EDetector& detector : Const::PIDDetectorSet::set()) {
367 if (detectorSet.contains(detector))
368 LogL[index_pdg] += pid->getLogL(pdgIter, detector) * weightMatrix.getWeight(pdgIter.getPDGCode(), detector, p, theta);
371 if (!hasMax || (LogL[index_pdg] > LogL_max)) {
372 LogL_max = LogL[index_pdg];
378 for (
unsigned i = 0; i < Const::ChargedStable::c_SetSize; ++i)
379 norm += exp(LogL[i] - LogL_max);
382 return exp(LogL[hypType.getIndex()] - LogL_max) / norm;
390 Manager::FunctionPtr pidWeightedPairProbabilityExpert(
const std::vector<std::string>& arguments)
392 if (arguments.size() < 4) {
393 B2ERROR(
"Need at least four arguments to pidWeightedPairProbabilityExpert");
396 std::string matrixName = arguments[0];
398 int pdgCodeHyp = 0, pdgCodeTest = 0;
400 pdgCodeHyp = Belle2::convertString<int>(arguments[1]);
401 }
catch (std::invalid_argument& e) {
402 B2ERROR(
"Second argument of pidWeightedPairProbabilityExpert must be PDG code");
406 pdgCodeTest = Belle2::convertString<int>(arguments[2]);
407 }
catch (std::invalid_argument& e) {
408 B2ERROR(
"Third argument of pidWeightedPairProbabilityExpert must be PDG code");
412 std::vector<std::string> detectors(arguments.begin() + 3, arguments.end());
414 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
415 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
416 auto testType = Const::ChargedStable(abs(pdgCodeTest));
418 auto func = [hypType, testType, detectorSet, matrixName](
const Particle * part) ->
double {
419 PIDCalibrationWeightUtil weightMatrix(matrixName);
421 const PIDLikelihood* pid = part->getPIDLikelihood();
422 if (!pid)
return std::numeric_limits<float>::quiet_NaN();
424 if (pid->getLogL(hypType, detectorSet) == 0)
425 return std::numeric_limits<float>::quiet_NaN();
427 const auto& frame = ReferenceFrame::GetCurrent();
428 auto mom = frame.getMomentum(part);
430 auto theta = mom.Theta();
432 double LogL_hypType(0), LogL_testType(0);
433 for (
const Const::EDetector& detector : Const::PIDDetectorSet::set())
435 if (detectorSet.contains(detector)) {
436 LogL_hypType += pid->getLogL(hypType, detector) * weightMatrix.getWeight(hypType.getPDGCode(), detector, p, theta);
437 LogL_testType += pid->getLogL(testType, detector) * weightMatrix.getWeight(testType.getPDGCode(), detector, p, theta);
441 double deltaLogL = LogL_testType - LogL_hypType;
445 double eLogL = exp(deltaLogL);
446 res = 1. / (1. + eLogL);
449 double eLogL = exp(-deltaLogL);
450 res = eLogL / (1.0 + eLogL);
453 if (std::isfinite(res))
461 double electronID(
const Particle* part)
463 static Manager::FunctionPtr pidFunction =
464 pidProbabilityExpert({
"11",
"ALL"});
465 return std::get<double>(pidFunction(part));
468 double muonID(
const Particle* part)
470 static Manager::FunctionPtr pidFunction =
471 pidProbabilityExpert({
"13",
"ALL"});
472 return std::get<double>(pidFunction(part));
475 double pionID(
const Particle* part)
477 static Manager::FunctionPtr pidFunction =
478 pidProbabilityExpert({
"211",
"ALL"});
479 return std::get<double>(pidFunction(part));
482 double kaonID(
const Particle* part)
484 static Manager::FunctionPtr pidFunction =
485 pidProbabilityExpert({
"321",
"ALL"});
486 return std::get<double>(pidFunction(part));
489 double protonID(
const Particle* part)
491 static Manager::FunctionPtr pidFunction =
492 pidProbabilityExpert({
"2212",
"ALL"});
493 return std::get<double>(pidFunction(part));
496 double deuteronID(
const Particle* part)
498 static Manager::FunctionPtr pidFunction =
499 pidProbabilityExpert({
"1000010020",
"ALL"});
500 return std::get<double>(pidFunction(part));
503 double binaryPID(
const Particle* part,
const std::vector<double>& arguments)
505 if (arguments.size() != 2) {
506 B2ERROR(
"The variable binaryPID needs exactly two arguments: the PDG codes of two hypotheses.");
507 return std::numeric_limits<float>::quiet_NaN();;
509 int pdgCodeHyp = std::abs(
int(std::lround(arguments[0])));
510 int pdgCodeTest = std::abs(
int(std::lround(arguments[1])));
511 return std::get<double>(Manager::Instance().getVariable(
"pidPairProbabilityExpert(" + std::to_string(
512 pdgCodeHyp) +
", " + std::to_string(
513 pdgCodeTest) +
", ALL)")->
function(part));
516 double electronID_noSVD(
const Particle* part)
519 static Manager::FunctionPtr pidFunction =
520 pidProbabilityExpert({
"11",
"CDC",
"TOP",
"ARICH",
"ECL",
"KLM"});
521 return std::get<double>(pidFunction(part));
524 double muonID_noSVD(
const Particle* part)
527 static Manager::FunctionPtr pidFunction =
528 pidProbabilityExpert({
"13",
"CDC",
"TOP",
"ARICH",
"ECL",
"KLM"});
529 return std::get<double>(pidFunction(part));
532 double pionID_noSVD(
const Particle* part)
535 static Manager::FunctionPtr pidFunction =
536 pidProbabilityExpert({
"211",
"CDC",
"TOP",
"ARICH",
"ECL",
"KLM"});
537 return std::get<double>(pidFunction(part));
540 double kaonID_noSVD(
const Particle* part)
543 static Manager::FunctionPtr pidFunction =
544 pidProbabilityExpert({
"321",
"CDC",
"TOP",
"ARICH",
"ECL",
"KLM"});
545 return std::get<double>(pidFunction(part));
548 double protonID_noSVD(
const Particle* part)
551 static Manager::FunctionPtr pidFunction =
552 pidProbabilityExpert({
"2212",
"CDC",
"TOP",
"ARICH",
"ECL",
"KLM"});
553 return std::get<double>(pidFunction(part));
556 double deuteronID_noSVD(
const Particle* part)
559 static Manager::FunctionPtr pidFunction =
560 pidProbabilityExpert({
"1000010020",
"CDC",
"TOP",
"ARICH",
"ECL",
"KLM"});
561 return std::get<double>(pidFunction(part));
564 double binaryPID_noSVD(
const Particle* part,
const std::vector<double>& arguments)
567 if (arguments.size() != 2) {
568 B2ERROR(
"The variable binaryPID_noSVD needs exactly two arguments: the PDG codes of two hypotheses.");
569 return std::numeric_limits<float>::quiet_NaN();;
571 int pdgCodeHyp = std::abs(
int(std::lround(arguments[0])));
572 int pdgCodeTest = std::abs(
int(std::lround(arguments[1])));
573 return std::get<double>(Manager::Instance().getVariable(
"pidPairProbabilityExpert(" + std::to_string(
574 pdgCodeHyp) +
", " + std::to_string(
575 pdgCodeTest) +
", CDC, TOP, ARICH, ECL, KLM)")->
function(part));
578 double electronID_noTOP(
const Particle* part)
581 static Manager::FunctionPtr pidFunction =
582 pidProbabilityExpert({
"11",
"SVD",
"CDC",
"ARICH",
"ECL",
"KLM"});
583 return std::get<double>(pidFunction(part));
586 double binaryElectronID_noTOP(
const Particle* part,
const std::vector<double>& arguments)
589 if (arguments.size() != 1) {
590 B2ERROR(
"The variable binaryElectronID_noTOP needs exactly one argument: the PDG code of the test hypothesis.");
591 return std::numeric_limits<float>::quiet_NaN();;
594 int pdgCodeHyp = Const::electron.getPDGCode();
595 int pdgCodeTest = std::abs(
int(std::lround(arguments[0])));
597 const auto var =
"pidPairProbabilityExpert(" + std::to_string(pdgCodeHyp) +
", " +
598 std::to_string(pdgCodeTest) +
", SVD, CDC, ARICH, ECL, KLM)";
600 return std::get<double>(Manager::Instance().getVariable(var)->
function(part));
603 double electronID_noSVD_noTOP(
const Particle* part)
606 static Manager::FunctionPtr pidFunction =
607 pidProbabilityExpert({
"11",
"CDC",
"ARICH",
"ECL",
"KLM"});
608 return std::get<double>(pidFunction(part));
611 double binaryElectronID_noSVD_noTOP(
const Particle* part,
const std::vector<double>& arguments)
614 if (arguments.size() != 1) {
615 B2ERROR(
"The variable binaryElectronID_noSVD_noTOP needs exactly one argument: the PDG code of the test hypothesis.");
616 return std::numeric_limits<float>::quiet_NaN();;
619 int pdgCodeHyp = Const::electron.getPDGCode();
620 int pdgCodeTest = std::abs(
int(std::lround(arguments[0])));
622 const auto var =
"pidPairProbabilityExpert(" + std::to_string(pdgCodeHyp) +
", " +
623 std::to_string(pdgCodeTest) +
", CDC, ARICH, ECL, KLM)";
625 return std::get<double>(Manager::Instance().getVariable(var)->
function(part));
629 double pionID_noARICHwoECL(
const Particle* part)
632 const ECLCluster* cluster = part->getECLCluster();
634 const PIDLikelihood* pid = part->getPIDLikelihood();
635 if (!pid)
return std::numeric_limits<float>::quiet_NaN();
636 if (pid->getLogL(Const::kaon, Const::ARICH) > pid->getLogL(Const::pion, Const::ARICH)) {
637 static Manager::FunctionPtr pidFunction =
638 pidProbabilityExpert({
"211",
"SVD",
"CDC",
"TOP",
"ECL",
"KLM"});
639 return std::get<double>(pidFunction(part));
646 double kaonID_noARICHwoECL(
const Particle* part)
649 const ECLCluster* cluster = part->getECLCluster();
651 const PIDLikelihood* pid = part->getPIDLikelihood();
652 if (!pid)
return std::numeric_limits<float>::quiet_NaN();
653 if (pid->getLogL(Const::kaon, Const::ARICH) > pid->getLogL(Const::pion, Const::ARICH)) {
654 static Manager::FunctionPtr pidFunction =
655 pidProbabilityExpert({
"321",
"SVD",
"CDC",
"TOP",
"ECL",
"KLM"});
656 return std::get<double>(pidFunction(part));
663 double binaryPID_noARICHwoECL(
const Particle* part,
const std::vector<double>& arguments)
666 if (arguments.size() != 2) {
667 B2ERROR(
"The variable binaryPID_noARICHwoECL needs exactly two arguments: the PDG codes of two hypotheses.");
668 return std::numeric_limits<float>::quiet_NaN();;
670 int pdgCodeHyp = std::abs(
int(std::lround(arguments[0])));
671 int pdgCodeTest = std::abs(
int(std::lround(arguments[1])));
672 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
673 auto testType = Const::ChargedStable(abs(pdgCodeTest));
675 const ECLCluster* cluster = part->getECLCluster();
677 const PIDLikelihood* pid = part->getPIDLikelihood();
678 if (!pid)
return std::numeric_limits<float>::quiet_NaN();
679 double lkhdiff = pid->getLogL(hypType, Const::ARICH) - pid->getLogL(testType, Const::ARICH);
680 if ((lkhdiff > 0 && pdgCodeHyp > pdgCodeTest) || (lkhdiff < 0 && pdgCodeHyp < pdgCodeTest)) {
681 return std::get<double>(Manager::Instance().getVariable(
"pidPairProbabilityExpert(" + std::to_string(
682 pdgCodeHyp) +
", " + std::to_string(
683 pdgCodeTest) +
", SVD, CDC, TOP, ECL, KLM)")->
function(part));
687 return binaryPID(part, arguments);
693 double antineutronID(
const Particle* particle)
695 if (particle->hasExtraInfo(
"nbarID")) {
696 return particle->getExtraInfo(
"nbarID");
698 if (particle->getPDGCode() == -Const::neutron.getPDGCode()) {
699 B2WARNING(
"The extraInfo nbarID is not registered! \n"
700 "Please use function getNbarIDMVA in modularAnalysis.");
702 return std::numeric_limits<float>::quiet_NaN();
706 Manager::FunctionPtr pidChargedBDTScore(
const std::vector<std::string>& arguments)
708 if (arguments.size() != 2) {
709 B2ERROR(
"Need exactly two arguments for pidChargedBDTScore: pdgCodeHyp, detector");
715 hypPdgId = Belle2::convertString<int>(arguments.at(0));
716 }
catch (std::invalid_argument& e) {
717 B2ERROR(
"First argument of pidChargedBDTScore must be an integer (PDG code).");
720 Const::ChargedStable hypType = Const::ChargedStable(hypPdgId);
722 std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
723 Const::PIDDetectorSet detectorSet = parseDetectorsChargedBDT(detectors);
725 auto func = [hypType, detectorSet](
const Particle * part) ->
double {
726 auto name =
"pidChargedBDTScore_" + std::to_string(hypType.getPDGCode());
727 for (
const Const::EDetector& detector : detectorSet)
729 name +=
"_" + std::to_string(detector);
731 return (part->hasExtraInfo(name)) ? part->getExtraInfo(name) : std::numeric_limits<float>::quiet_NaN();
736 Manager::FunctionPtr pidPairChargedBDTScore(
const std::vector<std::string>& arguments)
738 if (arguments.size() != 3) {
739 B2ERROR(
"Need exactly three arguments for pidPairChargedBDTScore: pdgCodeHyp, pdgCodeTest, detector.");
743 int hypPdgId, testPdgId;
745 hypPdgId = Belle2::convertString<int>(arguments.at(0));
746 }
catch (std::invalid_argument& e) {
747 B2ERROR(
"First argument of pidPairChargedBDTScore must be an integer (PDG code).");
751 testPdgId = Belle2::convertString<int>(arguments.at(1));
752 }
catch (std::invalid_argument& e) {
753 B2ERROR(
"First argument of pidPairChargedBDTScore must be an integer (PDG code).");
756 Const::ChargedStable hypType = Const::ChargedStable(hypPdgId);
757 Const::ChargedStable testType = Const::ChargedStable(testPdgId);
759 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
760 Const::PIDDetectorSet detectorSet = parseDetectorsChargedBDT(detectors);
762 auto func = [hypType, testType, detectorSet](
const Particle * part) ->
double {
763 auto name =
"pidPairChargedBDTScore_" + std::to_string(hypType.getPDGCode()) +
"_VS_" + std::to_string(testType.getPDGCode());
764 for (
const Const::EDetector& detector : detectorSet)
766 name +=
"_" + std::to_string(detector);
768 return (part->hasExtraInfo(name)) ? part->getExtraInfo(name) : std::numeric_limits<float>::quiet_NaN();
773 double mostLikelyPDG(
const Particle* part,
const std::vector<double>& arguments)
775 if (arguments.size() != 0 and arguments.size() != Const::ChargedStable::c_SetSize) {
776 B2ERROR(
"Need zero or exactly " << Const::ChargedStable::c_SetSize <<
" arguments for pidMostLikelyPDG");
777 return std::numeric_limits<double>::quiet_NaN();
779 double prob[Const::ChargedStable::c_SetSize];
780 if (arguments.size() == 0) {
781 for (
unsigned int i = 0; i < Const::ChargedStable::c_SetSize; i++) prob[i] = 1. / Const::ChargedStable::c_SetSize;
783 copy(arguments.begin(), arguments.end(), prob);
786 auto* pid = part->getPIDLikelihood();
787 if (!pid)
return std::numeric_limits<double>::quiet_NaN();
788 return pid->getMostLikely(prob).getPDGCode();
791 bool isMostLikely(
const Particle* part,
const std::vector<double>& arguments)
793 if (arguments.size() != 0 and arguments.size() != Const::ChargedStable::c_SetSize) {
794 B2ERROR(
"Need zero or exactly " << Const::ChargedStable::c_SetSize <<
" arguments for pidIsMostLikely");
797 return mostLikelyPDG(part, arguments) == abs(part->getPDGCode());
800 Manager::FunctionPtr weightedElectronID(
const std::vector<std::string>& arguments)
803 if (arguments.size() == 0) {
804 varName =
"pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 11, ALL)";
805 }
else if (arguments.size() == 1) {
806 varName =
"pidWeightedProbabilityExpert(" + arguments[0] +
", 11, ALL)";
808 B2ERROR(
"Need zero or one argument for weightedElectronID");
812 const Variable::Manager::Var* var = Manager::Instance().getVariable(varName);
813 auto func = [var](
const Particle * particle) ->
double {
814 return std::get<double>(var->function(particle));
819 Manager::FunctionPtr weightedMuonID(
const std::vector<std::string>& arguments)
822 if (arguments.size() == 0) {
823 varName =
"pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 13, ALL)";
824 }
else if (arguments.size() == 1) {
825 varName =
"pidWeightedProbabilityExpert(" + arguments[0] +
", 13, ALL)";
827 B2ERROR(
"Need zero or one argument for weightedMuonID");
831 const Variable::Manager::Var* var = Manager::Instance().getVariable(varName);
832 auto func = [var](
const Particle * particle) ->
double {
833 return std::get<double>(var->function(particle));
838 Manager::FunctionPtr weightedPionID(
const std::vector<std::string>& arguments)
841 if (arguments.size() == 0) {
842 varName =
"pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 211, ALL)";
843 }
else if (arguments.size() == 1) {
844 varName =
"pidWeightedProbabilityExpert(" + arguments[0] +
", 211, ALL)";
846 B2ERROR(
"Need zero or one argument for weightedPionID");
850 const Variable::Manager::Var* var = Manager::Instance().getVariable(varName);
851 auto func = [var](
const Particle * particle) ->
double {
852 return std::get<double>(var->function(particle));
857 Manager::FunctionPtr weightedKaonID(
const std::vector<std::string>& arguments)
860 if (arguments.size() == 0) {
861 varName =
"pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 321, ALL)";
862 }
else if (arguments.size() == 1) {
863 varName =
"pidWeightedProbabilityExpert(" + arguments[0] +
", 321, ALL)";
865 B2ERROR(
"Need zero or one argument for weightedKaonID");
869 const Variable::Manager::Var* var = Manager::Instance().getVariable(varName);
870 auto func = [var](
const Particle * particle) ->
double {
871 return std::get<double>(var->function(particle));
876 Manager::FunctionPtr weightedProtonID(
const std::vector<std::string>& arguments)
879 if (arguments.size() == 0) {
880 varName =
"pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 2212, ALL)";
881 }
else if (arguments.size() == 1) {
882 varName =
"pidWeightedProbabilityExpert(" + arguments[0] +
", 2212, ALL)";
884 B2ERROR(
"Need zero or one argument for weightedProtonID");
888 const Variable::Manager::Var* var = Manager::Instance().getVariable(varName);
889 auto func = [var](
const Particle * particle) ->
double {
890 return std::get<double>(var->function(particle));
895 Manager::FunctionPtr weightedDeuteronID(
const std::vector<std::string>& arguments)
898 if (arguments.size() == 0) {
899 varName =
"pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 1000010020, ALL)";
900 }
else if (arguments.size() == 1) {
901 varName =
"pidWeightedProbabilityExpert(" + arguments[0] +
", 1000010020, ALL)";
903 B2ERROR(
"Need zero or one argument for weightedDeuteronID");
907 const Variable::Manager::Var* var = Manager::Instance().getVariable(varName);
908 auto func = [var](
const Particle * particle) ->
double {
909 return std::get<double>(var->function(particle));
918 double muIDBelle(
const Particle* particle)
920 const PIDLikelihood* pid = particle->getPIDLikelihood();
921 if (!pid)
return 0.5;
923 if (pid->isAvailable(Const::KLM))
924 return exp(pid->getLogL(Const::muon, Const::KLM));
929 double muIDBelleQuality(
const Particle* particle)
931 const PIDLikelihood* pid = particle->getPIDLikelihood();
934 return pid->isAvailable(Const::KLM);
937 double atcPIDBelle(
const Particle* particle,
const std::vector<double>& sigAndBkgHyp)
939 int sigHyp = int(std::lround(sigAndBkgHyp[0]));
940 int bkgHyp = int(std::lround(sigAndBkgHyp[1]));
942 const PIDLikelihood* pid = particle->getPIDLikelihood();
943 if (!pid)
return 0.5;
946 Const::PIDDetectorSet set = Const::ARICH;
947 double acc_sig = exp(pid->getLogL(hypothesisConversion(sigHyp), set));
948 double acc_bkg = exp(pid->getLogL(hypothesisConversion(bkgHyp), set));
950 if (acc_sig + acc_bkg > 0.0)
951 acc = acc_sig / (acc_sig + acc_bkg);
955 double tof_sig = exp(pid->getLogL(hypothesisConversion(sigHyp), set));
956 double tof_bkg = exp(pid->getLogL(hypothesisConversion(bkgHyp), set));
958 double tof_all = tof_sig + tof_bkg;
960 tof = tof_sig / tof_all;
961 if (tof < 0.001) tof = 0.001;
962 if (tof > 0.999) tof = 0.999;
967 double cdc_sig = exp(pid->getLogL(hypothesisConversion(sigHyp), set));
968 double cdc_bkg = exp(pid->getLogL(hypothesisConversion(bkgHyp), set));
970 double cdc_all = cdc_sig + cdc_bkg;
972 cdc = cdc_sig / cdc_all;
973 if (cdc < 0.001) cdc = 0.001;
974 if (cdc > 0.999) cdc = 0.999;
978 double pid_sig = acc * tof * cdc;
979 double pid_bkg = (1. - acc) * (1. - tof) * (1. - cdc);
981 return pid_sig / (pid_sig + pid_bkg);
985 double eIDBelle(
const Particle* part)
987 const PIDLikelihood* pid = part->getPIDLikelihood();
988 if (!pid)
return 0.5;
990 Const::PIDDetectorSet set = Const::ECL;
991 return pid->getProbability(Const::electron, Const::pion, set);
996 VARIABLE_GROUP(
"PID");
997 REGISTER_VARIABLE(
"particleID", particleID,
998 "the particle identification probability under the particle's own hypothesis, using info from all available detectors");
999 REGISTER_VARIABLE(
"electronID", electronID,
1000 "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");
1001 REGISTER_VARIABLE(
"muonID", muonID,
1002 "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");
1003 REGISTER_VARIABLE(
"pionID", pionID,
1004 "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");
1005 REGISTER_VARIABLE(
"kaonID", kaonID,
1006 "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");
1007 REGISTER_VARIABLE(
"protonID", protonID,
1008 "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");
1009 REGISTER_VARIABLE(
"deuteronID", deuteronID,
1010 "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");
1011 REGISTER_METAVARIABLE(
"binaryPID(pdgCode1, pdgCode2)", binaryPID,
1012 "Returns the binary probability for the first provided mass hypothesis with respect to the second mass hypothesis using all detector components",
1013 Manager::VariableDataType::c_double);
1014 REGISTER_METAVARIABLE(
"pidChargedBDTScore(pdgCodeHyp, detector)", pidChargedBDTScore,
1015 "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.",
1016 Manager::VariableDataType::c_double);
1017 REGISTER_METAVARIABLE(
"pidPairChargedBDTScore(pdgCodeHyp, pdgCodeTest, detector)", pidPairChargedBDTScore,
1018 "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.",
1019 Manager::VariableDataType::c_double);
1020 REGISTER_VARIABLE(
"nbarID", antineutronID, R
"DOC(
1021 Returns MVA classifier for antineutron PID.
1023 - 1 signal(antineutron) like
1025 - -1 invalid using this PID due to some ECL variables used unavailable
1027 This PID is only for antineutron. Neutron is also considered as background.
1028 The variables used are `clusterPulseShapeDiscriminationMVA`, `clusterE`, `clusterLAT`, `clusterE1E9`, `clusterE9E21`,
1029 `clusterAbsZernikeMoment40`, `clusterAbsZernikeMoment51`, `clusterZernikeMVA`.)DOC");
1032 REGISTER_VARIABLE(
"electronID_noSVD", electronID_noSVD,
1033 "**(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*");
1034 REGISTER_VARIABLE(
"muonID_noSVD", muonID_noSVD,
1035 "**(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*");
1036 REGISTER_VARIABLE(
"pionID_noSVD", pionID_noSVD,
1037 "**(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*");
1038 REGISTER_VARIABLE(
"kaonID_noSVD", kaonID_noSVD,
1039 "**(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*");
1040 REGISTER_VARIABLE(
"protonID_noSVD", protonID_noSVD,
1041 "**(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*");
1042 REGISTER_VARIABLE(
"deuteronID_noSVD", deuteronID_noSVD,
1043 "**(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*");
1044 REGISTER_METAVARIABLE(
"binaryPID_noSVD(pdgCode1, pdgCode2)", binaryPID_noSVD,
1045 "Returns the binary probability for the first provided mass hypothesis with respect to the second mass hypothesis using all detector components, *excluding the SVD*.",
1046 Manager::VariableDataType::c_double);
1047 REGISTER_VARIABLE(
"electronID_noTOP", electronID_noTOP,
1048 "**(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*");
1049 REGISTER_METAVARIABLE(
"binaryElectronID_noTOP(pdgCodeTest)", binaryElectronID_noTOP,
1050 "**(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**",
1051 Manager::VariableDataType::c_double);
1052 REGISTER_VARIABLE(
"electronID_noSVD_noTOP", electronID_noSVD_noTOP,
1053 "**(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*");
1054 REGISTER_METAVARIABLE(
"binaryElectronID_noSVD_noTOP(pdgCodeTest)", binaryElectronID_noSVD_noTOP,
1055 "**(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**",
1056 Manager::VariableDataType::c_double);
1057 REGISTER_VARIABLE(
"pionID_noARICHwoECL", pionID_noARICHwoECL,
1058 "**(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");
1059 REGISTER_VARIABLE(
"kaonID_noARICHwoECL", kaonID_noARICHwoECL,
1060 "**(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");
1061 REGISTER_METAVARIABLE(
"binaryPID_noARICHwoECL(pdgCode1, pdgCode2)", binaryPID_noARICHwoECL,
1062 "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",
1063 Manager::VariableDataType::c_double);
1066 REGISTER_METAVARIABLE(
"weightedElectronID(weightMatrixName)", weightedElectronID,
1068 weighted electron identification probability defined as :math:`\frac{\mathcal{\tilde{L}}_e}{\sum_{i=e,\mu,\pi,K,p,d} \mathcal{\tilde{L}}_i}`,
1069 where :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}`.
1070 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.
1071 One can provide the name of the weight matrix as the argument.
1073 Manager::VariableDataType::c_double);
1074 REGISTER_METAVARIABLE("weightedMuonID(weightMatrixName)", weightedMuonID,
1076 weighted muon identification probability defined as :math:`\frac{\mathcal{\tilde{L}}_\mu}{\sum_{i=e,\mu,\pi,K,p,d} \mathcal{\tilde{L}}_i}`,
1077 where :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}`.
1078 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.
1079 One can provide the name of the weight matrix as the argument.
1081 Manager::VariableDataType::c_double);
1082 REGISTER_METAVARIABLE("weightedPionID(weightMatrixName)", weightedPionID,
1084 weighted pion identification probability defined as :math:`\frac{\mathcal{\tilde{L}}_\pi}{\sum_{i=e,\mu,\pi,K,p,d} \mathcal{\tilde{L}}_i}`,
1085 where :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}`.
1086 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.
1087 One can provide the name of the weight matrix as the argument.
1089 Manager::VariableDataType::c_double);
1090 REGISTER_METAVARIABLE("weightedKaonID(weightMatrixName)", weightedKaonID,
1092 weighted kaon identification probability defined as :math:`\frac{\mathcal{\tilde{L}}_K}{\sum_{i=e,\mu,\pi,K,p,d} \mathcal{\tilde{L}}_i}`,
1093 where :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}`.
1094 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.
1095 One can provide the name of the weight matrix as the argument.
1097 Manager::VariableDataType::c_double);
1098 REGISTER_METAVARIABLE("weightedProtonID(weightMatrixName)", weightedProtonID,
1100 weighted proton identification probability defined as :math:`\frac{\mathcal{\tilde{L}}_p}{\sum_{i=e,\mu,\pi,K,p,d} \mathcal{\tilde{L}}_i}`,
1101 where :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}`.
1102 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.
1103 One can provide the name of the weight matrix as the argument.
1105 Manager::VariableDataType::c_double);
1106 REGISTER_METAVARIABLE("weightedDeuteronID(weightMatrixName)", weightedDeuteronID,
1108 weighted deuteron identification probability defined as :math:`\frac{\mathcal{\tilde{L}}_d}{\sum_{i=e,\mu,\pi,K,p,d} \mathcal{\tilde{L}}_i}`,
1109 where :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}`.
1110 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.
1111 One can provide the name of the weight matrix as the argument.
1113 Manager::VariableDataType::c_double);
1116 VARIABLE_GROUP(
"PID_expert");
1117 REGISTER_METAVARIABLE(
"pidLogLikelihoodValueExpert(pdgCode, detectorList)", pidLogLikelihoodValueExpert,
1118 "returns the log likelihood value of for a specific mass hypothesis and set of detectors.", Manager::VariableDataType::c_double);
1119 REGISTER_METAVARIABLE(
"pidDeltaLogLikelihoodValueExpert(pdgCode1, pdgCode2, detectorList)", pidDeltaLogLikelihoodValueExpert,
1120 "returns LogL(hyp1) - LogL(hyp2) (aka DLL) for two mass hypotheses and a set of detectors.", Manager::VariableDataType::c_double);
1121 REGISTER_METAVARIABLE(
"pidPairProbabilityExpert(pdgCodeHyp, pdgCodeTest, detectorList)", pidPairProbabilityExpert,
1122 "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})`",
1123 Manager::VariableDataType::c_double);
1124 REGISTER_METAVARIABLE(
"pidProbabilityExpert(pdgCodeHyp, detectorList)", pidProbabilityExpert,
1125 "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})`. ",
1126 Manager::VariableDataType::c_double);
1127 REGISTER_METAVARIABLE(
"pidMissingProbabilityExpert(detectorList)", pidMissingProbabilityExpert,
1128 "returns 1 if the PID probabiliy is missing for the provided detector list, otherwise 0. ", Manager::VariableDataType::c_double);
1129 REGISTER_VARIABLE(
"pidMostLikelyPDG(ePrior=1/6, muPrior=1/6, piPrior=1/6, KPrior=1/6, pPrior=1/6, dPrior=1/6)", mostLikelyPDG,
1131 Returns PDG code of the largest PID likelihood, or NaN if PID information is not available.
1132 This function accepts either no arguments, or 6 floats as priors for the charged particle hypotheses
1133 following the order shown in the metavariable's declaration. Flat priors are assumed as default.)DOC");
1134 REGISTER_VARIABLE("pidIsMostLikely(ePrior=1/6, muPrior=1/6, piPrior=1/6, KPrior=1/6, pPrior=1/6, dPrior=1/6)", isMostLikely, R
"DOC(
1135 Returns True if the largest PID likelihood of a given particle corresponds to its particle hypothesis.
1136 This function accepts either no arguments, or 6 floats as priors for the charged particle hypotheses
1137 following the order shown in the metavariable's declaration. Flat priors are assumed as default.)DOC");
1139 REGISTER_METAVARIABLE("pidWeightedLogLikelihoodValueExpert(weightMatrixName, pdgCode, detectorList)",
1140 pidWeightedLogLikelihoodValueExpert,
1141 "returns the weighted log likelihood value of for a specific mass hypothesis and set of detectors, "
1142 ":math:`\\log\\mathcal{\\tilde{L}}_{hyp} = \\sum_{j\\in\\mathrm{detectorList}} \\mathcal{w}_{hyp,j}\\log\\mathcal{L}_{hyp,j}`. "
1143 "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.",
1144 Manager::VariableDataType::c_double);
1145 REGISTER_METAVARIABLE(
"pidWeightedPairProbabilityExpert(weightMatrixName, pdgCodeHyp, pdgCodeTest, detectorList)",
1146 pidWeightedPairProbabilityExpert,
1147 "Weighted pair (or binary) probability for the pdgCodeHyp mass hypothesis with respect to the pdgCodeTest one, using an arbitrary set of detectors, "
1148 ":math:`\\mathcal{\\tilde{L}}_{hyp}/(\\mathcal{\\tilde{L}}_{test}+\\mathcal{\\tilde{L}}_{hyp})` where :math:`\\mathcal{\\tilde{L}}_{i}` is defined as "
1149 ":math:`\\log\\mathcal{\\tilde{L}}_{i} = \\sum_{j\\in\\mathrm{detectorList}} \\mathcal{w}_{i,j}\\log\\mathcal{L}_{i,j}`. "
1150 "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.",
1151 Manager::VariableDataType::c_double);
1152 REGISTER_METAVARIABLE(
"pidWeightedProbabilityExpert(weightMatrixName, pdgCodeHyp, detectorList)",
1153 pidWeightedProbabilityExpert,
1154 "Weighted probability for the pdgCodeHyp mass hypothesis with respect to all the other ones, using an arbitrary set of detectors, "
1155 ":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 "
1156 ":math:`\\log\\mathcal{\\tilde{L}}_{i} = \\sum_{j\\in\\mathrm{detectorList}} \\mathcal{w}_{i,j}\\log\\mathcal{L}_{i,j}`. "
1157 "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.",
1158 Manager::VariableDataType::c_double);
1161 VARIABLE_GROUP(
"Belle PID variables");
1162 REGISTER_METAVARIABLE(
"atcPIDBelle(i,j)", atcPIDBelle, R
"DOC(
1163 [Legacy] Returns Belle's PID atc variable: ``atc_pid(3,1,5,i,j).prob()``.
1164 Parameters i,j are signal and background hypothesis: (0 = electron, 1 = muon, 2 = pion, 3 = kaon, 4 = proton)
1165 Returns 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).
1167 .. warning:: The behaviour is different from Belle II PID variables which typically return NaN in case of error.
1168 )DOC", Manager::VariableDataType::c_double);
1169 REGISTER_VARIABLE("muIDBelle", muIDBelle, R
"DOC(
1170 [Legacy] Returns Belle's PID ``Muon_likelihood()`` variable.
1171 Returns 0.5 in case there is no likelihood found and returns zero if the muon likelihood is not usable (Belle behaviour).
1173 .. warning:: The behaviour is different from Belle II PID variables which typically return NaN in case of error.
1175 REGISTER_VARIABLE("muIDBelleQuality", muIDBelleQuality, R
"DOC(
1176 [Legacy] Returns true if Belle's PID ``Muon_likelihood()`` is usable (reliable).
1177 Returns zero/false if not usable or if there is no PID found.
1179 REGISTER_VARIABLE("eIDBelle", eIDBelle, R
"DOC(
1180 [Legacy] Returns Belle's electron ID ``eid(3,-1,5).prob()`` variable.
1181 Returns 0.5 in case there is no likelihood found (Belle behaviour).
1183 .. warning:: The behaviour is different from Belle II PID variables which typically return NaN in case of error.
Abstract base class for different kinds of events.