9#include <analysis/DecayDescriptor/DecayDescriptor.h>
10#include <analysis/DecayDescriptor/DecayString.h>
11#include <analysis/DecayDescriptor/DecayStringDecay.h>
12#include <analysis/DecayDescriptor/DecayStringGrammar.h>
13#include <analysis/utility/EvtPDLUtil.h>
14#include <analysis/dataobjects/Particle.h>
16#include <analysis/utility/AnalysisConfiguration.h>
18#include <mdst/dataobjects/MCParticle.h>
20#include <framework/gearbox/Const.h>
21#include <framework/logging/Logger.h>
23#include <TDatabasePDG.h>
25#include <boost/variant/get.hpp>
26#include <boost/spirit/include/qi.hpp>
49 std::string::const_iterator iter = str.begin();
50 std::string::const_iterator end = str.end();
51 bool r = phrase_parse(iter, end, g, boost::spirit::unicode::space, s);
52 if (!r || iter != end)
return false;
65 B2WARNING(
"Could not initialise mother particle " << p->m_strName);
69 }
else if (
const DecayStringDecay* d = boost::get< DecayStringDecay > (&s)) {
73 B2WARNING(
"Could not initialise mother particle " << d->m_mother.m_strName);
78 if (d->m_strArrow ==
"->") {
81 }
else if (d->m_strArrow ==
"=norad=>") {
83 }
else if (d->m_strArrow ==
"=direct=>") {
85 }
else if (d->m_strArrow ==
"=exact=>") {
88 B2WARNING(
"Unknown arrow: " << d->m_strArrow);
94 if (d->m_daughters.empty()) {
98 int nDaughters = d->m_daughters.size();
99 for (
int iDaughter = 0; iDaughter < nDaughters; iDaughter++) {
101 m_isInitOK = daughter.init(d->m_daughters[iDaughter]);
103 B2WARNING(
"Could not initialise daughter!");
111 if ((std::find(d->m_keywords.begin(), d->m_keywords.end(),
"?nu")) != d->m_keywords.end()) {
115 if ((std::find(d->m_keywords.begin(), d->m_keywords.end(),
"?gamma")) != d->m_keywords.end()) {
119 if ((std::find(d->m_keywords.begin(), d->m_keywords.end(),
"...")) != d->m_keywords.end()) {
123 if ((std::find(d->m_keywords.begin(), d->m_keywords.end(),
"?addbrems")) != d->m_keywords.end()) {
141 B2WARNING(
"NULL pointer provided instead of particle.");
146 if (
const auto* part_test =
dynamic_cast<const Particle*
>(p))
147 iPDGCode_p = part_test->getPDGCode();
148 else if (
const auto* mc_test =
dynamic_cast<const MCParticle*
>(p))
149 iPDGCode_p = mc_test->getPDG();
151 B2WARNING(
"Template type not supported!");
155 int iPDGCodeCC_p = TDatabasePDG::Instance()->GetParticle(iPDGCode_p)->AntiParticle()->PdgCode();
157 if (abs(iPDGCode_d) != abs(iPDGCode_p))
return 0;
159 if (iPDGCode_p == iPDGCodeCC_p) iCC = 3;
160 else if (iPDGCode_d == iPDGCode_p) iCC = 1;
161 else if (iPDGCode_d == iPDGCodeCC_p) iCC = 2;
163 const std::vector<T*> daughterList = p->getDaughters();
164 int nDaughters_p = daughterList.size();
174 if (nDaughters_p == 0)
return 0;
184 vector< pair< int, int > > singlematch;
186 vector< pair< int, set<int> > > multimatch;
188 bool isAmbiguities =
false;
190 set<int> matches_global;
193 for (
int iDaughter_d = 0; iDaughter_d <
getNDaughters(); iDaughter_d++) {
195 for (
int jDaughter_p = 0; jDaughter_p < nDaughters_p; jDaughter_p++) {
196 const T* daughter = daughterList[jDaughter_p];
197 int iPDGCode_daughter_p = 0;
198 if (
const auto* part_test =
dynamic_cast<const Particle*
>(daughter))
199 iPDGCode_daughter_p = part_test->getPDGCode();
200 else if (
const auto* mc_test =
dynamic_cast<const MCParticle*
>(daughter))
201 iPDGCode_daughter_p = mc_test->getPDG();
205 matches_global.insert(jDaughter_p);
207 int iMatchResult =
m_daughters[iDaughter_d].match(daughter, jDaughter_p);
208 if (iMatchResult < 0) isAmbiguities =
true;
209 if (abs(iMatchResult) == 2 && iCC == 1)
continue;
210 if (abs(iMatchResult) == 1 && iCC == 2)
continue;
211 if (abs(iMatchResult) == 2 && iCC == 3)
continue;
212 matches.insert(jDaughter_p);
213 matches_global.insert(jDaughter_p);
215 if (matches.empty())
return 0;
216 if (matches.size() == 1) {
217 int jDaughter_p = *(matches.begin());
218 singlematch.emplace_back(iDaughter_d, jDaughter_p);
219 }
else multimatch.emplace_back(iDaughter_d, matches);
224 &&
int(matches_global.size()) != nDaughters_p)
return 0;
229 bool isModified =
true;
230 for (
int iTry = 0; iTry < 20; iTry++) {
232 if (!isModified)
break;
234 for (
auto& itMulti : multimatch) {
235 for (
auto& itSingle : singlematch) {
237 if (itMulti.second.erase(itSingle.second)) {
238 B2FATAL(
"Trying to execute part of the code with known bug, which is not fixed yet! Send email to anze.zupanc@ijs.si with notification that this happens!");
265 if (!multimatch.empty()) isAmbiguities =
true;
266 if (isAmbiguities)
return -iCC;
284 vector<const Particle*> selparticles;
286 int motherPDG = abs(particle->getPDGCode());
288 if (motherPDG != decayDescriptorMotherPDG)
289 B2ERROR(
"The PDG code of the mother particle (" << motherPDG <<
290 ") does not match the PDG code of the DecayDescriptor mother (" << decayDescriptorMotherPDG <<
291 ")! Check the order of the decay string is the same you expect in the reconstructed Particles.");
292 selparticles.push_back(particle);
295 for (
int iDaughter_d = 0; iDaughter_d < nDaughters_d; ++iDaughter_d) {
297 int iDaughter_p =
m_daughters[iDaughter_d].getMatchedDaughter();
301 if (iDaughter_p < 0) iDaughter_p = iDaughter_d;
302 const Particle* daughter = particle->getDaughter(iDaughter_p);
304 B2WARNING(
"Could not find daughter!");
308 int daughterPDG = abs(daughter->getPDGCode());
310 if (daughterPDG != decayDescriptorDaughterPDG) {
311 B2ERROR(
"The PDG code of the particle daughter (" << daughterPDG <<
312 ") does not match the PDG code of the DecayDescriptor daughter (" << decayDescriptorDaughterPDG <<
313 ")! Check the order of the decay string is the same you expect in the reconstructed Particles.");
316 vector<const Particle*> seldaughters =
m_daughters[iDaughter_d].getSelectionParticles(daughter);
317 selparticles.insert(selparticles.end(), seldaughters.begin(), seldaughters.end());
325 std::vector<int> decay, decaybar;
328 int pdg = daughter->getPDGCode();
329 decay.push_back(pdg);
333 std::sort(decay.begin(), decay.end());
334 std::sort(decaybar.begin(), decaybar.end());
342 vector<string> strNames;
345 vector<string> strDaughterNames = daughter.getSelectionNames();
346 int nDaughters = strDaughterNames.size();
347 for (
int iDaughter = 0; iDaughter < nDaughters; iDaughter++) {
358 strNames.insert(strNames.end(), strDaughterNames.begin(), strDaughterNames.end());
363 for (
auto itName = strNames.begin(); itName != strNames.end(); ++itName) {
364 if (count(itName, strNames.end(), *itName) == 1)
continue;
366 string strNameOld = *itName;
367 auto itOccurrence = strNames.begin();
369 while (iOccurrence <= 10) {
371 itOccurrence = find(itOccurrence, strNames.end(), strNameOld);
373 if (itOccurrence == strNames.end())
break;
375 string strNameNew = strNameOld + std::to_string(iOccurrence);
377 if (count(strNames.begin(), strNames.end(), strNameNew) == 0) {
378 *itOccurrence = strNameNew;
383 if (iOccurrence == 10) {
384 B2ERROR(
"DecayDescriptor::getSelectionNames - Something is wrong! More than 10x the same name!");
396 vector<int> listPDGDaughters = daughter.getSelectionPDGCodes();
397 listPDG.insert(listPDG.end(), listPDGDaughters.begin(), listPDGDaughters.end());
406 std::vector<std::vector<std::pair<int, std::string>>> hierarchy =
m_hierarchy;
409 std::vector<std::pair<int, std::string>> currentPath;
415 const std::vector<std::pair<int, std::string>>& currentPath)
418 for (std::size_t i = 0; i <
m_daughters.size(); i++) {
419 std::vector<std::pair<int, std::string>> newPath = currentPath;
421 std::vector<std::vector<std::pair<int, std::string>>> foundPathes =
m_daughters[i].getHierarchyOfSelected(newPath);
422 for (
auto& path : foundPathes)
m_hierarchy.push_back(path);
424 std::vector<std::vector<std::pair<int, std::string>>> hierarchy =
m_hierarchy;
static AnalysisConfiguration * instance()
Returns a pointer to the singleton instance.
int getPDGCode() const
PDG code.
static const ParticleType photon
photon particle
Represents a particle in the DecayDescriptor.
int getPDGCode() const
Return PDG code.
std::string getNameSimple() const
Return the name from getName() without + - * or anti-.
bool init(const DecayStringParticle &p)
initialise member variables from std::string member variables contained in a DecayStringParticle stru...
bool isSelected() const
Is the particle selected in the decay string?
The DecayDescriptor stores information about a decay tree or parts of a decay tree.
DecayDescriptor()
Default ctor.
bool isIgnoreBrems() const
Check if added Brems gammas shall be ignored.
bool isIgnoreRadiatedPhotons() const
Check if additional radiated photons shall be ignored.
bool init(const std::string &str)
Initialise the DecayDescriptor from given string.
bool isSelfConjugated() const
Is the decay or the particle self conjugated.
const DecayDescriptor * getDaughter(int i) const
return i-th daughter (0 based index).
DecayDescriptorParticle m_mother
Mother of the decay ('left side').
bool m_isInitOK
Is this object initialized correctly?
bool isIgnoreNeutrino() const
Check if missing neutrinos shall be ignored.
std::vector< int > getSelectionPDGCodes()
Return list of PDG codes of selected particles.
int getNDaughters() const
return number of direct daughters.
void resetMatch()
Reset results from previous call of the match() function.
bool isIgnoreMassive() const
Check if missing massive final state particles shall be ignored.
std::vector< std::vector< std::pair< int, std::string > > > getHierarchyOfSelected()
Function to get hierarchy of selected particles and their names (for python use)
bool isIgnoreGamma() const
Check if missing gammas shall be ignored.
std::vector< std::string > getSelectionNames()
Return list of human readable names of selected particles.
std::vector< DecayDescriptor > m_daughters
Direct daughters of the decaying particle.
std::vector< std::vector< std::pair< int, std::string > > > m_hierarchy
Collection of hierarchy paths of selected particles.
std::vector< const Particle * > getSelectionParticles(const Particle *particle)
Get a vector of pointers with selected daughters in the decay tree.
int m_iDaughter_p
ID of the Daughter Particle* matched to this DecayDescriptor.
int match(const T *p, int iDaughter_p)
Internally called by match(Particle*) and match(MCParticle*) function.
bool isIgnoreIntermediate() const
Check if intermediate resonances/particles shall be ignored.
const DecayDescriptorParticle * getMother() const
return mother.
int m_properties
Particle property.
A Class to store the Monte Carlo particle information.
Class to store reconstructed particles.
@ c_IsIgnoreNeutrino
Is the particle MC matched with the ignore missing neutrino flag set?
@ c_IsIgnoreRadiatedPhotons
Is the particle MC matched with the ignore radiated photon flag set?
@ c_IsIgnoreGamma
Is the particle MC matched with the ignore missing gamma flag set?
@ c_IsIgnoreBrems
Is the particle MC matched with the ignore added Brems gamma flag set?
@ c_IsIgnoreIntermediate
Is the particle MC matched with the ignore intermediate resonances flag set?
@ c_IsIgnoreMassive
Is the particle MC matched with the ignore missing massive particle flag set?
boost::variant< boost::recursive_wrapper< DecayStringDecay >, DecayStringParticle > DecayString
The DecayStringElement can be either a DecayStringDecay or a vector of mother particles.
bool hasAntiParticle(int pdgCode)
Checks if the particle with given pdg code has an anti-particle or not.
Abstract base class for different kinds of events.
Holds the information of a decay.
This class describes the grammar and the syntax elements of decay strings.
Holds the information of a particle in the decay string.