Belle II Software  release-05-01-25
PIDVariables.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2010 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Marko Staric, Anze Zupanc, Umberto Tamponi *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 // Own include
12 #include <analysis/variables/PIDVariables.h>
13 
14 #include <analysis/VariableManager/Manager.h>
15 
16 #include <mdst/dataobjects/PIDLikelihood.h>
17 
18 // framework aux
19 #include <framework/logging/Logger.h>
20 #include <framework/utilities/Conversion.h>
21 
22 #include <framework/utilities/Conversion.h>
23 
24 #include <boost/algorithm/string.hpp>
25 
26 #include <iostream>
27 #include <cmath>
28 
29 using namespace std;
30 
31 namespace Belle2 {
36  namespace Variable {
37 
38 
39 
40  //*************
41  // Utilities
42  //*************
43 
44  // converts Belle numbering scheme for charged final state particles
45  // to Belle II ChargedStable
46  Const::ChargedStable hypothesisConversion(const int hypothesis)
47  {
48  switch (hypothesis) {
49  case 0:
50  return Const::electron;
51  case 1:
52  return Const::muon;
53  case 2:
54  return Const::pion;
55  case 3:
56  return Const::kaon;
57  case 4:
58  return Const::proton;
59  }
60 
61  return Const::pion;
62  }
63 
64 
65  Const::PIDDetectorSet parseDetectors(const std::vector<std::string>& arguments)
66  {
67  Const::PIDDetectorSet result;
68  for (std::string val : arguments) {
69  boost::to_lower(val);
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);
78  }
79  return result;
80  }
81 
82  // Specialisation of valid detectors parser for ChargedBDT.
83  Const::PIDDetectorSet parseDetectorsChargedBDT(const std::vector<std::string>& arguments)
84  {
85  Const::PIDDetectorSet result;
86  for (std::string val : arguments) {
87  boost::to_lower(val);
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.");
91  }
92  return result;
93  }
94 
95  //*************
96  // Belle II
97  //*************
98 
99  // a "smart" variable:
100  // finds the global probability based on the PDG code of the input particle
101  double particleID(const Particle* p)
102  {
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();
111  }
112 
113  Manager::FunctionPtr pidLogLikelihoodValueExpert(const std::vector<std::string>& arguments)
114  {
115  if (arguments.size() < 2) {
116  B2ERROR("Need at least two arguments to pidLogLikelihoodValueExpert");
117  return nullptr;
118  }
119  int pdgCode;
120  try {
121  pdgCode = Belle2::convertString<int>(arguments[0]);
122  } catch (std::invalid_argument& e) {
123  B2ERROR("First argument of pidLogLikelihoodValueExpert must be a PDG code");
124  return nullptr;
125  }
126  std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
127 
128  Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
129  auto hypType = Const::ChargedStable(abs(pdgCode));
130 
131  auto func = [hypType, detectorSet](const Particle * part) -> double {
132  const PIDLikelihood* pid = part->getPIDLikelihood();
133  if (!pid)
134  return std::numeric_limits<float>::quiet_NaN();
135  // No informaiton form any subdetector in the list
136  if (pid->getLogL(hypType, detectorSet) == 0)
137  return std::numeric_limits<float>::quiet_NaN();
138 
139  return pid->getLogL(hypType, detectorSet);
140  };
141  return func;
142  }
143 
144 
145 
146  Manager::FunctionPtr pidDeltaLogLikelihoodValueExpert(const std::vector<std::string>& arguments)
147  {
148  if (arguments.size() < 3) {
149  B2ERROR("Need at least three arguments to pidDeltaLogLikelihoodValueExpert");
150  return nullptr;
151  }
152  int pdgCodeHyp, pdgCodeTest;
153  try {
154  pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
155  } catch (std::invalid_argument& e) {
156  B2ERROR("First argument of pidDeltaLogLikelihoodValueExpert must be a PDG code");
157  return nullptr;
158  }
159  try {
160  pdgCodeTest = Belle2::convertString<int>(arguments[1]);
161  } catch (std::invalid_argument& e) {
162  B2ERROR("Second argument of pidDeltaLogLikelihoodValueExpert must be a PDG code");
163  return nullptr;
164  }
165 
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));
170 
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();
174  // No informaiton form any subdetector in the list
175  if (pid->getLogL(hypType, detectorSet) == 0)
176  return std::numeric_limits<float>::quiet_NaN();
177 
178  return (pid->getLogL(hypType, detectorSet) - pid->getLogL(testType, detectorSet));
179  };
180  return func;
181  }
182 
183 
184  Manager::FunctionPtr pidPairProbabilityExpert(const std::vector<std::string>& arguments)
185  {
186  if (arguments.size() < 3) {
187  B2ERROR("Need at least three arguments to pidPairProbabilityExpert");
188  return nullptr;
189  }
190  int pdgCodeHyp = 0, pdgCodeTest = 0;
191  try {
192  pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
193  } catch (std::invalid_argument& e) {
194  B2ERROR("First argument of pidPairProbabilityExpert must be PDG code");
195  return nullptr;
196  }
197  try {
198  pdgCodeTest = Belle2::convertString<int>(arguments[1]);
199  } catch (std::invalid_argument& e) {
200  B2ERROR("Second argument of pidPairProbabilityExpert must be PDG code");
201  return nullptr;
202  }
203 
204  std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
205 
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();
212  // No information from any subdetector in the list
213  if (pid->getLogL(hypType, detectorSet) == 0)
214  return std::numeric_limits<float>::quiet_NaN();
215 
216  return pid->getProbability(hypType, testType, detectorSet);
217  };
218  return func;
219  }
220 
221 
222  Manager::FunctionPtr pidProbabilityExpert(const std::vector<std::string>& arguments)
223  {
224  if (arguments.size() < 2) {
225  B2ERROR("Need at least two arguments for pidProbabilityExpert");
226  return nullptr;
227  }
228  int pdgCodeHyp = 0;
229  try {
230  pdgCodeHyp = Belle2::convertString<int>(arguments[0]);
231  } catch (std::invalid_argument& e) {
232  B2ERROR("First argument of pidProbabilityExpert must be PDG code");
233  return nullptr;
234  }
235 
236  std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
237  Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
238  auto hypType = Const::ChargedStable(abs(pdgCodeHyp));
239 
240  // Placeholder for the priors
241  const unsigned int n = Const::ChargedStable::c_SetSize;
242  double frac[n];
243  for (double& i : frac) i = 1.0; // flat priors
244 
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();
248  // No information from any subdetector in the list
249  if (pid->getLogL(hypType, detectorSet) == 0)
250  return std::numeric_limits<float>::quiet_NaN();
251 
252  return pid->getProbability(hypType, frac, detectorSet);
253  };
254  return func;
255  }
256 
257 
258  Manager::FunctionPtr pidMissingProbabilityExpert(const std::vector<std::string>& arguments)
259  {
260  if (arguments.size() < 1) {
261  B2ERROR("Need at least one argument to pidMissingProbabilityExpert");
262  return nullptr;
263  }
264 
265  std::vector<std::string> detectors(arguments.begin(), arguments.end());
266  Const::PIDDetectorSet detectorSet = parseDetectors(detectors);
267 
268  auto func = [detectorSet](const Particle * part) -> int {
269  const PIDLikelihood* pid = part->getPIDLikelihood();
270  if (not pid->isAvailable(detectorSet))
271  return 1;
272  else return 0;
273  };
274  return func;
275  }
276 
277  double electronID(const Particle* part)
278  {
279  return Manager::Instance().getVariable("pidProbabilityExpert(11, CDC, TOP, ARICH, ECL, KLM)")->function(part);
280  }
281 
282  double muonID(const Particle* part)
283  {
284  return Manager::Instance().getVariable("pidProbabilityExpert(13, CDC, TOP, ARICH, ECL, KLM)")->function(part);
285  }
286 
287  double pionID(const Particle* part)
288  {
289  return Manager::Instance().getVariable("pidProbabilityExpert(211, CDC, TOP, ARICH, ECL, KLM)")->function(part);
290  }
291 
292  double kaonID(const Particle* part)
293  {
294  return Manager::Instance().getVariable("pidProbabilityExpert(321, CDC, TOP, ARICH, ECL, KLM)")->function(part);
295  }
296 
297  double protonID(const Particle* part)
298  {
299  return Manager::Instance().getVariable("pidProbabilityExpert(2212, CDC, TOP, ARICH, ECL, KLM)")->function(part);
300  }
301 
302  double deuteronID(const Particle* part)
303  {
304  return Manager::Instance().getVariable("pidProbabilityExpert(1000010020, CDC, TOP, ARICH, ECL, KLM)")->function(part);
305  }
306 
307  double binaryPID(const Particle* part, const std::vector<double>& arguments)
308  {
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();;
312  }
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);
317  }
318 
319  double electronID_noTOP(const Particle* part)
320  {
321  // Excluding TOP for electron ID. This is temporary. BII-8376
322  return Manager::Instance().getVariable("pidProbabilityExpert(11, CDC, ARICH, ECL, KLM)")->function(part);
323  }
324 
325  double binaryPID_noTOP(const Particle* part, const std::vector<double>& arguments)
326  {
327  // Excluding TOP for electron ID. This is temporary. BII-8376
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();;
331  }
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();
338  }
339  return Manager::Instance().getVariable("pidPairProbabilityExpert(" + std::to_string(pdgCodeHyp) + ", " + std::to_string(
340  pdgCodeTest) + ", CDC, ARICH, ECL, KLM)")->function(part);
341  }
342 
343  double pionID_SVD(const Particle* part)
344  {
345  return Manager::Instance().getVariable("formula(exp(pidLogLikelihoodValueExpert(211, ALL))/[exp(pidLogLikelihoodValueExpert(211, ALL))+exp(pidLogLikelihoodValueExpert(321, ALL))+exp(pidLogLikelihoodValueExpert(2212, ALL))])")->function(
346  part);
347  }
348 
349  double kaonID_SVD(const Particle* part)
350  {
351  return Manager::Instance().getVariable("formula(exp(pidLogLikelihoodValueExpert(321, ALL))/[exp(pidLogLikelihoodValueExpert(211, ALL))+exp(pidLogLikelihoodValueExpert(321, ALL))+exp(pidLogLikelihoodValueExpert(2212, ALL))])")->function(
352  part);
353  }
354 
355  double protonID_SVD(const Particle* part)
356  {
357  return Manager::Instance().getVariable("formula(exp(pidLogLikelihoodValueExpert(2212, ALL))/[exp(pidLogLikelihoodValueExpert(211, ALL))+exp(pidLogLikelihoodValueExpert(321, ALL))+exp(pidLogLikelihoodValueExpert(2212, ALL))])")->function(
358  part);
359  }
360 
361  double binaryPID_SVD(const Particle* part, const std::vector<double>& arguments)
362  {
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();
366  }
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();
373  }
374  return Manager::Instance().getVariable("pidPairProbabilityExpert(" + std::to_string(pdgCodeHyp) + ", " + std::to_string(
375  pdgCodeTest) + ", ALL)")->function(part);
376  }
377 
378  Manager::FunctionPtr pidChargedBDTScore(const std::vector<std::string>& arguments)
379  {
380  if (arguments.size() != 2) {
381  B2ERROR("Need exactly two arguments for pidChargedBDTScore: pdgCodeHyp, detector");
382  return nullptr;
383  }
384 
385  int hypPdgId;
386  try {
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).");
390  return nullptr;
391  }
392  Const::ChargedStable hypType = Const::ChargedStable(hypPdgId);
393 
394  std::vector<std::string> detectors(arguments.begin() + 1, arguments.end());
395  Const::PIDDetectorSet detectorSet = parseDetectorsChargedBDT(detectors);
396 
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)
400  {
401  auto det = detectorSet[iDet];
402  name += "_" + std::to_string(det);
403  }
404  return (part->hasExtraInfo(name)) ? part->getExtraInfo(name) : std::numeric_limits<float>::quiet_NaN();
405  };
406  return func;
407  }
408 
409  Manager::FunctionPtr pidPairChargedBDTScore(const std::vector<std::string>& arguments)
410  {
411  if (arguments.size() != 3) {
412  B2ERROR("Need exactly three arguments for pidPairChargedBDTScore: pdgCodeHyp, pdgCodeTest, detector.");
413  return nullptr;
414  }
415 
416  int hypPdgId, testPdgId;
417  try {
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).");
421  return nullptr;
422  }
423  try {
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).");
427  return nullptr;
428  }
429  Const::ChargedStable hypType = Const::ChargedStable(hypPdgId);
430  Const::ChargedStable testType = Const::ChargedStable(testPdgId);
431 
432  std::vector<std::string> detectors(arguments.begin() + 2, arguments.end());
433  Const::PIDDetectorSet detectorSet = parseDetectorsChargedBDT(detectors);
434 
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)
438  {
439  auto det = detectorSet[iDet];
440  name += "_" + std::to_string(det);
441  }
442  return (part->hasExtraInfo(name)) ? part->getExtraInfo(name) : std::numeric_limits<float>::quiet_NaN();
443  };
444  return func;
445  }
446 
447  Manager::FunctionPtr mostLikelyPDG(const std::vector<std::string>& arguments)
448  {
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");
451  return nullptr;
452  }
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;
456  }
457  if (arguments.size() == Const::ChargedStable::c_SetSize) {
458  try {
459  int i = 0;
460  for (std::string arg : arguments) {
461  prob[i++] = Belle2::convertString<float>(arg);
462  }
463  } catch (std::invalid_argument& e) {
464  B2ERROR("All arguments of mostLikelyPDG must be a float number");
465  return nullptr;
466  }
467  }
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();
472  };
473  return func;
474  }
475 
476  Manager::FunctionPtr isMostLikely(const std::vector<std::string>& arguments)
477  {
478  if (arguments.size() != 0 and arguments.size() != 6) {
479  B2ERROR("Need zero or exactly " << Const::ChargedStable::c_SetSize << " arguments for pidIsMostLikely");
480  return nullptr;
481  }
482  auto func = [arguments](const Particle * part) -> double {
483  return mostLikelyPDG(arguments)(part) == abs(part->getPDGCode());
484  };
485  return func;
486  }
487 
488  //*************
489  // B2BII
490  //*************
491 
492  double muIDBelle(const Particle* particle)
493  {
494  const PIDLikelihood* pid = particle->getPIDLikelihood();
495  if (!pid) return 0.5; // Belle standard
496 
497  if (pid->isAvailable(Const::KLM))
498  return exp(pid->getLogL(Const::muon, Const::KLM));
499  else
500  return 0; // Belle standard
501  }
502 
503  double muIDBelleQuality(const Particle* particle)
504  {
505  const PIDLikelihood* pid = particle->getPIDLikelihood();
506  if (!pid) return 0;// Belle standard
507 
508  return pid->isAvailable(Const::KLM);
509  }
510 
511  double atcPIDBelle(const Particle* particle, const std::vector<double>& sigAndBkgHyp)
512  {
513  int sigHyp = int(std::lround(sigAndBkgHyp[0]));
514  int bkgHyp = int(std::lround(sigAndBkgHyp[1]));
515 
516  const PIDLikelihood* pid = particle->getPIDLikelihood();
517  if (!pid) return 0.5; // Belle standard
518 
519  // ACC = ARICH
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));
523  double acc = 0.5; // Belle standard
524  if (acc_sig + acc_bkg > 0.0)
525  acc = acc_sig / (acc_sig + acc_bkg);
526 
527  // TOF = TOP
528  set = Const::TOP;
529  double tof_sig = exp(pid->getLogL(hypothesisConversion(sigHyp), set));
530  double tof_bkg = exp(pid->getLogL(hypothesisConversion(bkgHyp), set));
531  double tof = 0.5; // Belle standard
532  double tof_all = tof_sig + tof_bkg;
533  if (tof_all != 0) {
534  tof = tof_sig / tof_all;
535  if (tof < 0.001) tof = 0.001;
536  if (tof > 0.999) tof = 0.999;
537  }
538 
539  // dE/dx = CDC
540  set = Const::CDC;
541  double cdc_sig = exp(pid->getLogL(hypothesisConversion(sigHyp), set));
542  double cdc_bkg = exp(pid->getLogL(hypothesisConversion(bkgHyp), set));
543  double cdc = 0.5; // Belle standard
544  double cdc_all = cdc_sig + cdc_bkg;
545  if (cdc_all != 0) {
546  cdc = cdc_sig / cdc_all;
547  if (cdc < 0.001) cdc = 0.001;
548  if (cdc > 0.999) cdc = 0.999;
549  }
550 
551  // Combined
552  double pid_sig = acc * tof * cdc;
553  double pid_bkg = (1. - acc) * (1. - tof) * (1. - cdc);
554 
555  return pid_sig / (pid_sig + pid_bkg);
556  }
557 
558 
559  double eIDBelle(const Particle* part)
560  {
561  const PIDLikelihood* pid = part->getPIDLikelihood();
562  if (!pid) return 0.5; // Belle standard
563 
564  Const::PIDDetectorSet set = Const::ECL;
565  return pid->getProbability(Const::electron, Const::pion, set);
566  }
567 
568 
569  // PID variables to be used for analysis
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`)");
599 
600  // Metafunctions for experts to access the basic PID quantities
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");
620 
621  // B2BII PID
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.");
632 
633  }
635 }
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19