9 #include <analysis/utility/MCMatching.h>
10 #include <analysis/utility/AnalysisConfiguration.h>
12 #include <analysis/dataobjects/Particle.h>
13 #include <mdst/dataobjects/MCParticle.h>
15 #include <framework/datastore/StoreArray.h>
16 #include <framework/gearbox/Const.h>
17 #include <framework/logging/Logger.h>
19 #include <unordered_set>
28 if (flags == c_Correct)
36 case c_MissFSR : s +=
"c_MissFSR";
break;
37 case c_MissingResonance : s +=
"c_MissingResonance";
break;
38 case c_DecayInFlight : s +=
"c_DecayInFlight";
break;
39 case c_MissNeutrino : s +=
"c_MissNeutrino";
break;
40 case c_MissGamma : s +=
"c_MissGamma";
break;
41 case c_MissMassiveParticle : s +=
"c_MissMassiveParticle";
break;
42 case c_MissKlong : s +=
"c_MissKlong";
break;
43 case c_MisID : s +=
"c_MisID";
break;
44 case c_AddedWrongParticle : s +=
"c_AddedWrongParticle";
break;
45 case c_InternalError : s +=
"c_InternalError";
break;
46 case c_MissPHOTOS : s +=
"c_MissPHOTOS";
break;
47 case c_AddedRecoBremsPhoton : s +=
"c_AddedRecoBremsPhoton";
break;
50 B2ERROR(
"MCMatching::explainFlags() doesn't know about flag " << f <<
", please update it.");
64 genMCPMothers.push_back(mcP->
getIndex());
74 for (
unsigned int i = lastMother; i < firstMothers.size(); i++) {
75 if (firstMothers[i] == idx)
90 if (particle->hasExtraInfo(c_extraInfoMCErrors))
98 int nChildren = particle->getNDaughters();
105 bool daugMCTruth =
true;
106 for (
int i = 0; i < nChildren; ++i) {
107 const Particle* daugP = particle->getDaughter(i);
109 daugMCTruth &= setMCTruth(daugP);
115 if (nChildren == 1) {
117 const Particle* daugP = particle->getDaughter(0);
131 vector<int> firstDaugMothers;
134 for (
int i = 0; i < nChildren; ++i) {
135 const Particle* daugP = particle->getDaughter(i);
139 fillGenMothers(daugMCP, firstDaugMothers);
141 lastMother = findCommonMother(daugMCP, firstDaugMothers, lastMother);
142 if (lastMother == -1)
147 motherIndex = firstDaugMothers[lastMother];
160 B2ERROR(
"setMCTruth(): sanity check failed!");
164 const MCParticle* mcMatch = mcParticles[motherIndex - 1];
165 particle->addRelationTo(mcMatch);
174 void appendParticles(
const Particle* p, unordered_set<const MCParticle*>& mcMatchedParticles)
176 for (
unsigned i = 0; i < p->getNDaughters(); ++i) {
177 const Particle* daug = p->getDaughter(i);
182 mcMatchedParticles.insert(mcParticle);
184 if (daug->getNDaughters() != 0) {
186 appendParticles(daug, mcMatchedParticles);
197 mcMatchedParticles.insert(mcParticle);
210 void appendParticles(
const MCParticle* gen, vector<const MCParticle*>& children)
215 const vector<MCParticle*>& genDaughters = gen->
getDaughters();
216 for (
auto daug : genDaughters) {
217 children.push_back(daug);
218 appendParticles(daug, children);
225 const int property = part->getProperty();
227 const int absPDG = abs(mcDaug->
getPDG());
231 if (property & Particle::PropertyFlags::c_IsIgnoreIntermediate)
236 if (property & Particle::PropertyFlags::c_IsIgnoreRadiatedPhotons)
239 if (property & Particle::PropertyFlags::c_IsIgnoreGamma)
242 }
else if (absPDG == 12 or absPDG == 14 or absPDG == 16) {
243 if (property & Particle::PropertyFlags::c_IsIgnoreNeutrino)
246 if (property & Particle::PropertyFlags::c_IsIgnoreMassive)
254 void appendAcceptedMissingDaughters(
const Particle* p, unordered_set<const MCParticle*>& acceptedParticles)
258 vector<const MCParticle*> genDaughters;
259 appendParticles(mcParticle, genDaughters);
261 for (
auto mcDaug : genDaughters) {
262 if (isDaughterAccepted(mcDaug, p))
263 acceptedParticles.insert(mcDaug);
265 acceptedParticles.erase(mcDaug);
269 for (
unsigned i = 0; i < p->getNDaughters(); ++i) {
270 const Particle* daug = p->getDaughter(i);
271 appendAcceptedMissingDaughters(daug, acceptedParticles);
281 if (particle->hasExtraInfo(c_extraInfoMCErrors)) {
282 return particle->getExtraInfo(c_extraInfoMCErrors);
285 mcParticle = particle->getRelatedTo<
MCParticle>();
286 return setMCErrorsExtraInfo(
const_cast<Particle*
>(particle), mcParticle);
292 auto setStatus = [](
Particle * part,
int s) ->
int {
293 part->addExtraInfo(c_extraInfoMCErrors, s);
298 return setStatus(particle, MCErrorFlags::c_InternalError);
300 if (particle->getNDaughters() == 0) {
302 return setStatus(particle, getFlagsOfFSP(particle, mcParticle));;
315 if (mother and particle->getPDGCode() == mother->getPDG() and getNumberOfDaughtersWithoutNeutrinos(mother) == 1
316 and !particle->hasExtraInfo(
"bremsCorrected")) {
317 if (abs(mother->getPDG()) != 15 and abs(mcParticle->
getPDG()) != 15) {
318 B2WARNING(
"Special treatment in MCMatching for tau is called for a non-tau particle. Check if you discovered another special case here, or if we have a bug! "
319 << mother->getPDG() <<
" " << particle->getPDGCode() <<
" " << mcParticle->
getPDG());
322 if (not(particle->getProperty() & Particle::PropertyFlags::c_IsIgnoreIntermediate))
323 status |= MCErrorFlags::c_MissingResonance;
324 }
else if (!(particle->getProperty() & Particle::PropertyFlags::c_IsUnspecified)) {
326 status |= MCErrorFlags::c_AddedWrongParticle;
330 status |= getFlagsOfDaughters(particle, mcParticle);
332 status |= getMissingParticleFlags(particle, mcParticle);
335 status &= ~(getFlagsIgnoredByProperty(particle));
337 return setStatus(particle, status);
342 if (particle->getPDGCode() == mcParticle->
getPDG())
343 return MCErrorFlags::c_Correct;
348 return MCErrorFlags::c_MisID;
351 int status = MCErrorFlags::c_DecayInFlight;
359 status |= MCErrorFlags::c_InternalError;
360 }
else if (particle->getPDGCode() != primary->
getPDG()) {
362 status |= MCErrorFlags::c_MisID;
370 unsigned nChildren = particle->getNDaughters();
373 vector<const MCParticle*> genParts;
375 if (particle->hasExtraInfo(
"bremsCorrected") && nChildren > 1) {
376 if (mcParticle && mcParticle->
getMother())
377 appendParticles(mcParticle->
getMother(), genParts);
380 int daughterStatuses = 0;
381 vector<int> daughterProperties = particle->getDaughterProperties();
382 for (
unsigned i = 0; i < nChildren; ++i) {
383 const Particle* daughter = particle->getDaughter(i);
384 int daughterStatus = 0;
387 daughterStatus |= getFlagsOfBremsPhotonDaughter(daughter, mcParticle, genParts);
389 daughterStatus |= getMCErrors(daughter);
392 int daughterStatusAcceptMask = (~c_Correct);
393 if (i < daughterProperties.size())
394 daughterStatusAcceptMask = makeDaughterAcceptMask(daughterProperties[i]);
396 daughterStatuses |= (daughterStatus & daughterStatusAcceptMask);
400 const int daughterStatusesAcceptMask = c_MisID | c_AddedWrongParticle | c_DecayInFlight | c_InternalError | c_AddedRecoBremsPhoton;
401 return (daughterStatuses & daughterStatusesAcceptMask);
407 const vector<const MCParticle*>& genParts)
410 int daughterStatus = getMCErrors(daughter);
416 daughterStatus &= (~c_InternalError);
417 daughterStatus |= c_AddedRecoBremsPhoton;
420 else if (mcDaughter == mcParticle) {
421 daughterStatus &= (~c_MisID);
424 else if (std::find(genParts.begin(), genParts.end(), mcDaughter) == genParts.end()) {
425 daughterStatus |= c_AddedRecoBremsPhoton;
429 return daughterStatus;
435 unsigned int number_of_neutrinos = 0;
436 for (
auto& p : daughters) {
437 auto pdg = abs(p->getPDG());
438 if (pdg == 12 || pdg == 14 || pdg == 16) {
439 number_of_neutrinos++;
442 return daughters.size() - number_of_neutrinos;
479 B2ERROR(
"The hell? why would this gamma not have a mother?");
483 int ndaug = mother->getNDaughters();
503 vector<const MCParticle*> genParts;
504 appendParticles(mcParticle, genParts);
506 unordered_set<const MCParticle*> mcMatchedParticles;
507 appendParticles(particle, mcMatchedParticles);
508 unordered_set<const MCParticle*> acceptedParticles;
509 appendAcceptedMissingDaughters(particle, acceptedParticles);
510 for (
auto part : acceptedParticles) {
511 mcMatchedParticles.insert(part);
518 if (mcMatchedParticles.find(genPart) != mcMatchedParticles.end())
522 const int generatedPDG = genPart->getPDG();
523 const int absGeneratedPDG = abs(generatedPDG);
525 if (!
isFSP(generatedPDG)) {
526 flags |= c_MissingResonance;
529 if (flags & (c_MissFSR | c_MissGamma)) {
532 if (isFSRLegacy(genPart)) {
534 flags |= c_MissPHOTOS;
536 flags |= c_MissGamma;
543 flags |= c_MissPHOTOS;
545 flags |= c_MissGamma;
547 }
else if (absGeneratedPDG == 12 || absGeneratedPDG == 14 || absGeneratedPDG == 16) {
548 flags |= c_MissNeutrino;
550 flags |= c_MissMassiveParticle;
552 flags |= c_MissKlong;
560 unordered_set<const MCParticle*> mcMatchedParticles;
563 appendParticles(particle, mcMatchedParticles);
564 vector<const MCParticle*> genParts;
565 appendParticles(mcParticle, genParts);
567 int nMissingDaughter = 0;
570 const bool missing = (mcMatchedParticles.find(genPart) == mcMatchedParticles.end());
573 const int generatedPDG = genPart->getPDG();
574 const int absGeneratedPDG = abs(generatedPDG);
576 auto result = find(daughterPDG.begin(), daughterPDG.end(), absGeneratedPDG);
577 if (result != daughterPDG.end())
582 return nMissingDaughter;
598 if (daughterProperty & Particle::PropertyFlags::c_IsIgnoreMisID) flags |= (
MCMatching::c_MisID);
static AnalysisConfiguration * instance()
Returns a pointer to the singleton instance.
int getPDGCode() const
PDG code.
static const ParticleType Klong
K^0_L particle.
static const ParticleType photon
photon particle
A Class to store the Monte Carlo particle information.
@ c_IsFSRPhoton
bit 7: Particle is from finial state radiation
@ c_IsPHOTOSPhoton
bit 8: Particle is an radiative photon from PHOTOS
@ c_IsRadiativePhoton
combined flag to test whether the particle is radiative
@ c_PrimaryParticle
bit 0: Particle is primary particle.
int getIndex() const
Get 1-based index of the particle in the corresponding MCParticle list.
std::vector< Belle2::MCParticle * > getDaughters() const
Get vector of all daughter particles, empty vector if none.
bool hasStatus(unsigned short int bitmask) const
Return if specific status bit is set.
int getPDG() const
Return PDG code of particle.
Class to store reconstructed particles.
EFlavorType
describes flavor type, see getFlavorType().
@ c_Unflavored
Is its own antiparticle or we don't know whether it is a particle/antiparticle.
@ c_Flavored
Is either particle or antiparticle.
TO * getRelatedTo(const std::string &name="", const std::string &namedRelation="") const
Get the object to which this object has a relation.
int getEntries() const
Get the number of objects in the array.
bool isFSP(int pdg)
defines what is a final state particle for this purpose.
MCParticle * getMother() const
Returns a pointer to the mother particle.
Abstract base class for different kinds of events.
static int countMissingParticle(const Belle2::Particle *particle, const Belle2::MCParticle *mcParticle, const std::vector< int > &daughterPDG)
Count the number of missing daughters of the 'particle'.
static std::string explainFlags(unsigned int flags)
Return string with all human-readable flags, e.g.
@ c_DecayInFlight
A Particle was reconstructed from the secondary decay product of the actual particle.
@ c_MisID
One of the charged final state particles is mis-identified.
@ c_AddedRecoBremsPhoton
A photon added with the bremsstrahlung recovery tools (correctBrems or correctBremsBelle) has no MC p...
static bool isRadiativePhoton(const Belle2::MCParticle *p)
Returns true if given MCParticle is a radiative photon.
static int makeDaughterAcceptMask(int daughterProperty)
Returns the daughter mask from given daughterProperty.
static int getNumberOfDaughtersWithoutNeutrinos(const MCParticle *mcParticle)
Determines the number of daughter particles which are not neutrinos.
static int getFlagsOfBremsPhotonDaughter(const Particle *daughter, const MCParticle *mcParticle, const std::vector< const MCParticle * > &genParts)
Returns flags of given daughter which is a brems photon.
static bool setMCTruth(const Belle2::Particle *particle)
This is the main function of MC matching algorithm.
static int getFlagsOfFSP(const Particle *particle, const MCParticle *mcParticle)
Returns flags of given Final State Particle.
static int getMCErrors(const Belle2::Particle *particle, const Belle2::MCParticle *mcParticle=nullptr)
Returns quality indicator of the match as a bit pattern where the individual bits indicate the the ty...
static int getFlagsOfDaughters(const Particle *daughter, const MCParticle *mcParticle)
Returns flags of daughters of given particle.
static bool isFSR(const Belle2::MCParticle *p)
Returns true if given MCParticle is a final state radiation (FSR) photon based on MCParticle::c_IsFSR...
static bool isFSRLegacy(const Belle2::MCParticle *p)
Returns true if given MCParticle is a final state radiation (FSR) photon.
static void fillGenMothers(const Belle2::MCParticle *mcP, std::vector< int > &genMCPMothers)
Fills vector with array (1-based) indices of all generator ancestors of given MCParticle.
static int setMCErrorsExtraInfo(Belle2::Particle *particle, const Belle2::MCParticle *mcParticle)
Sets error flags in extra-info (also returns it).
static int getFlagsIgnoredByProperty(const Belle2::Particle *particle)
Returns the flags ignored by PropertyFlags of given particle.
static int getMissingParticleFlags(const Belle2::Particle *particle, const Belle2::MCParticle *mcParticle)
Determines which daughters of 'mcParticle' are not reconstructed by any daughter of 'particle'.
static bool isFSP(int pdg)
Returns true if given PDG code indicates a FSP.
static const std::string c_extraInfoMCErrors
Name of extra-info field stored in Particle.
static int findCommonMother(const Belle2::MCParticle *mcP, const std::vector< int > &firstMothers, int lastMother)
Finds a mother of mcP that is in firstMothers, from [lastMother, end].