Belle II Software development
FEIVariables.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/FEIVariables.h>
11
12// include VariableManager
13#include <analysis/VariableManager/Manager.h>
14
15#include <analysis/dataobjects/Particle.h>
16#include <analysis/utility/PCmsLabTransform.h>
17#include <framework/gearbox/Const.h>
18#include <mdst/dataobjects/MCParticle.h>
19#include <framework/datastore/StoreArray.h>
20#include <map>
21#include <algorithm>
22#include <iterator>
23
24namespace Belle2 {
29 namespace Variable {
30
31 int mostcommonBTagIndex(const Particle* part)
32 {
33 std::map <int, int> tag_candidates;
34 const std::vector<const Particle*>& fsp_tag = part->getFinalStateDaughters();
35 for (const Particle* fsp : fsp_tag) {
36 const MCParticle* mc_fsp = fsp->getMCParticle();
37 if (mc_fsp) {
38 int tag_index = finddescendant(mc_fsp);
39 if (tag_candidates.find(tag_index) == tag_candidates.end()) {
40 tag_candidates[tag_index] = 1;
41 } else {
42 tag_candidates[tag_index]++;
43 }
44 }
45 }
46 int tag_index = -1;
47 int tag_N = 0;
48 // cppcheck-suppress unassignedVariable
49 for (const auto& [key, value] : tag_candidates) {
50 if (value > tag_N) {
51 tag_index = key;
52 tag_N = value;
53 }
54 }
55 return tag_index;
56 }
57 int finddescendant(const MCParticle* mcpart)
58 {
59 const MCParticle* i_mcpart = mcpart;
60 while (i_mcpart) {
61 auto* i_mcpart_mother = i_mcpart->getMother();
62 if (i_mcpart_mother) {
63 constexpr std::array<int, 2> B_PDG = {511, 521};
64 auto result = std::find(B_PDG.begin(), B_PDG.end(), abs(i_mcpart_mother->getPDG()));
65 if (result != B_PDG.end()) {
66 return i_mcpart_mother->getArrayIndex();
67 }
68 i_mcpart = i_mcpart_mother;
69 } else {
70 return -1;
71 }
72 }
73 return -2;
74 }
75 std::vector<int> truthFSPTag(int BTag_index)
76 {
77 StoreArray<MCParticle> MC_Particle_list;
78 std::vector<int> fsp_truth_index;
79 for (const MCParticle& iMCParticle : MC_Particle_list) {
80 if ((BTag_index == finddescendant(&iMCParticle)) && (iMCParticle.hasStatus(MCParticle::c_StableInGenerator) == true)
81 && (iMCParticle.hasStatus(MCParticle::c_IsISRPhoton) == false) && iMCParticle.hasStatus(MCParticle::c_IsFSRPhoton) == false
82 && (iMCParticle.hasStatus(MCParticle::c_IsPHOTOSPhoton) == false)) {
83 fsp_truth_index.push_back(iMCParticle.getArrayIndex());
84 }
85 }
86 return fsp_truth_index;
87 }
88 double percentageMissingParticlesBTag(const Particle* part)
89 {
90 int index = mostcommonBTagIndex(part);
91 if (index == -1) {
92 return -1;
93 } else {
94 std::vector<int> fsp_FEI_index;
95 const std::vector<const Particle*>& fsp_tag = part->getFinalStateDaughters();
96 for (const Particle* fsp : fsp_tag) {
97 const MCParticle* mc_fsp = fsp->getMCParticle();
98 if (mc_fsp) {
99 int tag_index = finddescendant(mc_fsp);
100 if (tag_index == index) {
101 fsp_FEI_index.push_back(mc_fsp->getArrayIndex());
102 }
103 }
104 }
105 std::vector<int> diff;
106 std::vector<int> fsp_truth_index = truthFSPTag(index);
107 std::sort(fsp_truth_index.begin(), fsp_truth_index.end());
108 std::sort(fsp_FEI_index.begin(), fsp_FEI_index.end());
109 std::set_difference(fsp_truth_index.begin(), fsp_truth_index.end(), fsp_FEI_index.begin(), fsp_FEI_index.end(), std::inserter(diff,
110 diff.begin()));
111 return double(diff.size()) / double(fsp_truth_index.size());
112 }
113 }
114 double percentageWrongParticlesBTag(const Particle* part)
115 {
116 int index = mostcommonBTagIndex(part);
117 if (index == -1) {
118 return -1;
119 } else {
120 const std::vector<const Particle*>& fsp_tag = part->getFinalStateDaughters();
121 int wrong_FEI = 0;
122 for (const Particle* fsp : fsp_tag) {
123 const MCParticle* mc_fsp = fsp->getMCParticle();
124 if (mc_fsp) {
125 int tag_index = finddescendant(mc_fsp);
126 if (tag_index != index) {
127 wrong_FEI ++;
128 }
129 }
130 }
131 return double(wrong_FEI) / double(truthFSPTag(index).size());
132 }
133 }
134 double mostcommonBTagDeltaP(const Particle* part)
135 {
136 int idx = mostcommonBTagIndex(part);
137 if (idx < 0) return Const::doubleNaN;
138
139 StoreArray<MCParticle> mcParticles;
140 PCmsLabTransform T;
141 ROOT::Math::XYZVector recoP3 = (T.rotateLabToCms() * part->get4Vector()).Vect();
142 ROOT::Math::XYZVector genP3 = (T.rotateLabToCms() * mcParticles[idx]->get4Vector()).Vect();
143 return (recoP3 - genP3).R();
144 }
145
146 double mostcommonBTagPDG(const Particle* part)
147 {
148 int idx = mostcommonBTagIndex(part);
149 if (idx < 0) return Const::doubleNaN;
150
151 StoreArray<MCParticle> mcParticles;
152 return mcParticles[idx]->getPDG();
153 }
154
155 VARIABLE_GROUP("FEIVariables");
156 REGISTER_VARIABLE("mostcommonBTagIndex", mostcommonBTagIndex,
157 "By giving e.g. a FEI B meson candidate the B meson index on generator level is determined, where most reconstructed particles can be assigned to. If no B meson found on generator level -1 is returned.");
158 REGISTER_VARIABLE("percentageMissingParticlesBTag", percentageMissingParticlesBTag,
159 "Get the percentage of missing particles by using the mostcommonBTagIndex. So the number of particles not reconstructed by e.g. the FEI are determined and divided by the number of generated particles using the given index of the B meson. If no B meson found on generator level -1 is returned.");
160 REGISTER_VARIABLE("percentageWrongParticlesBTag", percentageWrongParticlesBTag,
161 "Get the percentage of wrong particles by using the mostcommonBTagIndex. In this context wrong means that the reconstructed particles originated from the other B meson. The absolute number is divided by the total number of generated FSP from the given B meson index. If no B meson found on generator level -1 is returned.");
162 REGISTER_VARIABLE("mostcommonBTagDeltaP", mostcommonBTagDeltaP,
163 "Returns the magnitude of the 3-momentum difference in CMS frame between the "
164 "reconstructed particle and the generated B meson identified by mostcommonBTagIndex. "
165 "Returns NaN if no B meson is found on generator level.", "GeV/c");
166 REGISTER_VARIABLE("mostcommonBTagPDG", mostcommonBTagPDG,
167 "Returns the PDG code of the generated B meson identified by mostcommonBTagIndex. "
168 "Returns NaN if no B meson is found on generator level. "
169 "Note: this is equivalent to ``genParticle(mostcommonBTagIndex, PDG)``. "
170 "Other variables can be accessed the same way by replacing ``PDG`` with any variable.");
171 }
173}
static const double doubleNaN
quiet_NaN
Definition Const.h:703
@ c_IsFSRPhoton
bit 7: Particle is from final state radiation
Definition MCParticle.h:61
@ c_IsPHOTOSPhoton
bit 8: Particle is an radiative photon from PHOTOS
Definition MCParticle.h:63
@ c_StableInGenerator
bit 1: Particle is stable, i.e., not decaying in the generator.
Definition MCParticle.h:49
@ c_IsISRPhoton
bit 6: Particle is from initial state radiation
Definition MCParticle.h:59
Abstract base class for different kinds of events.