Belle II Software development
PIDVariables.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9// Own header.
10#include <analysis/variables/PIDVariables.h>
11
12#include <analysis/dataobjects/Particle.h>
13#include <analysis/utility/ReferenceFrame.h>
14#include <mdst/dataobjects/PIDLikelihood.h>
15
16// framework aux
17#include <framework/logging/Logger.h>
18#include <framework/utilities/Conversion.h>
19#include <framework/gearbox/Const.h>
20
21// database
22#include <analysis/utility/PIDCalibrationWeightUtil.h>
23#include <analysis/utility/PIDNeuralNetwork.h>
24
25#include <boost/algorithm/string.hpp>
26
27#include <cmath>
28
29using namespace std;
30
31namespace Belle2 {
36 namespace Variable {
37
38 //*************
39 // Utilities
40 //*************
41
42 // converts Belle numbering scheme for charged final state particles
43 // to Belle II ChargedStable
44 Const::ChargedStable hypothesisConversion(const int hypothesis)
45 {
46 switch (hypothesis) {
47 case 0:
48 return Const::electron;
49 case 1:
50 return Const::muon;
51 case 2:
52 return Const::pion;
53 case 3:
54 return Const::kaon;
55 case 4:
56 return Const::proton;
57 }
58
59 return Const::pion;
60 }
61
62
63 Const::PIDDetectorSet parseDetectors(const std::vector<std::string>& arguments)
64 {
66 for (std::string val : arguments) {
67 boost::to_lower(val);
68 if (val == "all") return Const::PIDDetectors::set();
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);
76 }
77 return result;
78 }
79
80 // Specialisation of valid detectors parser for ChargedBDT.
81 Const::PIDDetectorSet parseDetectorsChargedBDT(const std::vector<std::string>& arguments)
82 {
84 for (std::string val : arguments) {
85 boost::to_lower(val);
86 if (val == "all") return Const::PIDDetectors::set();
87 else if (val == "ecl") result += Const::ECL;
88 else B2ERROR("Invalid detector component: " << val << " for charged BDT.");
89 }
90 return result;
91 }
92
93 //*************
94 // Belle II
95 //*************
96
97 // a "smart" variable:
98 // finds the global probability based on the PDG code of the input particle
99 double particleID(const Particle* p)
100 {
101 int pdg = abs(p->getPDGCode());
102 if (pdg == Const::electron.getPDGCode()) return electronID(p);
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);
107 else if (pdg == Const::deuteron.getPDGCode()) return deuteronID(p);
108 else return Const::doubleNaN;
109 }
110
111 bool isPIDAvailable(const Particle* part)
112 {
113 const auto* pid = part->getPIDLikelihood();
114 if (not pid) return false;
115 return pid->isAvailable();
116 }
117
118 Manager::FunctionPtr isPIDAvailableFrom(const std::vector<std::string>& arguments)
119 {
120 Const::PIDDetectorSet detectorSet = parseDetectors(arguments);
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);
125 };
126 return func;
127 }
128
129 Manager::FunctionPtr pidLogLikelihoodValueExpert(const std::vector<std::string>& arguments)
130 {
131 if (arguments.size() < 2) {
132 B2ERROR("Need at least two arguments to pidLogLikelihoodValueExpert");
133 return nullptr;
134 }
135 int pdgCode;
136 try {
137 pdgCode = Belle2::convertString<int>(arguments[0]);
138 } catch (std::invalid_argument& e) {
139 B2ERROR("First argument of pidLogLikelihoodValueExpert must be a PDG code");
140 return nullptr;
141 }
142 std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
143
144 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
145 auto hypType = Const::ChargedStable(abs(pdgCode));
146
147 auto func = [hypType, detectorSet](const Particle * part) -> double {
148 const PIDLikelihood* pid = part->getPIDLikelihood();
149 if (!pid)
150 return Const::doubleNaN;
151 // No information from any subdetector in the list
152 if (not pid->isAvailable(detectorSet)) return Const::doubleNaN;
153
154 return pid->getLogL(hypType, detectorSet);
155 };
156 return func;
157 }
158
159
160 Manager::FunctionPtr pidDeltaLogLikelihoodValueExpert(const std::vector<std::string>& arguments)
161 {
162 if (arguments.size() < 3) {
163 B2ERROR("Need at least three arguments to pidDeltaLogLikelihoodValueExpert");
164 return nullptr;
165 }
166 int pdgCodeHyp, pdgCodeTest;
167 try {
168 pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
169 } catch (std::invalid_argument& e) {
170 B2ERROR("First argument of pidDeltaLogLikelihoodValueExpert must be a PDG code");
171 return nullptr;
172 }
173 try {
174 pdgCodeTest = Belle2::convertString<int>(arguments[1]);
175 } catch (std::invalid_argument& e) {
176 B2ERROR("Second argument of pidDeltaLogLikelihoodValueExpert must be a PDG code");
177 return nullptr;
178 }
179
180 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
181 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
182 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
183 auto testType = Const::ChargedStable(abs(pdgCodeTest));
184
185 auto func = [hypType, testType, detectorSet](const Particle * part) -> double {
186 const PIDLikelihood* pid = part->getPIDLikelihood();
187 if (!pid) return Const::doubleNaN;
188 // No information from any subdetector in the list
189 if (not pid->isAvailable(detectorSet)) return Const::doubleNaN;
190
191 return pid->getDeltaLogL(hypType, testType, detectorSet);
192 };
193 return func;
194 }
195
196
197 Manager::FunctionPtr pidPairProbabilityExpert(const std::vector<std::string>& arguments)
198 {
199 if (arguments.size() < 3) {
200 B2ERROR("Need at least three arguments to pidPairProbabilityExpert");
201 return nullptr;
202 }
203 int pdgCodeHyp = 0, pdgCodeTest = 0;
204 try {
205 pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
206 } catch (std::invalid_argument& e) {
207 B2ERROR("First argument of pidPairProbabilityExpert must be PDG code");
208 return nullptr;
209 }
210 try {
211 pdgCodeTest = Belle2::convertString<int>(arguments[1]);
212 } catch (std::invalid_argument& e) {
213 B2ERROR("Second argument of pidPairProbabilityExpert must be PDG code");
214 return nullptr;
215 }
216
217 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
218
219 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
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();
224 if (!pid) return Const::doubleNaN;
225 // No information from any subdetector in the list
226 if (not pid->isAvailable(detectorSet)) return Const::doubleNaN;
227
228 return pid->getProbability(hypType, testType, detectorSet);
229 };
230 return func;
231 }
232
233
234 Manager::FunctionPtr pidProbabilityExpert(const std::vector<std::string>& arguments)
235 {
236 if (arguments.size() < 2) {
237 B2ERROR("Need at least two arguments for pidProbabilityExpert");
238 return nullptr;
239 }
240 int pdgCodeHyp = 0;
241 try {
242 pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
243 } catch (std::invalid_argument& e) {
244 B2ERROR("First argument of pidProbabilityExpert must be PDG code");
245 return nullptr;
246 }
247
248 std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
249 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
250 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
251
252 // Placeholder for the priors
253 const unsigned int n = Const::ChargedStable::c_SetSize;
254 double frac[n];
255 for (double& i : frac) i = 1.0; // flat priors
256
257 auto func = [hypType, frac, detectorSet](const Particle * part) -> double {
258 const PIDLikelihood* pid = part->getPIDLikelihood();
259 if (!pid) return Const::doubleNaN;
260 // No information from any subdetector in the list
261 if (not pid->isAvailable(detectorSet)) return Const::doubleNaN;
262
263 return pid->getProbability(hypType, frac, detectorSet);
264 };
265 return func;
266 }
267
268
269 Manager::FunctionPtr pidLogarithmicProbabilityExpert(const std::vector<std::string>& arguments)
270 {
271 if (arguments.size() < 2) {
272 B2ERROR("Need at least two arguments for pidLogarithmicProbabilityExpert");
273 return nullptr;
274 }
275 int pdgCodeHyp = 0;
276 try {
277 pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
278 } catch (std::invalid_argument& e) {
279 B2ERROR("First argument of pidLogarithmicProbabilityExpert must be PDG code");
280 return nullptr;
281 }
282
283 std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
284 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
285 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
286
287 // Placeholder for the priors
288 const unsigned int n = Const::ChargedStable::c_SetSize;
289 double frac[n];
290 for (double& i : frac) i = 1.0; // flat priors
291
292 auto func = [hypType, frac, detectorSet](const Particle * part) -> double {
293 const auto* pid = part->getPIDLikelihood();
294 if (not pid) return Const::doubleNaN;
295 if (not pid->isAvailable(detectorSet)) return Const::doubleNaN;
296 return pid->getLogarithmicProbability(hypType, frac, detectorSet);
297 };
298 return func;
299 }
300
301
302 Manager::FunctionPtr pidMissingProbabilityExpert(const std::vector<std::string>& arguments)
303 {
304 if (arguments.size() < 1) {
305 B2ERROR("Need at least one argument to pidMissingProbabilityExpert");
306 return nullptr;
307 }
308
309 std::vector<std::string> detectors(arguments.begin(), arguments.end());
310 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
311
312 auto func = [detectorSet](const Particle * part) -> double {
313 const PIDLikelihood* pid = part->getPIDLikelihood();
314 if (!pid) return Const::doubleNaN;
315 if (not pid->areAllAvailable(detectorSet)) return 1; // to keep the same behaviour as in previous releases
316 else return 0;
317 };
318 return func;
319 }
320
321 Manager::FunctionPtr pidWeightedLogLikelihoodValueExpert(const std::vector<std::string>& arguments)
322 {
323 if (arguments.size() < 3) {
324 B2ERROR("Need at least three arguments to pidWeightedLogLikelihoodValueExpert");
325 return nullptr;
326 }
327 std::string matrixName = arguments[0];
328
329 int pdgCode;
330 try {
331 pdgCode = Belle2::convertString<int>(arguments[1]);
332 } catch (std::invalid_argument& e) {
333 B2ERROR("Second argument of pidWeightedLogLikelihoodValueExpert must be a PDG code");
334 return nullptr;
335 }
336 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
337 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
338 auto hypType = Const::ChargedStable(abs(pdgCode));
339
340 auto func = [hypType, detectorSet, matrixName](const Particle * part) -> double {
341 PIDCalibrationWeightUtil weightMatrix(matrixName);
342 const PIDLikelihood* pid = part->getPIDLikelihood();
343 if (!pid)
344 return Const::doubleNaN;
345 // No information from any subdetector in the list
346 if (not pid->isAvailable(detectorSet)) return Const::doubleNaN;
347
348 const auto& frame = ReferenceFrame::GetCurrent();
349 auto mom = frame.getMomentum(part);
350 auto p = mom.P();
351 auto theta = mom.Theta();
352
353 double LogL = 0;
354 for (const Const::EDetector& detector : Const::PIDDetectorSet::set())
355 {
356 if (detectorSet.contains(detector))
357 LogL += pid->getLogL(hypType, detector) * weightMatrix.getWeight(hypType.getPDGCode(), detector, p, theta);
358 }
359 return LogL;
360 };
361
362 return func;
363 }
364
365 Manager::FunctionPtr pidWeightedProbabilityExpert(const std::vector<std::string>& arguments)
366 {
367 if (arguments.size() < 3) {
368 B2ERROR("Need at least three arguments for pidWeightedProbabilityExpert");
369 return nullptr;
370 }
371 std::string matrixName = arguments[0];
372
373 int pdgCodeHyp = 0;
374 try {
375 pdgCodeHyp = Belle2::convertString<int>(arguments[1]);
376 } catch (std::invalid_argument& e) {
377 B2ERROR("Second argument of pidWeightedProbabilityExpert must be PDG code");
378 return nullptr;
379 }
380
381 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
382 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
383 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
384
385 auto func = [hypType, detectorSet, matrixName](const Particle * part) -> double {
386 PIDCalibrationWeightUtil weightMatrix(matrixName);
387 const PIDLikelihood* pid = part->getPIDLikelihood();
388 if (!pid) return Const::doubleNaN;
389 // No information from any subdetector in the list
390 if (not pid->isAvailable(detectorSet)) return Const::doubleNaN;
391
392 const auto& frame = ReferenceFrame::GetCurrent();
393 auto mom = frame.getMomentum(part);
394 auto p = mom.P();
395 auto theta = mom.Theta();
396
397 std::vector<double> LogL(Const::ChargedStable::c_SetSize);
398 double LogL_max = 0;
399 bool hasMax = false;
400 for (const auto& pdgIter : Const::chargedStableSet)
401 {
402 const int index_pdg = pdgIter.getIndex();
403
404 LogL[index_pdg] = 0;
405 for (const Const::EDetector& detector : Const::PIDDetectorSet::set()) {
406 if (detectorSet.contains(detector))
407 LogL[index_pdg] += pid->getLogL(pdgIter, detector) * weightMatrix.getWeight(pdgIter.getPDGCode(), detector, p, theta);
408 }
409
410 if (!hasMax || (LogL[index_pdg] > LogL_max)) {
411 LogL_max = LogL[index_pdg];
412 hasMax = true;
413 }
414 }
415
416 double norm = 0;
417 for (auto LogL_i : LogL)
418 norm += exp(LogL_i - LogL_max);
419
420 if (norm > 0)
421 return exp(LogL[hypType.getIndex()] - LogL_max) / norm;
422 else
423 return -1;
424 };
425 return func;
426 }
427
428
429 Manager::FunctionPtr pidNeuralNetworkValueExpert(const std::vector<std::string>& arguments)
430 {
431 if (arguments.size() == 0) {
432 B2ERROR("Need pdg code for pidNeuralNetworkValueExpert");
433 return nullptr;
434 }
435 if (arguments.size() > 2) {
436 B2ERROR("pidNeuralNetworkValueExpert expects at most two arguments, i.e. the pdg code and the pidNeuralNetworkName");
437 return nullptr;
438 }
439 int pdgCode;
440 try {
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");
444 return nullptr;
445 }
446
447 std::shared_ptr<PIDNeuralNetwork> neuralNetworkPtr;
448 if (arguments.size() == 2) {
449 std::string parameterSetName = arguments[1];
450 neuralNetworkPtr = std::make_shared<PIDNeuralNetwork>(parameterSetName);
451 } else {
452 neuralNetworkPtr = std::make_shared<PIDNeuralNetwork>();
453 }
454
455 neuralNetworkPtr->hasPdgCode(pdgCode, true); // raise exception if pdg code is not predicted
456
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);
461
462 const PIDLikelihood* pid = part->getPIDLikelihood();
463 if (not pid) return Const::doubleNaN;
464 if (not pid->isAvailable()) return Const::doubleNaN;
465
466 // collect only those inputs needed for the neural network in the correct order
467 std::vector<float> inputsNN;
468 inputsNN.reserve(neuralNetworkPtr->getInputSize());
469 for (const auto& inputName : neuralNetworkPtr->getInputBasf2Names())
470 inputsNN.push_back(std::get<double>(Variable::Manager::Instance().getVariable(inputName)->function(part)));
471
472 const auto probabilities = neuralNetworkPtr->predict(inputsNN);
473
474 // store all probabilities for all hypotheses in extraInfo
475 for (const auto element : probabilities)
476 {
477 const auto [pdgCodeElement, probability] = element;
478 const_cast<Particle*>(part)->addExtraInfo(neuralNetworkPtr->getExtraInfoName(pdgCodeElement), probability);
479 }
480
481 return probabilities.at(pdgCode);
482 };
483
484 return func;
485 }
486
487
488 Manager::FunctionPtr pidWeightedPairProbabilityExpert(const std::vector<std::string>& arguments)
489 {
490 if (arguments.size() < 4) {
491 B2ERROR("Need at least four arguments to pidWeightedPairProbabilityExpert");
492 return nullptr;
493 }
494 std::string matrixName = arguments[0];
495
496 int pdgCodeHyp = 0, pdgCodeTest = 0;
497 try {
498 pdgCodeHyp = Belle2::convertString<int>(arguments[1]);
499 } catch (std::invalid_argument& e) {
500 B2ERROR("Second argument of pidWeightedPairProbabilityExpert must be PDG code");
501 return nullptr;
502 }
503 try {
504 pdgCodeTest = Belle2::convertString<int>(arguments[2]);
505 } catch (std::invalid_argument& e) {
506 B2ERROR("Third argument of pidWeightedPairProbabilityExpert must be PDG code");
507 return nullptr;
508 }
509
510 std::vector<std::string> detectors(arguments.begin() + 3, arguments.end());
511
512 Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
513 auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
514 auto testType = Const::ChargedStable(abs(pdgCodeTest));
515
516 auto func = [hypType, testType, detectorSet, matrixName](const Particle * part) -> double {
517 PIDCalibrationWeightUtil weightMatrix(matrixName);
518
519 const PIDLikelihood* pid = part->getPIDLikelihood();
520 if (!pid) return Const::doubleNaN;
521 // No information from any subdetector in the list
522 if (not pid->isAvailable(detectorSet)) return Const::doubleNaN;
523
524 const auto& frame = ReferenceFrame::GetCurrent();
525 auto mom = frame.getMomentum(part);
526 auto p = mom.P();
527 auto theta = mom.Theta();
528
529 double LogL_hypType(0), LogL_testType(0);
530 for (const Const::EDetector& detector : Const::PIDDetectorSet::set())
531 {
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);
535 }
536 }
537
538 double deltaLogL = LogL_testType - LogL_hypType;
539 double res;
540 if (deltaLogL < 0)
541 {
542 double eLogL = exp(deltaLogL);
543 res = 1. / (1. + eLogL);
544 } else
545 {
546 double eLogL = exp(-deltaLogL);
547 res = eLogL / (1.0 + eLogL);
548 }
549
550 if (std::isfinite(res))
551 return res;
552
553 return 0;
554 };
555 return func;
556 }
557
558 double electronID(const Particle* part)
559 {
560 static Manager::FunctionPtr pidFunction =
561 pidProbabilityExpert({"11", "ALL"});
562 return std::get<double>(pidFunction(part));
563 }
564
565 double muonID(const Particle* part)
566 {
567 static Manager::FunctionPtr pidFunction =
568 pidProbabilityExpert({"13", "ALL"});
569 return std::get<double>(pidFunction(part));
570 }
571
572 double pionID(const Particle* part)
573 {
574 static Manager::FunctionPtr pidFunction =
575 pidProbabilityExpert({"211", "ALL"});
576 return std::get<double>(pidFunction(part));
577 }
578
579 double kaonID(const Particle* part)
580 {
581 static Manager::FunctionPtr pidFunction =
582 pidProbabilityExpert({"321", "ALL"});
583 return std::get<double>(pidFunction(part));
584 }
585
586 double protonID(const Particle* part)
587 {
588 static Manager::FunctionPtr pidFunction =
589 pidProbabilityExpert({"2212", "ALL"});
590 return std::get<double>(pidFunction(part));
591 }
592
593 double deuteronID(const Particle* part)
594 {
595 static Manager::FunctionPtr pidFunction =
596 pidProbabilityExpert({"1000010020", "ALL"});
597 return std::get<double>(pidFunction(part));
598 }
599
600 double binaryPID(const Particle* part, const std::vector<double>& arguments)
601 {
602 if (arguments.size() != 2) {
603 B2ERROR("The variable binaryPID needs exactly two arguments: the PDG codes of two hypotheses.");
604 return Const::doubleNaN;;
605 }
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));
611 }
612
613 double electronID_noSVD(const Particle* part)
614 {
615 // Excluding SVD for electron ID. This variable is temporary. BII-8760
616 static Manager::FunctionPtr pidFunction =
617 pidProbabilityExpert({"11", "CDC", "TOP", "ARICH", "ECL", "KLM"});
618 return std::get<double>(pidFunction(part));
619 }
620
621 double muonID_noSVD(const Particle* part)
622 {
623 // Excluding SVD for muon ID. This variable is temporary. BII-8760
624 static Manager::FunctionPtr pidFunction =
625 pidProbabilityExpert({"13", "CDC", "TOP", "ARICH", "ECL", "KLM"});
626 return std::get<double>(pidFunction(part));
627 }
628
629 double pionID_noSVD(const Particle* part)
630 {
631 // Excluding SVD for pion ID. This variable is temporary. BII-8760
632 static Manager::FunctionPtr pidFunction =
633 pidProbabilityExpert({"211", "CDC", "TOP", "ARICH", "ECL", "KLM"});
634 return std::get<double>(pidFunction(part));
635 }
636
637 double kaonID_noSVD(const Particle* part)
638 {
639 // Excluding SVD for kaon ID. This variable is temporary. BII-8760
640 static Manager::FunctionPtr pidFunction =
641 pidProbabilityExpert({"321", "CDC", "TOP", "ARICH", "ECL", "KLM"});
642 return std::get<double>(pidFunction(part));
643 }
644
645 double protonID_noSVD(const Particle* part)
646 {
647 // Excluding SVD for proton ID. This variable is temporary. BII-8760
648 static Manager::FunctionPtr pidFunction =
649 pidProbabilityExpert({"2212", "CDC", "TOP", "ARICH", "ECL", "KLM"});
650 return std::get<double>(pidFunction(part));
651 }
652
653 double deuteronID_noSVD(const Particle* part)
654 {
655 // Excluding SVD for deuteron ID. This variable is temporary. BII-8760
656 static Manager::FunctionPtr pidFunction =
657 pidProbabilityExpert({"1000010020", "CDC", "TOP", "ARICH", "ECL", "KLM"});
658 return std::get<double>(pidFunction(part));
659 }
660
661 double binaryPID_noSVD(const Particle* part, const std::vector<double>& arguments)
662 {
663 // Excluding SVD for binary ID. This variable is temporary. BII-8760
664 if (arguments.size() != 2) {
665 B2ERROR("The variable binaryPID_noSVD needs exactly two arguments: the PDG codes of two hypotheses.");
666 return Const::doubleNaN;;
667 }
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));
673 }
674
675 double electronID_noTOP(const Particle* part)
676 {
677 // Excluding TOP for electron ID. This variable is temporary. BII-8444
678 static Manager::FunctionPtr pidFunction =
679 pidProbabilityExpert({"11", "SVD", "CDC", "ARICH", "ECL", "KLM"});
680 return std::get<double>(pidFunction(part));
681 }
682
683 double binaryElectronID_noTOP(const Particle* part, const std::vector<double>& arguments)
684 {
685 // Excluding TOP for electron ID. This is temporary. BII-8444
686 if (arguments.size() != 1) {
687 B2ERROR("The variable binaryElectronID_noTOP needs exactly one argument: the PDG code of the test hypothesis.");
688 return Const::doubleNaN;;
689 }
690
691 int pdgCodeHyp = Const::electron.getPDGCode();
692 int pdgCodeTest = std::abs(int(std::lround(arguments[0])));
693
694 const auto var = "pidPairProbabilityExpert(" + std::to_string(pdgCodeHyp) + ", " +
695 std::to_string(pdgCodeTest) + ", SVD, CDC, ARICH, ECL, KLM)";
696
697 return std::get<double>(Manager::Instance().getVariable(var)->function(part));
698 }
699
700 double electronID_noSVD_noTOP(const Particle* part)
701 {
702 // Excluding SVD and TOP for electron ID. This variable is temporary. BII-8444, BII-8760.
703 static Manager::FunctionPtr pidFunction =
704 pidProbabilityExpert({"11", "CDC", "ARICH", "ECL", "KLM"});
705 return std::get<double>(pidFunction(part));
706 }
707
708 double binaryElectronID_noSVD_noTOP(const Particle* part, const std::vector<double>& arguments)
709 {
710 // Excluding SVD and TOP for electron ID. This is temporary. BII-8444, BII-8760.
711 if (arguments.size() != 1) {
712 B2ERROR("The variable binaryElectronID_noSVD_noTOP needs exactly one argument: the PDG code of the test hypothesis.");
713 return Const::doubleNaN;;
714 }
715
716 int pdgCodeHyp = Const::electron.getPDGCode();
717 int pdgCodeTest = std::abs(int(std::lround(arguments[0])));
718
719 const auto var = "pidPairProbabilityExpert(" + std::to_string(pdgCodeHyp) + ", " +
720 std::to_string(pdgCodeTest) + ", CDC, ARICH, ECL, KLM)";
721
722 return std::get<double>(Manager::Instance().getVariable(var)->function(part));
723 }
724
725
726 double pionID_noARICHwoECL(const Particle* part)
727 {
728 // remove arich if no ecl cluster + identified as kaon in arich
729 const ECLCluster* cluster = part->getECLCluster();
730 if (!cluster) {
731 const PIDLikelihood* pid = part->getPIDLikelihood();
732 if (!pid) return Const::doubleNaN;
733 if (pid->getDeltaLogL(Const::kaon, Const::pion, Const::ARICH) > 0) {
734 static Manager::FunctionPtr pidFunction =
735 pidProbabilityExpert({"211", "SVD", "CDC", "TOP", "ECL", "KLM"});
736 return std::get<double>(pidFunction(part));
737 }
738 }
739 return pionID(part);
740 }
741
742
743 double kaonID_noARICHwoECL(const Particle* part)
744 {
745 // remove arich if no ecl cluster + identified as kaon in arich
746 const ECLCluster* cluster = part->getECLCluster();
747 if (!cluster) {
748 const PIDLikelihood* pid = part->getPIDLikelihood();
749 if (!pid) return Const::doubleNaN;
750 if (pid->getDeltaLogL(Const::kaon, Const::pion, Const::ARICH) > 0) {
751 static Manager::FunctionPtr pidFunction =
752 pidProbabilityExpert({"321", "SVD", "CDC", "TOP", "ECL", "KLM"});
753 return std::get<double>(pidFunction(part));
754 }
755 }
756 return kaonID(part);
757 }
758
759
760 double binaryPID_noARICHwoECL(const Particle* part, const std::vector<double>& arguments)
761 {
762 // Excluding ARICH for tracks without ECL cluster and identified as heavier of the two hypotheses from binary ID.
763 if (arguments.size() != 2) {
764 B2ERROR("The variable binaryPID_noARICHwoECL needs exactly two arguments: the PDG codes of two hypotheses.");
765 return Const::doubleNaN;;
766 }
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));
771
772 const ECLCluster* cluster = part->getECLCluster();
773 if (!cluster) {
774 const PIDLikelihood* pid = part->getPIDLikelihood();
775 if (!pid) return Const::doubleNaN;
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));
781 }
782 }
783
784 return binaryPID(part, arguments);
785
786 }
787
788
789
790 double antineutronID(const Particle* particle)
791 {
792 if (particle->hasExtraInfo("nbarID")) {
793 return particle->getExtraInfo("nbarID");
794 } else {
795 if (particle->getPDGCode() == -Const::neutron.getPDGCode()) {
796 B2WARNING("The extraInfo nbarID is not registered! \n"
797 "Please use function getNbarIDMVA in modularAnalysis.");
798 }
799 return Const::doubleNaN;
800 }
801 }
802
803 Manager::FunctionPtr pidChargedBDTScore(const std::vector<std::string>& arguments)
804 {
805 if (arguments.size() != 2) {
806 B2ERROR("Need exactly two arguments for pidChargedBDTScore: pdgCodeHyp, detector");
807 return nullptr;
808 }
809
810 int hypPdgId;
811 try {
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).");
815 return nullptr;
816 }
817 Const::ChargedStable hypType = Const::ChargedStable(hypPdgId);
818
819 std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
820 Const::PIDDetectorSet detectorSet = parseDetectorsChargedBDT(detectors);
821
822 auto func = [hypType, detectorSet](const Particle * part) -> double {
823 auto name = "pidChargedBDTScore_" + std::to_string(hypType.getPDGCode());
824 for (const Const::EDetector& detector : detectorSet)
825 {
826 name += "_" + std::to_string(detector);
827 }
828 return (part->hasExtraInfo(name)) ? part->getExtraInfo(name) : Const::doubleNaN;
829 };
830 return func;
831 }
832
833 Manager::FunctionPtr pidPairChargedBDTScore(const std::vector<std::string>& arguments)
834 {
835 if (arguments.size() != 3) {
836 B2ERROR("Need exactly three arguments for pidPairChargedBDTScore: pdgCodeHyp, pdgCodeTest, detector.");
837 return nullptr;
838 }
839
840 int hypPdgId, testPdgId;
841 try {
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).");
845 return nullptr;
846 }
847 try {
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).");
851 return nullptr;
852 }
853 Const::ChargedStable hypType = Const::ChargedStable(hypPdgId);
854 Const::ChargedStable testType = Const::ChargedStable(testPdgId);
855
856 std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
857 Const::PIDDetectorSet detectorSet = parseDetectorsChargedBDT(detectors);
858
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());
861 for (const Const::EDetector& detector : detectorSet)
862 {
863 name += "_" + std::to_string(detector);
864 }
865 return (part->hasExtraInfo(name)) ? part->getExtraInfo(name) : Const::doubleNaN;
866 };
867 return func;
868 }
869
870 double mostLikelyPDG(const Particle* part, const std::vector<double>& arguments)
871 {
872 if (arguments.size() != 0 and arguments.size() != Const::ChargedStable::c_SetSize) {
873 B2ERROR("Need zero or exactly " << Const::ChargedStable::c_SetSize << " arguments for pidMostLikelyPDG");
874 return Const::doubleNaN;
875 }
877 if (arguments.size() == 0) {
878 for (unsigned int i = 0; i < Const::ChargedStable::c_SetSize; i++) prob[i] = 1. / Const::ChargedStable::c_SetSize;
879 } else {
880 copy(arguments.begin(), arguments.end(), prob);
881 }
882
883 auto* pid = part->getPIDLikelihood();
884 if (!pid) return Const::doubleNaN;
885 return pid->getMostLikely(prob).getPDGCode();
886 }
887
888 bool isMostLikely(const Particle* part, const std::vector<double>& arguments)
889 {
890 if (arguments.size() != 0 and arguments.size() != Const::ChargedStable::c_SetSize) {
891 B2ERROR("Need zero or exactly " << Const::ChargedStable::c_SetSize << " arguments for pidIsMostLikely");
892 return false;
893 }
894 return mostLikelyPDG(part, arguments) == abs(part->getPDGCode());
895 }
896
897 Manager::FunctionPtr weightedElectronID(const std::vector<std::string>& arguments)
898 {
899 std::string varName;
900 if (arguments.size() == 0) {
901 varName = "pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 11, ALL)";
902 } else if (arguments.size() == 1) {
903 varName = "pidWeightedProbabilityExpert(" + arguments[0] + ", 11, ALL)";
904 } else {
905 B2ERROR("Need zero or one argument for weightedElectronID");
906 return nullptr;
907 }
908
909 const Variable::Manager::Var* var = Manager::Instance().getVariable(varName);
910 auto func = [var](const Particle * particle) -> double {
911 return std::get<double>(var->function(particle));
912 };
913 return func;
914 };
915
916 Manager::FunctionPtr weightedMuonID(const std::vector<std::string>& arguments)
917 {
918 std::string varName;
919 if (arguments.size() == 0) {
920 varName = "pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 13, ALL)";
921 } else if (arguments.size() == 1) {
922 varName = "pidWeightedProbabilityExpert(" + arguments[0] + ", 13, ALL)";
923 } else {
924 B2ERROR("Need zero or one argument for weightedMuonID");
925 return nullptr;
926 }
927
928 const Variable::Manager::Var* var = Manager::Instance().getVariable(varName);
929 auto func = [var](const Particle * particle) -> double {
930 return std::get<double>(var->function(particle));
931 };
932 return func;
933 };
934
935 Manager::FunctionPtr weightedPionID(const std::vector<std::string>& arguments)
936 {
937 std::string varName;
938 if (arguments.size() == 0) {
939 varName = "pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 211, ALL)";
940 } else if (arguments.size() == 1) {
941 varName = "pidWeightedProbabilityExpert(" + arguments[0] + ", 211, ALL)";
942 } else {
943 B2ERROR("Need zero or one argument for weightedPionID");
944 return nullptr;
945 }
946
947 const Variable::Manager::Var* var = Manager::Instance().getVariable(varName);
948 auto func = [var](const Particle * particle) -> double {
949 return std::get<double>(var->function(particle));
950 };
951 return func;
952 };
953
954 Manager::FunctionPtr weightedKaonID(const std::vector<std::string>& arguments)
955 {
956 std::string varName;
957 if (arguments.size() == 0) {
958 varName = "pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 321, ALL)";
959 } else if (arguments.size() == 1) {
960 varName = "pidWeightedProbabilityExpert(" + arguments[0] + ", 321, ALL)";
961 } else {
962 B2ERROR("Need zero or one argument for weightedKaonID");
963 return nullptr;
964 }
965
966 const Variable::Manager::Var* var = Manager::Instance().getVariable(varName);
967 auto func = [var](const Particle * particle) -> double {
968 return std::get<double>(var->function(particle));
969 };
970 return func;
971 };
972
973 Manager::FunctionPtr weightedProtonID(const std::vector<std::string>& arguments)
974 {
975 std::string varName;
976 if (arguments.size() == 0) {
977 varName = "pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 2212, ALL)";
978 } else if (arguments.size() == 1) {
979 varName = "pidWeightedProbabilityExpert(" + arguments[0] + ", 2212, ALL)";
980 } else {
981 B2ERROR("Need zero or one argument for weightedProtonID");
982 return nullptr;
983 }
984
985 const Variable::Manager::Var* var = Manager::Instance().getVariable(varName);
986 auto func = [var](const Particle * particle) -> double {
987 return std::get<double>(var->function(particle));
988 };
989 return func;
990 };
991
992 Manager::FunctionPtr weightedDeuteronID(const std::vector<std::string>& arguments)
993 {
994 std::string varName;
995 if (arguments.size() == 0) {
996 varName = "pidWeightedProbabilityExpert(PIDCalibrationWeightMatrix, 1000010020, ALL)";
997 } else if (arguments.size() == 1) {
998 varName = "pidWeightedProbabilityExpert(" + arguments[0] + ", 1000010020, ALL)";
999 } else {
1000 B2ERROR("Need zero or one argument for weightedDeuteronID");
1001 return nullptr;
1002 }
1003
1004 const Variable::Manager::Var* var = Manager::Instance().getVariable(varName);
1005 auto func = [var](const Particle * particle) -> double {
1006 return std::get<double>(var->function(particle));
1007 };
1008 return func;
1009 };
1010
1011
1012 double electronIDNN(const Particle* particle)
1013 {
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));
1018 }
1019
1020 double muonIDNN(const Particle* particle)
1021 {
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));
1026 }
1027
1028 double pionIDNN(const Particle* particle)
1029 {
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));
1034 }
1035
1036 double kaonIDNN(const Particle* particle)
1037 {
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));
1042 }
1043
1044 double protonIDNN(const Particle* particle)
1045 {
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));
1050 }
1051
1052 double deuteronIDNN(const Particle* particle)
1053 {
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));
1058 }
1059
1060
1061 double klmMuonIDDNN(const Particle* part)
1062 {
1063 const PIDLikelihood* pid = part->getPIDLikelihood();
1064 if (!pid) return Const::doubleNaN;
1065 double klmMuonIDDNNvalue = pid->getPreOfficialLikelihood("klmMuonIDDNN");
1066 // klmMuonIDDNNvalue == -1.0 means there is no valid output from KLMMuonIDDNNExpertModule
1067 if (klmMuonIDDNNvalue < 0.0) return Const::doubleNaN;
1068 return klmMuonIDDNNvalue;
1069 }
1070
1071 //*************
1072 // B2BII
1073 //*************
1074
1075 double muIDBelle(const Particle* particle)
1076 {
1077 const PIDLikelihood* pid = particle->getPIDLikelihood();
1078 if (!pid) return 0.5; // Belle standard
1079
1080 if (pid->isAvailable(Const::KLM))
1081 return exp(pid->getLogL(Const::muon, Const::KLM));
1082 else
1083 return 0; // Belle standard
1084 }
1085
1086 double muIDBelleQuality(const Particle* particle)
1087 {
1088 const PIDLikelihood* pid = particle->getPIDLikelihood();
1089 if (!pid) return 0;// Belle standard
1090
1091 return pid->isAvailable(Const::KLM);
1092 }
1093
1094 double atcPIDBelle(const Particle* particle, const std::vector<double>& sigAndBkgHyp)
1095 {
1096 int sigHyp = int(std::lround(sigAndBkgHyp[0]));
1097 int bkgHyp = int(std::lround(sigAndBkgHyp[1]));
1098
1099 const PIDLikelihood* pid = particle->getPIDLikelihood();
1100 if (!pid) return 0.5; // Belle standard
1101
1102 // ACC = ARICH
1103 Const::PIDDetectorSet set = Const::ARICH;
1104 double acc_sig = exp(pid->getLogL(hypothesisConversion(sigHyp), set));
1105 double acc_bkg = exp(pid->getLogL(hypothesisConversion(bkgHyp), set));
1106 double acc = 0.5; // Belle standard
1107 if (acc_sig + acc_bkg > 0.0)
1108 acc = acc_sig / (acc_sig + acc_bkg);
1109
1110 // TOF = TOP
1111 set = Const::TOP;
1112 double tof_sig = exp(pid->getLogL(hypothesisConversion(sigHyp), set));
1113 double tof_bkg = exp(pid->getLogL(hypothesisConversion(bkgHyp), set));
1114 double tof = 0.5; // Belle standard
1115 double tof_all = tof_sig + tof_bkg;
1116 if (tof_all != 0) {
1117 tof = tof_sig / tof_all;
1118 if (tof < 0.001) tof = 0.001;
1119 if (tof > 0.999) tof = 0.999;
1120 }
1121
1122 // dE/dx = CDC
1123 set = Const::CDC;
1124 double cdc_sig = exp(pid->getLogL(hypothesisConversion(sigHyp), set));
1125 double cdc_bkg = exp(pid->getLogL(hypothesisConversion(bkgHyp), set));
1126 double cdc = 0.5; // Belle standard
1127 double cdc_all = cdc_sig + cdc_bkg;
1128 if (cdc_all != 0) {
1129 cdc = cdc_sig / cdc_all;
1130 if (cdc < 0.001) cdc = 0.001;
1131 if (cdc > 0.999) cdc = 0.999;
1132 }
1133
1134 // Combined
1135 double pid_sig = acc * tof * cdc;
1136 double pid_bkg = (1. - acc) * (1. - tof) * (1. - cdc);
1137
1138 return pid_sig / (pid_sig + pid_bkg);
1139 }
1140
1141
1142 double eIDBelle(const Particle* part)
1143 {
1144 const PIDLikelihood* pid = part->getPIDLikelihood();
1145 if (!pid) return 0.5; // Belle standard
1146
1147 Const::PIDDetectorSet set = Const::ECL;
1148 return pid->getProbability(Const::electron, Const::pion, set);
1149 }
1150
1151
1152 // PID variables to be used for analysis
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.
1184
1185- 1 signal(antineutron) like
1186- 0 background like
1187- -1 invalid using this PID due to some ECL variables used unavailable
1188
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");
1192
1193 // Special temporary variables defined for users' convenience.
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);
1226
1227
1228 REGISTER_METAVARIABLE("weightedElectronID(weightMatrixName)", weightedElectronID,
1229 R"DOC(
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.
1234)DOC",
1235 Manager::VariableDataType::c_double);
1236 REGISTER_METAVARIABLE("weightedMuonID(weightMatrixName)", weightedMuonID,
1237 R"DOC(
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.
1242)DOC",
1243 Manager::VariableDataType::c_double);
1244 REGISTER_METAVARIABLE("weightedPionID(weightMatrixName)", weightedPionID,
1245 R"DOC(
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.
1250)DOC",
1251 Manager::VariableDataType::c_double);
1252 REGISTER_METAVARIABLE("weightedKaonID(weightMatrixName)", weightedKaonID,
1253 R"DOC(
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.
1258)DOC",
1259 Manager::VariableDataType::c_double);
1260 REGISTER_METAVARIABLE("weightedProtonID(weightMatrixName)", weightedProtonID,
1261 R"DOC(
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.
1266)DOC",
1267 Manager::VariableDataType::c_double);
1268 REGISTER_METAVARIABLE("weightedDeuteronID(weightMatrixName)", weightedDeuteronID,
1269 R"DOC(
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.
1274)DOC",
1275 Manager::VariableDataType::c_double);
1276
1277
1278 REGISTER_VARIABLE("electronIDNN", electronIDNN,
1279 R"DOC(
1280electron identification probability as calculated from the PID neural network.
1281Requires global tag 'pid_nn_<release>' with the correct data <release>.
1282)DOC");
1283 REGISTER_VARIABLE("muonIDNN", muonIDNN,
1284 R"DOC(
1285muon identification probability as calculated from the PID neural network.
1286Requires global tag 'pid_nn_<release>' with the correct data <release>.
1287)DOC");
1288 REGISTER_VARIABLE("pionIDNN", pionIDNN,
1289 R"DOC(
1290pion identification probability as calculated from the PID neural network.
1291Requires global tag 'pid_nn_<release>' with the correct data <release>.
1292)DOC");
1293 REGISTER_VARIABLE("kaonIDNN", kaonIDNN,
1294 R"DOC(
1295kaon identification probability as calculated from the PID neural network.
1296Requires global tag 'pid_nn_<release>' with the correct data <release>.
1297)DOC");
1298 REGISTER_VARIABLE("protonIDNN", protonIDNN,
1299 R"DOC(
1300proton identification probability as calculated from the PID neural network.
1301Requires global tag 'pid_nn_<release>' with the correct data <release>.
1302)DOC");
1303 REGISTER_VARIABLE("deuteronIDNN", deuteronIDNN,
1304 R"DOC(
1305deuteron identification probability as calculated from the PID neural network.
1306Requires global tag 'pid_nn_<release>' with the correct data <release>.
1307)DOC");
1308
1309
1310 // Metafunctions for experts to access the basic PID quantities
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,
1329 R"DOC(
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");
1337
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)");
1366
1367 // B2BII PID
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).
1373
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).
1379
1380.. warning:: The behaviour is different from Belle II PID variables which typically return NaN in case of error.
1381 )DOC");
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.
1385 )DOC");
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).
1389
1390.. warning:: The behaviour is different from Belle II PID variables which typically return NaN in case of error.
1391 )DOC");
1392 }
1394}
static const unsigned int c_SetSize
Number of elements (for use in array bounds etc.)
Definition: Const.h:615
static DetectorSet set()
Accessor function for the set of valid detectors.
Definition: Const.h:374
int getPDGCode() const
PDG code.
Definition: Const.h:473
static DetectorSet set()
Accessor for the set of valid detector IDs.
Definition: Const.h:333
static const ParticleType neutron
neutron particle
Definition: Const.h:675
static const ChargedStable muon
muon particle
Definition: Const.h:660
RestrictedDetectorSet< PIDDetectors > PIDDetectorSet
Typedef for set of PID detectors.
Definition: Const.h:379
static const ParticleSet chargedStableSet
set of charged stable particles
Definition: Const.h:618
EDetector
Enum for identifying the detector components (detector and subdetector).
Definition: Const.h:42
static const ChargedStable pion
charged pion particle
Definition: Const.h:661
static const ChargedStable proton
proton particle
Definition: Const.h:663
static const double doubleNaN
quiet_NaN
Definition: Const.h:703
static const ChargedStable kaon
charged kaon particle
Definition: Const.h:662
static const ChargedStable electron
electron particle
Definition: Const.h:659
static const ChargedStable deuteron
deuteron particle
Definition: Const.h:664
static const ReferenceFrame & GetCurrent()
Get current rest frame.
std::function< VarVariant(const Particle *)> FunctionPtr
functions stored take a const Particle* and return VarVariant.
Definition: Manager.h:112
const Var * getVariable(std::string name)
Get the variable belonging to the given key.
Definition: Manager.cc:58
static Manager & Instance()
get singleton instance.
Definition: Manager.cc:26
Abstract base class for different kinds of events.
STL namespace.
FunctionPtr function
Pointer to function.
Definition: Manager.h:146