10 #include <analysis/modules/ParticleListManipulator/ParticleListManipulatorModule.h>
14 #include <framework/datastore/DataStore.h>
17 #include <framework/logging/Logger.h>
20 #include <analysis/DecayDescriptor/ParticleListName.h>
21 #include <analysis/utility/ValueIndexPairSorting.h>
45 setDescription(
"Manipulates ParticleLists: copies/merges/performs particle selection");
46 setPropertyFlags(c_ParallelProcessingCertified);
49 addParam(
"outputListName", m_outputListName,
"Output ParticleList name");
51 vector<string> defaultList;
52 addParam(
"inputListNames", m_inputListNames,
53 "list of input ParticleList names", defaultList);
55 addParam(
"cut", m_cutParameter,
"Selection criteria to be applied", std::string(
""));
57 addParam(
"variable", m_variableName,
"Variable which defines the best duplicate (see ``selectLowest`` for ordering)",
58 std::string(
"mdstIndex"));
59 addParam(
"preferLowest", m_preferLowest,
60 "If true, duplicate with lowest value of ``variable`` is accepted, otherwise higher one.",
true);
62 addParam(
"writeOut", m_writeOut,
63 "If true, the output ParticleList will be saved by RootOutput. If false, it will be ignored when writing the file.",
false);
67 m_isSelfConjugatedParticle =
false;
70 void ParticleListManipulatorModule::initialize()
72 m_particles.isRequired();
77 bool valid = m_decaydescriptor.init(m_outputListName);
79 B2ERROR(
"ParticleListManipulatorModule::initialize Invalid output ParticleList name: " << m_outputListName);
84 m_pdgCode = mother->getPDGCode();
89 string listLabel = mother->getLabel();
91 if (Const::finalStateParticlesSet.contains(
Const::ParticleType(abs(m_pdgCode))) and listLabel ==
"all") {
92 B2FATAL(
"You have tried to create the list " << m_outputListName <<
93 " but the label 'all' is forbidden for user-defined lists of final-state particles." <<
94 " It could introduce *very* dangerous bugs.");
95 }
else if ((listLabel ==
"MC") or (listLabel ==
"V0" and not((
"K_S0:mdst" == m_inputListNames[0])
96 or (
"Lambda0:mdst" == m_inputListNames[0]) or (
"gamma:v0mdst" == m_inputListNames[0])))) {
99 B2FATAL(
"You have tried to create the list " << m_outputListName <<
100 " but the label " << listLabel <<
" is not allowed for merged or copied particle lists.");
103 m_outputAntiListName = ParticleListName::antiParticleListName(m_outputListName);
104 m_isSelfConjugatedParticle = (m_outputListName == m_outputAntiListName);
107 for (
const std::string& listName : m_inputListNames) {
108 if (listName == m_outputListName) {
109 B2ERROR(
"ParticleListManipulatorModule: cannot copy Particles from " << listName <<
110 " to itself! Use applyCuts() (ParticleSelector module) instead.");
111 }
else if (!m_decaydescriptor.init(listName)) {
112 B2ERROR(
"Invalid input ParticleList name: " << listName);
119 m_particleList.registerInDataStore(m_outputListName, flags);
120 if (!m_isSelfConjugatedParticle) {
121 m_antiParticleList.registerInDataStore(m_outputAntiListName, flags);
124 m_variable = Variable::Manager::Instance().getVariable(m_variableName);
126 B2ERROR(
"Variable '" << m_variableName <<
"' is not available in Variable::Manager!");
128 m_cut = Variable::Cut::compile(m_cutParameter);
131 void ParticleListManipulatorModule::event()
134 m_particlesInTheList.clear();
136 bool existingList = m_particleList.isValid();
140 m_particleList.create();
141 m_particleList->initialize(m_pdgCode, m_outputListName);
143 if (!m_isSelfConjugatedParticle) {
144 m_antiParticleList.create();
145 m_antiParticleList->initialize(-1 * m_pdgCode, m_outputAntiListName);
147 m_antiParticleList->bindAntiParticleList(*(m_particleList));
153 for (
unsigned i = 0; i < m_particleList->getListSize(); i++) {
154 const Particle* particle = m_particleList->getParticle(i);
156 std::vector<int> idSeq;
157 fillUniqueIdentifier(particle, idSeq);
158 m_particlesInTheList.push_back(idSeq);
163 typedef std::pair<double, unsigned int> ValueIndexPair;
164 std::vector<ValueIndexPair> valueToIndex;
167 for (
const auto& inputListName : m_inputListNames) {
169 if (!inPList.
isValid())
continue;
171 std::vector<int> fsParticles = inPList->getList(ParticleList::EParticleType::c_FlavorSpecificParticle,
false);
172 const std::vector<int>& scParticles = inPList->getList(ParticleList::EParticleType::c_SelfConjugatedParticle,
false);
173 const std::vector<int>& fsAntiParticles = inPList->getList(ParticleList::EParticleType::c_FlavorSpecificParticle,
true);
175 fsParticles.insert(fsParticles.end(), scParticles.begin(), scParticles.end());
176 fsParticles.insert(fsParticles.end(), fsAntiParticles.begin(), fsAntiParticles.end());
178 for (
int fsParticle : fsParticles) {
179 const Particle* part = m_particles[fsParticle];
181 if (m_cut->check(part)) {
182 valueToIndex.emplace_back(m_variable->function(part), part->getArrayIndex());
189 if (m_preferLowest) {
190 std::stable_sort(valueToIndex.begin(), valueToIndex.end(), ValueIndexPairSorting::lowerPair<ValueIndexPair>);
192 std::stable_sort(valueToIndex.begin(), valueToIndex.end(), ValueIndexPairSorting::higherPair<ValueIndexPair>);
196 for (
const auto& candidate : valueToIndex) {
197 const Particle* part = m_particles[candidate.second];
199 std::vector<int> idSeq;
200 fillUniqueIdentifier(part, idSeq);
201 bool uniqueSeq = isUnique(idSeq);
204 m_particleList->addParticle(part);
205 m_particlesInTheList.push_back(idSeq);
210 void ParticleListManipulatorModule::fillUniqueIdentifier(
const Particle* p, std::vector<int>& idSequence)
212 idSequence.push_back(p->getPDGCode());
214 if (p->getNDaughters() == 0) {
215 idSequence.push_back(p->getMdstArrayIndex());
217 idSequence.push_back(p->getNDaughters());
218 auto daughters = p->getDaughters();
220 sort(daughters.begin(), daughters.end(), [](
const auto a,
const auto b) {
221 return a->getPDGCode() > b->getPDGCode();
224 for (
const auto& daughter : daughters)
225 fillUniqueIdentifier(daughter, idSequence);
229 bool ParticleListManipulatorModule::isUnique(
const std::vector<int>& idSeqOUT)
231 for (
const auto& idSeqIN : m_particlesInTheList) {
232 bool sameSeq = (idSeqIN == idSeqOUT);
The ParticleType class for identifying different particle types.
EStoreFlags
Flags describing behaviours of objects etc.
Represents a particle in the DecayDescriptor.
Module for copying Particles (actually their indices) from two or more ParticleLists(s) to another Pa...
Class to store reconstructed particles.
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
Type-safe access to single objects in the data store.
bool isValid() const
Check whether the object was created.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.