Belle II Software  release-08-01-10
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 
18 using namespace Belle2;
19 
20 //-----------------------------------------------------------------
21 // Register the Module
22 //-----------------------------------------------------------------
23 REG_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 
163 void 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 
168 void 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.
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().
std::vector< int > m_combination
Vector containing current combination of numbers (e.g.
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.
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:653
TClonesArray * getArrayPointer() const
Returns the pointer to the store array which holds the daughter particles.
Definition: Particle.h:911
EFlavorType getFlavorType() const
Returns flavor type of the decay (for FS particles: flavor type of particle)
Definition: Particle.h:441
int getPDGCode(void) const
Returns PDG code.
Definition: Particle.h:426
ROOT::Math::PxPyPzEVector get4Vector() const
Returns Lorentz vector.
Definition: Particle.h:517
@ c_Unflavored
Is its own antiparticle or we don't know whether it is a particle/antiparticle.
Definition: Particle.h:95
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
REG_MODULE(arichBtest)
Register the Module.
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
std::string antiParticleListName(const std::string &listName)
Returns name of anti-particle-list corresponding to listName.
Abstract base class for different kinds of events.