Belle II Software development
InclusiveBtagReconstructionModule.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#include <analysis/modules/InclusiveBtagReconstruction/InclusiveBtagReconstructionModule.h>
10
11#include <analysis/DecayDescriptor/ParticleListName.h>
12
13#include <unordered_set>
14#include <map>
15#include <vector>
16#include <Math/Vector4D.h>
17
18using namespace Belle2;
19
20//-----------------------------------------------------------------
21// Register the Module
22//-----------------------------------------------------------------
23REG_MODULE(InclusiveBtagReconstruction);
24
25//-----------------------------------------------------------------
26// Implementation
27//-----------------------------------------------------------------
28
30{
31 // Set module properties
32 setDescription("Inclusive Btag reconstruction");
33
34 // Parameter definitions
35 addParam("upsilonListName", m_upsilonListName, "Name of the ParticleList to be filled with Upsilon(4S) -> B:sig anti-B:tag",
36 std::string("Upsilon(4S)"));
37 addParam("bsigListName", m_bsigListName, "Name of the Bsig ParticleList", std::string(""));
38 addParam("btagListName", m_btagListName, "Name of the Btag ParticleList", std::string(""));
39 addParam("inputListsNames", m_inputListsNames, "List of names of the ParticleLists which are used to reconstruct Btag from");
40}
41
43
45{
46 m_bsigList.isRequired(m_bsigListName);
47
48 for (const std::string& inputListName : m_inputListsNames) {
49 StoreObjPtr<ParticleList> inputList(inputListName);
50 inputList.isRequired();
51 }
52
53 m_btagList.registerInDataStore(m_btagListName);
55 m_upsilonList.registerInDataStore(m_upsilonListName);
56}
57
59{
61 if (!valid)
62 B2ERROR("Invalid Bsig list name: " << m_bsigListName);
63
65 int pdgCode = mother->getPDGCode();
66
67 m_btagList.create();
68 m_btagList->initialize(-pdgCode, m_btagList.getName());
69
70 m_antiBtagList.create();
71 m_antiBtagList->initialize(pdgCode, m_antiBtagList.getName());
72 m_btagList->bindAntiParticleList(*m_antiBtagList);
73
74 m_upsilonList.create();
75 m_upsilonList->initialize(300553, m_upsilonList.getName());
76
77 const unsigned int n = m_bsigList->getListSize();
78 for (unsigned i = 0; i < n; i++) { // find Btag(s) for each Bsig
79 const Particle* bsig = m_bsigList->getParticle(i);
80 const std::vector<const Particle*>& bsigFinalStateDaughters = bsig->getFinalStateDaughters();
81 std::unordered_set<int> mdstSourcesOfBsigFinalStateDaughters;
82 std::map<int, std::vector<int>> btagDaughtersMap;
83
84 for (const Particle* daughter : bsigFinalStateDaughters) {
85 mdstSourcesOfBsigFinalStateDaughters.insert(daughter->getMdstSource());
86 }
87 auto mdstSourcesEnd = mdstSourcesOfBsigFinalStateDaughters.end();
88
89 // make a map of Btag daughters
90 for (const std::string& inputListName : m_inputListsNames) {
91 StoreObjPtr<ParticleList> inputList(inputListName);
92 const unsigned int m = inputList->getListSize();
93 for (unsigned j = 0; j < m; j++) {
94 const Particle* particle = inputList->getParticle(j);
95 const std::vector<const Particle*>& particleFinalStateDaughters = particle->getFinalStateDaughters();
96
97 // check if particle shares something with bsig...
98 for (const Particle* daughter : particleFinalStateDaughters) {
99 int mdstSource = daughter->getMdstSource();
100 if (mdstSourcesOfBsigFinalStateDaughters.find(mdstSource) != mdstSourcesEnd) {
101 break;
102 }
103 auto it = btagDaughtersMap.find(mdstSource);
104 if (it != btagDaughtersMap.end()) { // check for mdstSource overlaps
105 it->second.push_back(particle->getArrayIndex());
106 } else {
107 btagDaughtersMap[mdstSource] = {particle->getArrayIndex()};
108 }
109 }
110 }
111 }
112
113 // combine map entries to form Btag candidates
114 Map2Vector map2vector;
115 std::vector<std::vector<int>> btagCandidates;
116 map2vector.convert(btagDaughtersMap, btagCandidates);
117
118 for (std::vector<int> daughterIndices : btagCandidates) {
119 std::map<int, size_t> nonFinalStateIndicesCount;
120 ROOT::Math::PxPyPzEVector momentum;
121 for (int index : daughterIndices) {
122 // check if there are non-final-state particles. If yes, the momentum should be added just once.
123 if ((m_particles[index]->getFinalStateDaughters()).size() > 1) {
124 auto it = nonFinalStateIndicesCount.find(index);
125 if (it != nonFinalStateIndicesCount.end()) {
126 nonFinalStateIndicesCount[index]++;
127 continue;
128 } else {
129 nonFinalStateIndicesCount[index] = 1;
130 }
131 }
132 momentum += m_particles[index]->get4Vector();
133 }
134 // check the number of the daughters to make sure that the not-final-state particles are not mixed with the other particles that come from the same mdstSource
135 bool rightDaughtersCount = true;
136 for (auto& it : nonFinalStateIndicesCount) {
137 if (it.second != (m_particles[(it.first)]->getFinalStateDaughters()).size()) {
138 rightDaughtersCount = false;
139 break;
140 }
141 }
142 if (rightDaughtersCount == false) {
143 continue;
144 }
145
146 //remove repeated index in daughterIndices
147 std::vector<int>::iterator it;
148 std::sort(daughterIndices.begin(), daughterIndices.end());
149 it = std::unique(daughterIndices.begin(), daughterIndices.end());
150 daughterIndices.resize(std::distance(daughterIndices.begin(), it));
151
152 Particle btagCandidate(momentum, -1 * bsig->getPDGCode(), bsig->getFlavorType(), daughterIndices, bsig->getArrayPointer());
153 Particle* btag = m_particles.appendNew(btagCandidate);
154 m_btagList->addParticle(btag);
155
156 Particle upsilon(momentum + bsig->get4Vector(), 300553, Particle::c_Unflavored, { bsig->getArrayIndex(), btag->getArrayIndex() },
157 bsig->getArrayPointer());
158 m_upsilonList->addParticle(m_particles.appendNew(upsilon));
159 }
160 }
161}
162
163void Map2Vector::convert(std::map<int, std::vector<int>>& input, std::vector<std::vector<int>>& output)
164{
165 makeEntries(input.begin(), input.end(), 0, output);
166}
167
168void Map2Vector::makeEntries(std::map<int, std::vector<int>>::iterator positionOnTheMap,
169 const std::map<int, std::vector<int>>::const_iterator& end,
170 unsigned i, std::vector<std::vector<int>>& output)
171{
172 if (positionOnTheMap == end) {
173 output.push_back(m_combination);
174 } else {
175 std::vector<int>& v = positionOnTheMap->second;
176 ++positionOnTheMap;
177 for (int k : v) {
178 if (i < m_combination.size()) m_combination[i] = k;
179 else m_combination.push_back(k);
180 makeEntries(positionOnTheMap, end, i + 1, output);
181 }
182 }
183};
Represents a particle in the DecayDescriptor.
int getPDGCode() const
Return PDG code.
bool init(const std::string &str)
Initialise the DecayDescriptor from given string.
const DecayDescriptorParticle * getMother() const
return mother.
virtual void initialize() override
initialize the module (setup the data store)
StoreObjPtr< ParticleList > m_btagList
particle list of tag B
StoreArray< Particle > m_particles
StoreArray of Particles.
virtual ~InclusiveBtagReconstructionModule()
Destructor.
StoreObjPtr< ParticleList > m_upsilonList
particle list of Y(4S)
std::vector< std::string > m_inputListsNames
Names of the ParticleLists to be used to reconstruct Btag.
StoreObjPtr< ParticleList > m_bsigList
particle list of signal B
DecayDescriptor m_decaydescriptor
Decay descriptor for parsing the user specified DecayString.
std::string m_upsilonListName
Name of the ParticleList to be filled with Upsilon(4S) -> B:sig anti-B:tag
std::string m_bsigListName
Name of the Bsig ParticleList.
std::string m_btagListName
Name of the Btag ParticleList.
StoreObjPtr< ParticleList > m_antiBtagList
particle list of tag anti-B
Helper class to make a vector of all possible combinations of int numbers contained in the input vect...
void convert(std::map< int, std::vector< int > > &input, std::vector< std::vector< int > > &output)
Do the conversion using makeEntries().
void makeEntries(std::map< int, std::vector< int > >::iterator positionOnTheMap, const std::map< int, std::vector< int > >::const_iterator &end, unsigned i, std::vector< std::vector< int > > &output)
Recursively iterates over a map until the end is reached, then the output is ready.
std::vector< int > m_combination
Vector containing current combination of numbers (e.g.
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
Class to store reconstructed particles.
Definition: Particle.h:75
std::vector< const Belle2::Particle * > getFinalStateDaughters() const
Returns a vector of pointers to Final State daughter particles.
Definition: Particle.cc:649
EFlavorType getFlavorType() const
Returns flavor type of the decay (for FS particles: flavor type of particle)
Definition: Particle.h:469
int getPDGCode(void) const
Returns PDG code.
Definition: Particle.h:454
TClonesArray * getArrayPointer() const
Returns the pointer to the store array which holds the daughter particles.
Definition: Particle.h:953
ROOT::Math::PxPyPzEVector get4Vector() const
Returns Lorentz vector.
Definition: Particle.h:547
@ c_Unflavored
Is its own antiparticle or we don't know whether it is a particle/antiparticle.
Definition: Particle.h:95
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:246
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
std::string antiParticleListName(const std::string &listName)
Returns name of anti-particle-list corresponding to listName.
Abstract base class for different kinds of events.