12 #include <analysis/variables/PIDVariables.h>
14 #include <analysis/VariableManager/Manager.h>
16 #include <mdst/dataobjects/PIDLikelihood.h>
19 #include <framework/logging/Logger.h>
20 #include <framework/utilities/Conversion.h>
22 #include <framework/utilities/Conversion.h>
24 #include <boost/algorithm/string.hpp>
46 Const::ChargedStable hypothesisConversion(
const int hypothesis)
50 return Const::electron;
65 Const::PIDDetectorSet parseDetectors(
const std::vector<std::string>& arguments)
67 Const::PIDDetectorSet result;
68 for (std::string val : arguments) {
70 if (val ==
"all")
return Const::PIDDetectors::set();
71 else if (val ==
"svd") result += Const::SVD;
72 else if (val ==
"cdc") result += Const::CDC;
73 else if (val ==
"top") result += Const::TOP;
74 else if (val ==
"arich") result += Const::ARICH;
75 else if (val ==
"ecl") result += Const::ECL;
76 else if (val ==
"klm") result += Const::KLM;
77 else B2ERROR(
"Unknown detector component: " << val);
83 Const::PIDDetectorSet parseDetectorsChargedBDT(
const std::vector<std::string>& arguments)
85 Const::PIDDetectorSet result;
86 for (std::string val : arguments) {
88 if (val ==
"all")
return Const::PIDDetectors::set();
89 else if (val ==
"ecl") result += Const::ECL;
90 else B2ERROR(
"Invalid detector component: " << val <<
" for charged BDT.");
101 double particleID(
const Particle* p)
103 int pdg = abs(p->getPDGCode());
104 if (pdg == Const::electron.getPDGCode())
return electronID(p);
105 else if (pdg == Const::muon.getPDGCode())
return muonID(p);
106 else if (pdg == Const::pion.getPDGCode())
return pionID(p);
107 else if (pdg == Const::kaon.getPDGCode())
return kaonID(p);
108 else if (pdg == Const::proton.getPDGCode())
return protonID(p);
109 else if (pdg == Const::deuteron.getPDGCode())
return deuteronID(p);
110 else return std::numeric_limits<float>::quiet_NaN();
113 Manager::FunctionPtr pidLogLikelihoodValueExpert(
const std::vector<std::string>& arguments)
115 if (arguments.size() < 2) {
116 B2ERROR(
"Need at least two arguments to pidLogLikelihoodValueExpert");
121 pdgCode = Belle2::convertString<int>(arguments[0]);
122 }
catch (std::invalid_argument& e) {
123 B2ERROR(
"First argument of pidLogLikelihoodValueExpert must be a PDG code");
126 std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
128 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
129 auto hypType = Const::ChargedStable(abs(pdgCode));
131 auto func = [hypType, detectorSet](
const Particle * part) ->
double {
132 const PIDLikelihood* pid = part->getPIDLikelihood();
134 return std::numeric_limits<float>::quiet_NaN();
136 if (pid->getLogL(hypType, detectorSet) == 0)
137 return std::numeric_limits<float>::quiet_NaN();
139 return pid->getLogL(hypType, detectorSet);
146 Manager::FunctionPtr pidDeltaLogLikelihoodValueExpert(
const std::vector<std::string>& arguments)
148 if (arguments.size() < 3) {
149 B2ERROR(
"Need at least three arguments to pidDeltaLogLikelihoodValueExpert");
152 int pdgCodeHyp, pdgCodeTest;
154 pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
155 }
catch (std::invalid_argument& e) {
156 B2ERROR(
"First argument of pidDeltaLogLikelihoodValueExpert must be a PDG code");
160 pdgCodeTest = Belle2::convertString<int>(arguments[1]);
161 }
catch (std::invalid_argument& e) {
162 B2ERROR(
"Second argument of pidDeltaLogLikelihoodValueExpert must be a PDG code");
166 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
167 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
168 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
169 auto testType = Const::ChargedStable(abs(pdgCodeTest));
171 auto func = [hypType, testType, detectorSet](
const Particle * part) ->
double {
172 const PIDLikelihood* pid = part->getPIDLikelihood();
173 if (!pid)
return std::numeric_limits<float>::quiet_NaN();
175 if (pid->getLogL(hypType, detectorSet) == 0)
176 return std::numeric_limits<float>::quiet_NaN();
178 return (pid->getLogL(hypType, detectorSet) - pid->getLogL(testType, detectorSet));
184 Manager::FunctionPtr pidPairProbabilityExpert(
const std::vector<std::string>& arguments)
186 if (arguments.size() < 3) {
187 B2ERROR(
"Need at least three arguments to pidPairProbabilityExpert");
190 int pdgCodeHyp = 0, pdgCodeTest = 0;
192 pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
193 }
catch (std::invalid_argument& e) {
194 B2ERROR(
"First argument of pidPairProbabilityExpert must be PDG code");
198 pdgCodeTest = Belle2::convertString<int>(arguments[1]);
199 }
catch (std::invalid_argument& e) {
200 B2ERROR(
"Second argument of pidPairProbabilityExpert must be PDG code");
204 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
206 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
207 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
208 auto testType = Const::ChargedStable(abs(pdgCodeTest));
209 auto func = [hypType, testType, detectorSet](
const Particle * part) ->
double {
210 const PIDLikelihood* pid = part->getPIDLikelihood();
211 if (!pid)
return std::numeric_limits<float>::quiet_NaN();
213 if (pid->getLogL(hypType, detectorSet) == 0)
214 return std::numeric_limits<float>::quiet_NaN();
216 return pid->getProbability(hypType, testType, detectorSet);
222 Manager::FunctionPtr pidProbabilityExpert(
const std::vector<std::string>& arguments)
224 if (arguments.size() < 2) {
225 B2ERROR(
"Need at least two arguments for pidProbabilityExpert");
230 pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
231 }
catch (std::invalid_argument& e) {
232 B2ERROR(
"First argument of pidProbabilityExpert must be PDG code");
236 std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
237 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
238 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
241 const unsigned int n = Const::ChargedStable::c_SetSize;
243 for (
double& i : frac) i = 1.0;
245 auto func = [hypType, frac, detectorSet](
const Particle * part) ->
double {
246 const PIDLikelihood* pid = part->getPIDLikelihood();
247 if (!pid)
return std::numeric_limits<float>::quiet_NaN();
249 if (pid->getLogL(hypType, detectorSet) == 0)
250 return std::numeric_limits<float>::quiet_NaN();
252 return pid->getProbability(hypType, frac, detectorSet);
258 Manager::FunctionPtr pidMissingProbabilityExpert(
const std::vector<std::string>& arguments)
260 if (arguments.size() < 1) {
261 B2ERROR(
"Need at least one argument to pidMissingProbabilityExpert");
265 std::vector<std::string> detectors(arguments.begin(), arguments.end());
266 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
268 auto func = [detectorSet](
const Particle * part) ->
int {
269 const PIDLikelihood* pid = part->getPIDLikelihood();
270 if (not pid->isAvailable(detectorSet))
277 double electronID(
const Particle* part)
279 return Manager::Instance().getVariable(
"pidProbabilityExpert(11, CDC, TOP, ARICH, ECL, KLM)")->function(part);
282 double muonID(
const Particle* part)
284 return Manager::Instance().getVariable(
"pidProbabilityExpert(13, CDC, TOP, ARICH, ECL, KLM)")->function(part);
287 double pionID(
const Particle* part)
289 return Manager::Instance().getVariable(
"pidProbabilityExpert(211, CDC, TOP, ARICH, ECL, KLM)")->function(part);
292 double kaonID(
const Particle* part)
294 return Manager::Instance().getVariable(
"pidProbabilityExpert(321, CDC, TOP, ARICH, ECL, KLM)")->function(part);
297 double protonID(
const Particle* part)
299 return Manager::Instance().getVariable(
"pidProbabilityExpert(2212, CDC, TOP, ARICH, ECL, KLM)")->function(part);
302 double deuteronID(
const Particle* part)
304 return Manager::Instance().getVariable(
"pidProbabilityExpert(1000010020, CDC, TOP, ARICH, ECL, KLM)")->function(part);
307 double binaryPID(
const Particle* part,
const std::vector<double>& arguments)
309 if (arguments.size() != 2) {
310 B2ERROR(
"The variable binaryPID needs exactly two arguments: the PDG codes of two hypotheses.");
311 return std::numeric_limits<float>::quiet_NaN();;
313 int pdgCodeHyp = std::abs(
int(std::lround(arguments[0])));
314 int pdgCodeTest = std::abs(
int(std::lround(arguments[1])));
315 return Manager::Instance().getVariable(
"pidPairProbabilityExpert(" + std::to_string(pdgCodeHyp) +
", " + std::to_string(
316 pdgCodeTest) +
", CDC, TOP, ARICH, ECL, KLM)")->function(part);
319 double electronID_noTOP(
const Particle* part)
322 return Manager::Instance().getVariable(
"pidProbabilityExpert(11, CDC, ARICH, ECL, KLM)")->function(part);
325 double binaryPID_noTOP(
const Particle* part,
const std::vector<double>& arguments)
328 if (arguments.size() != 2) {
329 B2ERROR(
"The variable binaryPID_noTOP needs exactly two arguments: the PDG codes of two hypotheses.");
330 return std::numeric_limits<float>::quiet_NaN();;
332 int pdgCodeHyp = std::abs(
int(std::lround(arguments[0])));
333 int pdgCodeTest = std::abs(
int(std::lround(arguments[1])));
334 std::vector<int> pdgIds {pdgCodeHyp, pdgCodeTest};
335 if (std::any_of(pdgIds.begin(), pdgIds.end(), [](
int p) {return (p != Const::electron.getPDGCode());})) {
336 B2ERROR(
"The variable binaryPID_noTOP is defined only for particle hypothesis: 11.");
337 return std::numeric_limits<float>::quiet_NaN();
339 return Manager::Instance().getVariable(
"pidPairProbabilityExpert(" + std::to_string(pdgCodeHyp) +
", " + std::to_string(
340 pdgCodeTest) +
", CDC, ARICH, ECL, KLM)")->function(part);
343 double pionID_SVD(
const Particle* part)
345 return Manager::Instance().getVariable(
"formula(exp(pidLogLikelihoodValueExpert(211, ALL))/[exp(pidLogLikelihoodValueExpert(211, ALL))+exp(pidLogLikelihoodValueExpert(321, ALL))+exp(pidLogLikelihoodValueExpert(2212, ALL))])")->function(
349 double kaonID_SVD(
const Particle* part)
351 return Manager::Instance().getVariable(
"formula(exp(pidLogLikelihoodValueExpert(321, ALL))/[exp(pidLogLikelihoodValueExpert(211, ALL))+exp(pidLogLikelihoodValueExpert(321, ALL))+exp(pidLogLikelihoodValueExpert(2212, ALL))])")->function(
355 double protonID_SVD(
const Particle* part)
357 return Manager::Instance().getVariable(
"formula(exp(pidLogLikelihoodValueExpert(2212, ALL))/[exp(pidLogLikelihoodValueExpert(211, ALL))+exp(pidLogLikelihoodValueExpert(321, ALL))+exp(pidLogLikelihoodValueExpert(2212, ALL))])")->function(
361 double binaryPID_SVD(
const Particle* part,
const std::vector<double>& arguments)
363 if (arguments.size() != 2) {
364 B2ERROR(
"The variable binaryPID_SVD needs exactly two arguments: the PDG codes of two hypotheses.");
365 return std::numeric_limits<float>::quiet_NaN();
367 size_t pdgCodeHyp = std::abs(
int(std::lround(arguments[0])));
368 size_t pdgCodeTest = std::abs(
int(std::lround(arguments[1])));
369 std::vector<size_t> pdgIds {pdgCodeHyp, pdgCodeTest};
370 if (std::any_of(pdgIds.begin(), pdgIds.end(), [](
size_t p) {return (p == 11 || p == 13 || p == 1000010020);})) {
371 B2ERROR(
"The variable binaryPID_SVD is not defined for particle hypotheses {11, 13, 1000010020}.");
372 return std::numeric_limits<float>::quiet_NaN();
374 return Manager::Instance().getVariable(
"pidPairProbabilityExpert(" + std::to_string(pdgCodeHyp) +
", " + std::to_string(
375 pdgCodeTest) +
", ALL)")->function(part);
378 Manager::FunctionPtr pidChargedBDTScore(
const std::vector<std::string>& arguments)
380 if (arguments.size() != 2) {
381 B2ERROR(
"Need exactly two arguments for pidChargedBDTScore: pdgCodeHyp, detector");
387 hypPdgId = Belle2::convertString<int>(arguments.at(0));
388 }
catch (std::invalid_argument& e) {
389 B2ERROR(
"First argument of pidChargedBDTScore must be an integer (PDG code).");
392 Const::ChargedStable hypType = Const::ChargedStable(hypPdgId);
394 std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
395 Const::PIDDetectorSet detectorSet = parseDetectorsChargedBDT(detectors);
397 auto func = [hypType, detectorSet](
const Particle * part) ->
double {
398 auto name =
"pidChargedBDTScore_" + std::to_string(hypType.getPDGCode());
399 for (
size_t iDet(0); iDet < detectorSet.size(); ++iDet)
401 auto det = detectorSet[iDet];
402 name +=
"_" + std::to_string(det);
404 return (part->hasExtraInfo(name)) ? part->getExtraInfo(name) : std::numeric_limits<float>::quiet_NaN();
409 Manager::FunctionPtr pidPairChargedBDTScore(
const std::vector<std::string>& arguments)
411 if (arguments.size() != 3) {
412 B2ERROR(
"Need exactly three arguments for pidPairChargedBDTScore: pdgCodeHyp, pdgCodeTest, detector.");
416 int hypPdgId, testPdgId;
418 hypPdgId = Belle2::convertString<int>(arguments.at(0));
419 }
catch (std::invalid_argument& e) {
420 B2ERROR(
"First argument of pidPairChargedBDTScore must be an integer (PDG code).");
424 testPdgId = Belle2::convertString<int>(arguments.at(1));
425 }
catch (std::invalid_argument& e) {
426 B2ERROR(
"First argument of pidPairChargedBDTScore must be an integer (PDG code).");
429 Const::ChargedStable hypType = Const::ChargedStable(hypPdgId);
430 Const::ChargedStable testType = Const::ChargedStable(testPdgId);
432 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
433 Const::PIDDetectorSet detectorSet = parseDetectorsChargedBDT(detectors);
435 auto func = [hypType, testType, detectorSet](
const Particle * part) ->
double {
436 auto name =
"pidPairChargedBDTScore_" + std::to_string(hypType.getPDGCode()) +
"_VS_" + std::to_string(testType.getPDGCode());
437 for (
size_t iDet(0); iDet < detectorSet.size(); ++iDet)
439 auto det = detectorSet[iDet];
440 name +=
"_" + std::to_string(det);
442 return (part->hasExtraInfo(name)) ? part->getExtraInfo(name) : std::numeric_limits<float>::quiet_NaN();
447 Manager::FunctionPtr mostLikelyPDG(
const std::vector<std::string>& arguments)
449 if (arguments.size() != 0 and arguments.size() != Const::ChargedStable::c_SetSize) {
450 B2ERROR(
"Need zero or exactly " << Const::ChargedStable::c_SetSize <<
" arguments for pidMostLikelyPDG");
453 double prob[Const::ChargedStable::c_SetSize];
454 if (arguments.size() == 0) {
455 for (
unsigned int i = 0; i < Const::ChargedStable::c_SetSize; i++) prob[i] = 1. / Const::ChargedStable::c_SetSize;
457 if (arguments.size() == Const::ChargedStable::c_SetSize) {
460 for (std::string arg : arguments) {
461 prob[i++] = Belle2::convertString<float>(arg);
463 }
catch (std::invalid_argument& e) {
464 B2ERROR(
"All arguments of mostLikelyPDG must be a float number");
468 auto func = [prob](
const Particle * part) ->
double {
469 auto* pid = part->getPIDLikelihood();
470 if (!pid)
return std::numeric_limits<double>::quiet_NaN();
471 return pid->getMostLikely(prob).getPDGCode();
476 Manager::FunctionPtr isMostLikely(
const std::vector<std::string>& arguments)
478 if (arguments.size() != 0 and arguments.size() != 6) {
479 B2ERROR(
"Need zero or exactly " << Const::ChargedStable::c_SetSize <<
" arguments for pidIsMostLikely");
482 auto func = [arguments](
const Particle * part) ->
double {
483 return mostLikelyPDG(arguments)(part) == abs(part->getPDGCode());
492 double muIDBelle(
const Particle* particle)
494 const PIDLikelihood* pid = particle->getPIDLikelihood();
495 if (!pid)
return 0.5;
497 if (pid->isAvailable(Const::KLM))
498 return exp(pid->getLogL(Const::muon, Const::KLM));
503 double muIDBelleQuality(
const Particle* particle)
505 const PIDLikelihood* pid = particle->getPIDLikelihood();
508 return pid->isAvailable(Const::KLM);
511 double atcPIDBelle(
const Particle* particle,
const std::vector<double>& sigAndBkgHyp)
513 int sigHyp = int(std::lround(sigAndBkgHyp[0]));
514 int bkgHyp = int(std::lround(sigAndBkgHyp[1]));
516 const PIDLikelihood* pid = particle->getPIDLikelihood();
517 if (!pid)
return 0.5;
520 Const::PIDDetectorSet set = Const::ARICH;
521 double acc_sig = exp(pid->getLogL(hypothesisConversion(sigHyp), set));
522 double acc_bkg = exp(pid->getLogL(hypothesisConversion(bkgHyp), set));
524 if (acc_sig + acc_bkg > 0.0)
525 acc = acc_sig / (acc_sig + acc_bkg);
529 double tof_sig = exp(pid->getLogL(hypothesisConversion(sigHyp), set));
530 double tof_bkg = exp(pid->getLogL(hypothesisConversion(bkgHyp), set));
532 double tof_all = tof_sig + tof_bkg;
534 tof = tof_sig / tof_all;
535 if (tof < 0.001) tof = 0.001;
536 if (tof > 0.999) tof = 0.999;
541 double cdc_sig = exp(pid->getLogL(hypothesisConversion(sigHyp), set));
542 double cdc_bkg = exp(pid->getLogL(hypothesisConversion(bkgHyp), set));
544 double cdc_all = cdc_sig + cdc_bkg;
546 cdc = cdc_sig / cdc_all;
547 if (cdc < 0.001) cdc = 0.001;
548 if (cdc > 0.999) cdc = 0.999;
552 double pid_sig = acc * tof * cdc;
553 double pid_bkg = (1. - acc) * (1. - tof) * (1. - cdc);
555 return pid_sig / (pid_sig + pid_bkg);
559 double eIDBelle(
const Particle* part)
561 const PIDLikelihood* pid = part->getPIDLikelihood();
562 if (!pid)
return 0.5;
564 Const::PIDDetectorSet set = Const::ECL;
565 return pid->getProbability(Const::electron, Const::pion, set);
570 VARIABLE_GROUP(
"PID");
571 REGISTER_VARIABLE(
"particleID", particleID,
572 "the particle identification probability under the particle's own hypothesis, using info from all available detectors, *excluding the SVD*");
573 REGISTER_VARIABLE(
"electronID", electronID,
574 "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*");
575 REGISTER_VARIABLE(
"muonID", muonID,
576 "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*");
577 REGISTER_VARIABLE(
"pionID", pionID,
578 "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*");
579 REGISTER_VARIABLE(
"kaonID", kaonID,
580 "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*");
581 REGISTER_VARIABLE(
"protonID", protonID,
582 "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*");
583 REGISTER_VARIABLE(
"deuteronID", deuteronID,
584 "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*");
585 REGISTER_VARIABLE(
"binaryPID(pdgCode1, pdgCode2)", binaryPID,
586 "Returns the binary probability for the first provided mass hypothesis with respect to the second mass hypothesis using all detector components, *excluding the SVD*");
587 REGISTER_VARIABLE(
"binaryPID_noTOP(pdgCode1, pdgCode2)", binaryPID_noTOP,
588 "(SPECIAL (TEMP) variable) Returns the binary probability for the first provided mass hypothesis with respect to the second mass hypothesis using all detector components, *excluding the SVD and the TOP*. Note that either hypothesis in the pair *must be of an electron*.");
589 REGISTER_VARIABLE(
"electronID_noTOP", electronID_noTOP,
590 "(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*");
591 REGISTER_VARIABLE(
"pionID_SVD", pionID_SVD,
592 "pion identification probability defined as :math:`\\mathcal{L}_\\pi/(\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p+)`, using info from all available detectors, *including the SVD*");
593 REGISTER_VARIABLE(
"kaonID_SVD", kaonID_SVD,
594 "kaon identification probability defined as :math:`\\mathcal{L}_K/(\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p)`, using info from all available detectors, *including the SVD*");
595 REGISTER_VARIABLE(
"protonID_SVD", protonID_SVD,
596 "proton identification probability defined as :math:`\\mathcal{L}_p/(\\mathcal{L}_\\pi+\\mathcal{L}_K+\\mathcal{L}_p)`, using info from all available detectors, *including the SVD*");
597 REGISTER_VARIABLE(
"binaryPID_SVD(pdgCode1, pdgCode2)", binaryPID_SVD,
598 "Returns the binary probability for the first provided mass hypothesis with respect to the second mass hypothesis using all detector components, *including the SVD*. Accepted mass hypotheses are: 211 (:math:`\\pi`), 321 (:math:`K`), 2212 (:math:`p`)");
601 VARIABLE_GROUP(
"PID_expert");
602 REGISTER_VARIABLE(
"pidLogLikelihoodValueExpert(pdgCode, detectorList)", pidLogLikelihoodValueExpert,
603 "returns the log likelihood value of for a specific mass hypothesis and set of detectors.");
604 REGISTER_VARIABLE(
"pidDeltaLogLikelihoodValueExpert(pdgCode1, pdgCode2, detectorList)", pidDeltaLogLikelihoodValueExpert,
605 "returns LogL(hyp1) - LogL(hyp2) (aka DLL) for two mass hypoteses and a set of detectors.");
606 REGISTER_VARIABLE(
"pidPairProbabilityExpert(pdgCodeHyp, pdgCodeTest, detectorList)", pidPairProbabilityExpert,
607 "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}`");
608 REGISTER_VARIABLE(
"pidProbabilityExpert(pdgCodeHyp, detectorList)", pidProbabilityExpert,
609 "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}`. ");
610 REGISTER_VARIABLE(
"pidMissingProbabilityExpert(detectorList)", pidMissingProbabilityExpert,
611 "returns 1 if the PID probabiliy is missing for the provided detector list, otherwise 0. ");
612 REGISTER_VARIABLE(
"pidChargedBDTScore(pdgCodeHyp, detector)", pidChargedBDTScore,
613 "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.");
614 REGISTER_VARIABLE(
"pidPairChargedBDTScore(pdgCodeHyp, pdgCodeTest, detector)", pidPairChargedBDTScore,
615 "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.");
616 REGISTER_VARIABLE(
"pidMostLikelyPDG", mostLikelyPDG,
617 "Returns PDG code of the largest PID likelihood, or NaN if PID information is not available.");
618 REGISTER_VARIABLE(
"pidIsMostLikely", isMostLikely,
619 "Returns 1 if the PID likelihood for the particle given its PID is the largest one");
622 VARIABLE_GROUP(
"PID_belle");
623 REGISTER_VARIABLE(
"atcPIDBelle(i,j)", atcPIDBelle,
624 "returns Belle's PID atc variable: ``atc_pid(3,1,5,i,j).prob()``.\n"
625 "Parameters i,j are signal and backgroud hypothesis: (0 = electron, 1 = muon, 2 = pion, 3 = kaon, 4 = proton)");
626 REGISTER_VARIABLE(
"muIDBelle", muIDBelle,
627 "returns Belle's PID ``Muon_likelihood()`` variable.");
628 REGISTER_VARIABLE(
"muIDBelleQuality", muIDBelleQuality,
629 "returns true if Belle's PID ``Muon_likelihood()`` is usable (reliable).");
630 REGISTER_VARIABLE(
"eIDBelle", eIDBelle,
631 "returns Belle's electron ID ``eid(3,-1,5).prob()`` variable.");