10#include <analysis/variables/MCTruthVariables.h> 
   13#include <analysis/VariableManager/Manager.h> 
   15#include <analysis/dataobjects/Particle.h> 
   16#include <analysis/dataobjects/TauPairDecay.h> 
   17#include <analysis/utility/MCMatching.h> 
   18#include <analysis/utility/ReferenceFrame.h> 
   19#include <analysis/utility/ValueIndexPairSorting.h> 
   21#include <mdst/dataobjects/MCParticle.h> 
   22#include <mdst/dataobjects/ECLCluster.h> 
   23#include <mdst/dataobjects/Track.h> 
   26#include <framework/datastore/StoreArray.h> 
   27#include <framework/datastore/StoreObjPtr.h> 
   28#include <framework/dataobjects/EventMetaData.h> 
   29#include <framework/gearbox/Const.h> 
   30#include <framework/logging/Logger.h> 
   31#include <framework/database/DBObjPtr.h> 
   32#include <framework/dbobjects/BeamParameters.h> 
   34#include <Math/VectorUtil.h> 
   46    double isSignal(
const Particle* part)
 
   48      const MCParticle* mcparticle = part->getMCParticle();
 
   55    double isSignalAcceptWrongFSPs(
const Particle* part)
 
   57      const MCParticle* mcparticle = part->getMCParticle();
 
   62      status &= (~MCMatching::c_MisID);
 
   63      status &= (~MCMatching::c_AddedWrongParticle);
 
   68    double isPrimarySignal(
const Particle* part)
 
   70      return (isSignal(part) > 0.5 and particleMCPrimaryParticle(part) > 0.5);
 
   73    double isMisidentified(
const Particle* part)
 
   75      const MCParticle* mcp = part->getMCParticle();
 
   81    double isWrongCharge(
const Particle* part)
 
   83      const MCParticle* mcp = part->getMCParticle();
 
   85      return (part->getCharge() != mcp->getCharge());
 
   88    double isCloneTrack(
const Particle* particle)
 
   94      const auto mcpww = particle->getRelatedToWithWeight<MCParticle>();
 
   96      return (mcpww.second < 0);
 
   99    double isOrHasCloneTrack(
const Particle* particle)
 
  102      std::queue<const Particle*> qq;
 
  104      while (!qq.empty()) {
 
  105        const auto d = qq.front(); 
 
  107        if (isCloneTrack(d) == 1.0) 
return 1.0;
 
  108        size_t nDau = d->getNDaughters(); 
 
  109        for (
size_t iDau = 0; iDau < nDau; ++iDau)
 
  110          qq.push(d->getDaughter(iDau));
 
  115    double genNthMotherPDG(
const Particle* part, 
const std::vector<double>& args)
 
  117      const MCParticle* mcparticle = part->getMCParticle();
 
  118      if (!mcparticle) 
return 0.0;
 
  120      unsigned int nLevels = args.empty() ? 0 : args[0];
 
  122      const MCParticle* curMCParticle = mcparticle;
 
  123      for (
unsigned int i = 0; i <= nLevels; ++i) {
 
  124        const MCParticle* curMCMother = curMCParticle->getMother();
 
  125        if (!curMCMother) 
return 0.0;
 
  126        curMCParticle = curMCMother;
 
  128      return curMCParticle->getPDG();
 
  131    double genNthMotherIndex(
const Particle* part, 
const std::vector<double>& args)
 
  133      const MCParticle* mcparticle = part->getMCParticle();
 
  134      if (!mcparticle) 
return 0.0;
 
  136      unsigned int nLevels = args.empty() ? 0 : args[0];
 
  138      const MCParticle* curMCParticle = mcparticle;
 
  139      for (
unsigned int i = 0; i <= nLevels; ++i) {
 
  140        const MCParticle* curMCMother = curMCParticle->getMother();
 
  141        if (!curMCMother) 
return 0.0;
 
  142        curMCParticle = curMCMother;
 
  144      return curMCParticle->getArrayIndex();
 
  147    double genQ2PmPd(
const Particle* part, 
const std::vector<double>& daughter_indices)
 
  149      const MCParticle* mcparticle = part->getMCParticle();
 
  152      auto daughters = mcparticle->getDaughters();
 
  154      ROOT::Math::PxPyPzEVector  p4Daughters;
 
  155      for (
auto& double_daughter : daughter_indices) {
 
  156        unsigned long daughter = std::lround(double_daughter);
 
  159        p4Daughters += daughters[daughter]->get4Vector();
 
  161      auto p4Mother = mcparticle->get4Vector();
 
  162      return (p4Mother - p4Daughters).mag2();
 
  165    double genMotherPDG(
const Particle* part)
 
  167      return genNthMotherPDG(part, {});
 
  170    double genMotherP(
const Particle* part)
 
  172      const MCParticle* mcparticle = part->getMCParticle();
 
  175      const MCParticle* mcmother = mcparticle->getMother();
 
  178      return mcmother->getMomentum().R();
 
  181    double genMotherIndex(
const Particle* part)
 
  183      return genNthMotherIndex(part, {});
 
  186    double genParticleIndex(
const Particle* part)
 
  188      const MCParticle* mcparticle = part->getMCParticle();
 
  190      return mcparticle->getArrayIndex();
 
  193    double isSignalAcceptMissingNeutrino(
const Particle* part)
 
  195      const MCParticle* mcparticle = part->getMCParticle();
 
  200      status &= (~MCMatching::c_MissNeutrino);
 
  205    double isSignalAcceptMissingMassive(
const Particle* part)
 
  207      const MCParticle* mcparticle = part->getMCParticle();
 
  212      status &= (~MCMatching::c_MissMassiveParticle);
 
  213      status &= (~MCMatching::c_MissKlong);
 
  218    double isSignalAcceptMissingGamma(
const Particle* part)
 
  220      const MCParticle* mcparticle = part->getMCParticle();
 
  225      status &= (~MCMatching::c_MissGamma);
 
  230    double isSignalAcceptMissing(
const Particle* part)
 
  232      const MCParticle* mcparticle = part->getMCParticle();
 
  237      status &= (~MCMatching::c_MissGamma);
 
  238      status &= (~MCMatching::c_MissMassiveParticle);
 
  239      status &= (~MCMatching::c_MissKlong);
 
  240      status &= (~MCMatching::c_MissNeutrino);
 
  245    double isSignalAcceptBremsPhotons(
const Particle* part)
 
  247      const MCParticle* mcparticle = part->getMCParticle();
 
  252      status &= (~MCMatching::c_AddedRecoBremsPhoton);
 
  257    double particleMCMatchPDGCode(
const Particle* part)
 
  259      const MCParticle* mcparticle = part->getMCParticle();
 
  261      return mcparticle->getPDG();
 
  264    double particleMCErrors(
const Particle* part)
 
  269    double particleNumberOfMCMatch(
const Particle* particle)
 
  271      RelationVector<MCParticle> mcRelations = particle->getRelationsTo<MCParticle>();
 
  272      return (mcRelations.size());
 
  275    double particleMCMatchWeight(
const Particle* particle)
 
  277      auto relWithWeight = particle->getRelatedToWithWeight<MCParticle>();
 
  279      return relWithWeight.second;
 
  282    double particleMCMatchDecayTime(
const Particle* part)
 
  284      const MCParticle* mcparticle = part->getMCParticle();
 
  286      return mcparticle->getDecayTime();
 
  289    double particleMCMatchLifeTime(
const Particle* part)
 
  291      const MCParticle* mcparticle = part->getMCParticle();
 
  293      return mcparticle->getLifetime();
 
  296    double particleMCMatchPX(
const Particle* part)
 
  298      const MCParticle* mcparticle = part->getMCParticle();
 
  302      ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
 
  303      return frame.getMomentum(mcpP4).Px();
 
  306    double particleMCMatchPY(
const Particle* part)
 
  308      const MCParticle* mcparticle = part->getMCParticle();
 
  312      ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
 
  313      return frame.getMomentum(mcpP4).Py();
 
  316    double particleMCMatchPZ(
const Particle* part)
 
  318      const MCParticle* mcparticle = part->getMCParticle();
 
  322      ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
 
  323      return frame.getMomentum(mcpP4).Pz();
 
  326    double particleMCMatchPT(
const Particle* part)
 
  328      const MCParticle* mcparticle = part->getMCParticle();
 
  332      ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
 
  333      return frame.getMomentum(mcpP4).Pt();
 
  336    double particleMCMatchE(
const Particle* part)
 
  338      const MCParticle* mcparticle = part->getMCParticle();
 
  342      ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
 
  343      return frame.getMomentum(mcpP4).E();
 
  346    double particleMCMatchP(
const Particle* part)
 
  348      const MCParticle* mcparticle = part->getMCParticle();
 
  352      ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
 
  353      return frame.getMomentum(mcpP4).P();
 
  356    double particleMCMatchTheta(
const Particle* part)
 
  358      const MCParticle* mcparticle = part->getMCParticle();
 
  362      ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
 
  363      return frame.getMomentum(mcpP4).Theta();
 
  366    double particleMCMatchPhi(
const Particle* part)
 
  368      const MCParticle* mcparticle = part->getMCParticle();
 
  372      ROOT::Math::PxPyPzEVector mcpP4 = mcparticle->get4Vector();
 
  373      return frame.getMomentum(mcpP4).Phi();
 
  376    double mcParticleNDaughters(
const Particle* part)
 
  378      const MCParticle* mcparticle = part->getMCParticle();
 
  381      return mcparticle->getNDaughters();
 
  384    double particleMCRecoilMass(
const Particle* part)
 
  386      StoreArray<MCParticle> mcparticles;
 
  389      ROOT::Math::PxPyPzEVector pInitial = mcparticles[0]->get4Vector();
 
  390      ROOT::Math::PxPyPzEVector pDaughters;
 
  391      const std::vector<Particle*> daughters = part->getDaughters();
 
  392      for (
auto daughter : daughters) {
 
  393        const MCParticle* mcD = daughter->getMCParticle();
 
  396        pDaughters += mcD->get4Vector();
 
  398      return (pInitial - pDaughters).M();
 
  401    ROOT::Math::PxPyPzEVector MCInvisibleP4(
const MCParticle* mcparticle)
 
  403      ROOT::Math::PxPyPzEVector ResultP4;
 
  404      int pdg = std::abs(mcparticle->getPDG());
 
  405      bool isNeutrino = (pdg == 12 or pdg == 14 or pdg == 16);
 
  407      if (mcparticle->getNDaughters() > 0) {
 
  408        const std::vector<MCParticle*> daughters = mcparticle->getDaughters();
 
  409        for (
auto daughter : daughters)
 
  410          ResultP4 += MCInvisibleP4(daughter);
 
  411      } 
else if (isNeutrino)
 
  412        ResultP4 += mcparticle->get4Vector();
 
  417    double particleMCCosThetaBetweenParticleAndNominalB(
const Particle* part)
 
  419      int particlePDG = abs(part->getPDGCode());
 
  420      if (particlePDG != 511 and particlePDG != 521)
 
  421        B2FATAL(
"The variable mcCosThetaBetweenParticleAndNominalB is only meant to be used on B mesons!");
 
  424      double e_Beam = T.getCMSEnergy() / 2.0; 
 
  425      double m_B = part->getPDGMass();
 
  428      const double  mY4S = 10.5794; 
 
  431      if (e_Beam * e_Beam - m_B * m_B < 0) {
 
  434      double p_B = std::sqrt(e_Beam * e_Beam - m_B * m_B);
 
  437      const MCParticle* mcB = part->getMCParticle();
 
  440      int mcParticlePDG = std::abs(mcB->getPDG());
 
  441      if (mcParticlePDG != 511 and mcParticlePDG != 521)
 
  444      ROOT::Math::PxPyPzEVector p = T.rotateLabToCms() * (mcB->get4Vector() - MCInvisibleP4(mcB));
 
  449      double theta_BY = (2 * e_Beam * e_d - m_B * m_B - m_d * m_d)
 
  454    double mcParticleSecondaryPhysicsProcess(
const Particle* p)
 
  456      const MCParticle* mcp = p->getMCParticle();
 
  458      return mcp->getSecondaryPhysicsProcess();
 
  461    double mcParticleStatus(
const Particle* p)
 
  463      const MCParticle* mcp = p->getMCParticle();
 
  465      return mcp->getStatus();
 
  468    double particleMCPrimaryParticle(
const Particle* p)
 
  470      const MCParticle* mcp = p->getMCParticle();
 
  474      return mcp->hasStatus(bitmask);
 
  477    double particleMCVirtualParticle(
const Particle* p)
 
  479      const MCParticle* mcp = p->getMCParticle();
 
  483      return mcp->hasStatus(bitmask);
 
  486    double particleMCInitialParticle(
const Particle* p)
 
  488      const MCParticle* mcp = p->getMCParticle();
 
  492      return mcp->hasStatus(bitmask);
 
  495    double particleMCISRParticle(
const Particle* p)
 
  497      const MCParticle* mcp = p->getMCParticle();
 
  501      return mcp->hasStatus(bitmask);
 
  504    double particleMCFSRParticle(
const Particle* p)
 
  506      const MCParticle* mcp = p->getMCParticle();
 
  510      return mcp->hasStatus(bitmask);
 
  513    double particleMCPhotosParticle(
const Particle* p)
 
  515      const MCParticle* mcp = p->getMCParticle();
 
  519      return mcp->hasStatus(bitmask);
 
  522    double generatorEventWeight(
const Particle*)
 
  524      StoreObjPtr<EventMetaData> evtMetaData;
 
  526      return evtMetaData->getGeneratedWeight();
 
  529    int tauPlusMcMode(
const Particle*)
 
  531      StoreObjPtr<TauPairDecay> tauDecay;
 
  533        B2WARNING(
"Cannot find tau decay ID, did you forget to run TauDecayMarkerModule?");
 
  536      return tauDecay->getTauPlusIdMode();
 
  539    int tauMinusMcMode(
const Particle*)
 
  541      StoreObjPtr<TauPairDecay> tauDecay;
 
  543        B2WARNING(
"Cannot find tau decay ID, did you forget to run TauDecayMarkerModule?");
 
  546      return tauDecay->getTauMinusIdMode();
 
  549    int tauPlusMcProng(
const Particle*)
 
  551      StoreObjPtr<TauPairDecay> tauDecay;
 
  553        B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
 
  556      return tauDecay->getTauPlusMcProng();
 
  559    int tauMinusMcProng(
const Particle*)
 
  561      StoreObjPtr<TauPairDecay> tauDecay;
 
  563        B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
 
  566      return tauDecay->getTauMinusMcProng();
 
  569    double tauPlusEgstar(
const Particle*)
 
  571      StoreObjPtr<TauPairDecay> tauDecay;
 
  573        B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
 
  576      return tauDecay->getTauPlusEgstar();
 
  579    double tauMinusEgstar(
const Particle*)
 
  581      StoreObjPtr<TauPairDecay> tauDecay;
 
  583        B2WARNING(
"Cannot find tau prong, did you forget to run TauDecayMarkerModule?");
 
  586      return tauDecay->getTauMinusEgstar();
 
  589    double isReconstructible(
const Particle* p)
 
  591      if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
 
  593      const MCParticle* mcp = p->getMCParticle();
 
  598      return (std::abs(mcp->getCharge()) > 0) ? seenInSVD(p) : seenInECL(p);
 
  601    double isTrackFound(
const Particle* p)
 
  603      if (p->getParticleSource() != Particle::EParticleSourceObject::c_MCParticle)
 
  605      const MCParticle* tmp_mcP = p->getMCParticle();
 
  608      Track* tmp_track = tmp_mcP->getRelated<Track>();
 
  610        const TrackFitResult* tmp_tfr = tmp_track->getTrackFitResultWithClosestMass(Const::ChargedStable(std::abs(tmp_mcP->getPDG())));
 
  615        if (tmp_tfr->getChargeSign()*tmp_mcP->getCharge() > 0)
 
  623    double seenInPXD(
const Particle* p)
 
  625      if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
 
  627      const MCParticle* mcp = p->getMCParticle();
 
  629      return mcp->hasSeenInDetector(Const::PXD);
 
  632    double seenInSVD(
const Particle* p)
 
  634      if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
 
  636      const MCParticle* mcp = p->getMCParticle();
 
  638      return mcp->hasSeenInDetector(Const::SVD);
 
  641    double seenInCDC(
const Particle* p)
 
  643      if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
 
  645      const MCParticle* mcp = p->getMCParticle();
 
  647      return mcp->hasSeenInDetector(Const::CDC);
 
  650    double seenInTOP(
const Particle* p)
 
  652      if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
 
  654      const MCParticle* mcp = p->getMCParticle();
 
  656      return mcp->hasSeenInDetector(Const::TOP);
 
  659    double seenInECL(
const Particle* p)
 
  661      if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
 
  663      const MCParticle* mcp = p->getMCParticle();
 
  665      return mcp->hasSeenInDetector(Const::ECL);
 
  668    double seenInARICH(
const Particle* p)
 
  670      if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
 
  672      const MCParticle* mcp = p->getMCParticle();
 
  674      return mcp->hasSeenInDetector(Const::ARICH);
 
  677    double seenInKLM(
const Particle* p)
 
  679      if (p->getParticleSource() == Particle::EParticleSourceObject::c_Composite)
 
  681      const MCParticle* mcp = p->getMCParticle();
 
  683      return mcp->hasSeenInDetector(Const::KLM);
 
  686    int genNStepsToDaughter(
const Particle* p, 
const std::vector<double>& arguments)
 
  688      if (arguments.size() != 1)
 
  689        B2FATAL(
"Wrong number of arguments for genNStepsToDaughter");
 
  691      const MCParticle* mcp = p->getMCParticle();
 
  693        B2WARNING(
"No MCParticle is associated to the particle");
 
  697      int nChildren = p->getNDaughters();
 
  698      if (arguments[0] >= nChildren) {
 
  702      const Particle*   daugP   = p->getDaughter(arguments[0]);
 
  703      const MCParticle* daugMCP = daugP->getMCParticle();
 
  707        B2WARNING(
"No MCParticle is associated to the i-th daughter");
 
  711      if (nChildren == 1) 
return 1;
 
  713      std::vector<int> genMothers;
 
  715      auto match = std::find(genMothers.begin(), genMothers.end(), mcp->getIndex());
 
  716      return match - genMothers.begin();
 
  719    int genNMissingDaughter(
const Particle* p, 
const std::vector<double>& arguments)
 
  721      if (arguments.size() < 1)
 
  722        B2FATAL(
"Wrong number of arguments for genNMissingDaughter");
 
  724      const std::vector<int> PDGcodes(arguments.begin(), arguments.end());
 
  726      const MCParticle* mcp = p->getMCParticle();
 
  728        B2WARNING(
"No MCParticle is associated to the particle");
 
  735    double getHEREnergy(
const Particle*)
 
  737      static DBObjPtr<BeamParameters> beamParamsDB;
 
  738      if (!beamParamsDB.isValid())
 
  740      return (beamParamsDB->getHER()).E();
 
  743    double getLEREnergy(
const Particle*)
 
  745      static DBObjPtr<BeamParameters> beamParamsDB;
 
  746      if (!beamParamsDB.isValid())
 
  748      return (beamParamsDB->getLER()).E();
 
  751    double getCrossingAngleX(
const Particle*)
 
  754      static DBObjPtr<BeamParameters> beamParamsDB;
 
  755      if (!beamParamsDB.isValid())
 
  757      ROOT::Math::PxPyPzEVector herVec = beamParamsDB->getHER();
 
  758      ROOT::Math::PxPyPzEVector lerVec = beamParamsDB->getLER();
 
  763      return ROOT::Math::VectorUtil::Angle(herVec, -lerVec);
 
  766    double getCrossingAngleY(
const Particle*)
 
  769      static DBObjPtr<BeamParameters> beamParamsDB;
 
  770      if (!beamParamsDB.isValid())
 
  772      ROOT::Math::PxPyPzEVector herVec = beamParamsDB->getHER();
 
  773      ROOT::Math::PxPyPzEVector lerVec = beamParamsDB->getLER();
 
  778      return ROOT::Math::VectorUtil::Angle(herVec, -lerVec);
 
  782    double particleClusterMatchWeight(
const Particle* particle)
 
  790      const MCParticle* matchedToParticle = particle->getMCParticle();
 
  792      int matchedToIndex = matchedToParticle->getArrayIndex();
 
  794      const ECLCluster* cluster = particle->getECLCluster();
 
  797      const auto mcps = cluster->getRelationsTo<MCParticle>();
 
  798      for (
unsigned int i = 0; i < mcps.size(); ++i)
 
  799        if (mcps[i]->getArrayIndex() == matchedToIndex)
 
  800          return mcps.weight(i);
 
  805    double particleClusterBestMCMatchWeight(
const Particle* particle)
 
  817      const ECLCluster* cluster = particle->getECLCluster();
 
  823      auto mcps = cluster->getRelationsTo<MCParticle>();
 
  826      std::vector<double> weights;
 
  827      for (
unsigned int i = 0; i < mcps.size(); ++i)
 
  828        weights.emplace_back(mcps.weight(i));
 
  831      std::sort(weights.begin(), weights.end());
 
  832      std::reverse(weights.begin(), weights.end());
 
  836    double particleClusterBestMCPDGCode(
const Particle* particle)
 
  846      const ECLCluster* cluster = particle->getECLCluster();
 
  849      auto mcps = cluster->getRelationsTo<MCParticle>();
 
  852      std::vector<std::pair<double, int>> weightsAndIndices;
 
  853      for (
unsigned int i = 0; i < mcps.size(); ++i)
 
  854        weightsAndIndices.emplace_back(mcps.weight(i), i);
 
  857      std::sort(weightsAndIndices.begin(), weightsAndIndices.end(),
 
  858                ValueIndexPairSorting::higherPair<
decltype(weightsAndIndices)::value_type>);
 
  860      return mcps.object(weightsAndIndices[0].second)->getPDG();
 
  863    double particleClusterTotalMCMatchWeight(
const Particle* particle)
 
  865      const ECLCluster* cluster = particle->getECLCluster();
 
  868      auto mcps = cluster->getRelationsTo<MCParticle>();
 
  871      double weightsum = 0;
 
  872      for (
unsigned int i = 0; i < mcps.size(); ++i)
 
  873        weightsum += mcps.weight(i);
 
  879    void getKlongWeightMap(
const Particle* particle, std::map<int, double>& mapMCParticleIndxAndWeight)
 
  881      const ECLCluster* cluster = particle->getECLCluster();
 
  882      auto mcps = cluster->getRelationsTo<MCParticle>();
 
  884      for (
unsigned int i = 0; i < mcps.size(); ++i) {
 
  885        double weight = mcps.weight(i);
 
  886        const MCParticle* mcp = mcps[i];
 
  889          if (mcp->getPDG() == 130) {
 
  890            int index = mcp->getArrayIndex();
 
  891            if (mapMCParticleIndxAndWeight.find(index) != mapMCParticleIndxAndWeight.end()) {
 
  892              mapMCParticleIndxAndWeight.at(index) = mapMCParticleIndxAndWeight.at(index) + weight;
 
  894              mapMCParticleIndxAndWeight.insert({index, weight});
 
  898            mcp = mcp->getMother();
 
  904    double particleClusterTotalMCMatchWeightForKlong(
const Particle* particle)
 
  906      const ECLCluster* cluster = particle->getECLCluster();
 
  909      auto mcps = cluster->getRelationsTo<MCParticle>();
 
  912      std::map<int, double> mapMCParticleIndxAndWeight;
 
  913      getKlongWeightMap(particle, mapMCParticleIndxAndWeight);
 
  915      double totalWeight = 0;
 
  916      for (
const auto& map : mapMCParticleIndxAndWeight) {
 
  917        totalWeight += map.second;
 
  923    double particleClusterTotalMCMatchWeightForBestKlong(
const Particle* particle)
 
  925      const ECLCluster* cluster = particle->getECLCluster();
 
  928      auto mcps = cluster->getRelationsTo<MCParticle>();
 
  931      std::map<int, double> mapMCParticleIndxAndWeight;
 
  932      getKlongWeightMap(particle, mapMCParticleIndxAndWeight);
 
  934      if (mapMCParticleIndxAndWeight.size() == 0)
 
  937      auto maxMap = std::max_element(mapMCParticleIndxAndWeight.begin(), mapMCParticleIndxAndWeight.end(),
 
  938      [](
const auto & x, 
const auto & y) { return x.second < y.second; }
 
  941      return maxMap->second;
 
  944    double isBBCrossfeed(
const Particle* particle)
 
  946      if (particle == 
nullptr)
 
  949      int pdg = particle->getPDGCode();
 
  950      if (std::abs(pdg) != 511 && std::abs(pdg) != 521 && std::abs(pdg) != 531)
 
  953      std::vector<const Particle*> daughters = particle->getFinalStateDaughters();
 
  954      int nDaughters = daughters.size();
 
  957      std::vector<int> mother_ids;
 
  959      for (
int j = 0; j < nDaughters; ++j) {
 
  960        const MCParticle* curMCParticle = daughters[j]->getMCParticle();
 
  961        while (curMCParticle != 
nullptr) {
 
  962          pdg = curMCParticle->getPDG();
 
  963          if (std::abs(pdg) == 511 || std::abs(pdg) == 521 || std::abs(pdg) == 531) {
 
  964            mother_ids.emplace_back(curMCParticle->getArrayIndex());
 
  967          const MCParticle* curMCMother = curMCParticle->getMother();
 
  968          curMCParticle = curMCMother;
 
  970        if (curMCParticle == 
nullptr) {
 
  975      std::set<int> distinctIDs = std::set(mother_ids.begin(), mother_ids.end());
 
  976      if (distinctIDs.size() == 1)
 
  982    int ancestorBIndex(
const Particle* particle)
 
  984      const MCParticle* mcpart = particle->getMCParticle();
 
  987        int pdg = std::abs(mcpart->getPDG());
 
  989        if ((pdg == 521) || (pdg == 511))
 
  990          return mcpart->getArrayIndex();
 
  992        mcpart = mcpart->getMother();
 
  999    int ccbarTagPartialHelper(
 
 1000      const MCParticle* mcParticle,
 
 1001      std::vector<Particle*>& recParticles,
 
 1002      std::vector<const MCParticle*>& missedParticles
 
 1005      bool CaughtAll = 
true;
 
 1006      bool missedAll = 
true;
 
 1007      for (
auto& mcDaughter : mcParticle->getDaughters()) {
 
 1013        if (abs(mcDaughter->getPDG()) == 21) 
continue; 
 
 1014        if (abs(mcDaughter->getPDG()) == 1) 
continue; 
 
 1015        if (abs(mcDaughter->getPDG()) == 2) 
continue; 
 
 1016        if (abs(mcDaughter->getPDG()) == 3) 
continue; 
 
 1017        if (abs(mcDaughter->getPDG()) == 4) 
continue; 
 
 1018        if (abs(mcDaughter->getPDG()) == 5) 
continue; 
 
 1019        if (abs(mcDaughter->getPDG()) == 6) 
continue; 
 
 1021        auto it = std::find_if(recParticles.begin(), recParticles.end(), [mcDaughter](Particle * rec) { return rec->getMCParticle() == mcDaughter; });
 
 1022        if (it != recParticles.end()) {
 
 1023          recParticles.erase(it);
 
 1025        } 
else if (mcDaughter->getNDaughters() == 0) {
 
 1026          missedParticles.push_back(mcDaughter);
 
 1029          std::vector<const MCParticle*> tempMissedParticles;
 
 1030          int status = ccbarTagPartialHelper(mcDaughter, recParticles, tempMissedParticles);
 
 1032            missedParticles.push_back(mcDaughter);
 
 1034          } 
else if (status == 1) {
 
 1039            missedParticles.insert(missedParticles.end(), tempMissedParticles.begin(), tempMissedParticles.end());
 
 1043      if (missedAll) 
return 0;
 
 1044      else if (CaughtAll) 
return 1;
 
 1048    int ccbarTagPartialHelper(
 
 1049      const MCParticle* mcParticle,
 
 1050      const std::vector<Particle*>& recParticles
 
 1053      bool CaughtAll = 
true;
 
 1054      bool missedAll = 
true;
 
 1055      for (
auto& mcDaughter : mcParticle->getDaughters()) {
 
 1057            && mcDaughter->getEnergy() < 0.1) 
continue; 
 
 1058        auto it = std::find_if(recParticles.begin(), recParticles.end(), [mcDaughter](Particle * rec) { return rec->getMCParticle() == mcDaughter; });
 
 1059        if (it != recParticles.end()) missedAll = 
false;
 
 1060        else if (mcDaughter->getNDaughters() == 0) CaughtAll = 
false;
 
 1062          int status = ccbarTagPartialHelper(mcDaughter, recParticles);
 
 1063          if (status == 0) CaughtAll = 
false;
 
 1064          else if (status == 1) missedAll = 
false;
 
 1071      if (missedAll) 
return 0;
 
 1072      else if (CaughtAll) 
return 1;
 
 1076    int ccbarTagEventStatus(
const Particle* part)
 
 1079      int sigPDGCode = part->getPDGCode() * (-1); 
 
 1080      StoreArray<MCParticle> mcparticles;
 
 1081      int eventStatus = 100;
 
 1082      for (
int i = 0; i < mcparticles.getEntries(); i++) {
 
 1083        if (mcparticles[i]->getPDG() == sigPDGCode) {
 
 1084          int recStatus = ccbarTagPartialHelper(mcparticles[i], part->getDaughters());
 
 1085          if (recStatus == 0) 
return 0; 
 
 1086          else if (recStatus == 2) eventStatus = 200; 
 
 1092    int ccbarTagSignal(
const Particle* part)
 
 1094      int returnValue = ccbarTagEventStatus(part);
 
 1095      int sigPDGCode = part->getPDGCode() * (-1); 
 
 1097      for (
auto& daughter : part->getDaughters()) {
 
 1098        if (!daughter->getMCParticle()) 
return returnValue + 10;
 
 1102      const MCParticle* allMother = 
nullptr;
 
 1103      for (
auto& daughter : part->getDaughters()) {
 
 1104        const MCParticle* curMCMother = daughter->getMCParticle()->getMother();
 
 1105        if (curMCMother == 
nullptr) 
return returnValue + 20;
 
 1107          const MCParticle* grandMother = curMCMother->getMother();
 
 1108          while (grandMother != 
nullptr) {
 
 1109            curMCMother = grandMother;
 
 1110            grandMother = curMCMother->getMother();
 
 1114              && curMCMother->getPDG() != 10022) 
return returnValue + 20;
 
 1115          else if (!allMother) allMother = curMCMother;
 
 1116          else if (allMother != curMCMother) 
return returnValue + 20;
 
 1121      bool hasMissingGamma = 
false;
 
 1122      bool hasMissingNeutrino = 
false;
 
 1123      bool hasDecayInFlight = 
false;
 
 1124      for (
auto& daughter : part->getDaughters()) { 
 
 1136      if (hasDecayInFlight) returnValue += 40;
 
 1137      else if (hasMissingNeutrino) returnValue += 50;
 
 1138      else if (hasMissingGamma) returnValue += 60;
 
 1141      std::vector<Particle*> daughters = part->getDaughters();
 
 1142      std::vector<const MCParticle*> missedParticles;
 
 1143      ccbarTagPartialHelper(allMother, daughters, missedParticles);
 
 1145      if (daughters.size() > 0) 
return returnValue + 1000;
 
 1147      if (missedParticles.size() == 1) {
 
 1148        if (missedParticles[0]->getPDG() == sigPDGCode) 
return returnValue + 1;
 
 1149        else return returnValue + 2;
 
 1150      } 
else if (missedParticles.size() > 1) {
 
 1151        return returnValue + 3;
 
 1157    int ccbarTagSignalSimplified(
const Particle* part)
 
 1159      int sigPDGCode = part->getPDGCode() * (-1); 
 
 1161      for (
auto& daughter : part->getDaughters()) {
 
 1162        if (!daughter->getMCParticle()) 
return 10;
 
 1166      const MCParticle* allMother = 
nullptr;
 
 1167      for (
auto& daughter : part->getDaughters()) {
 
 1168        const MCParticle* curMCMother = daughter->getMCParticle()->getMother();
 
 1169        if (curMCMother == 
nullptr) 
return 20;
 
 1171          const MCParticle* grandMother = curMCMother->getMother();
 
 1172          while (grandMother != 
nullptr) {
 
 1173            curMCMother = grandMother;
 
 1174            grandMother = curMCMother->getMother();
 
 1177          if (curMCMother->getPDG() != 
Const::photon.
getPDGCode() && curMCMother->getPDG() != 23 && curMCMother->getPDG() != 10022) 
return 20;
 
 1178          else if (!allMother) allMother = curMCMother;
 
 1179          else if (allMother != curMCMother) 
return 20;
 
 1184      for (
auto& daughter : part->getDaughters()) {
 
 1191      std::vector<Particle*> daughters = part->getDaughters();
 
 1192      std::vector<const MCParticle*> missedParticles;
 
 1193      ccbarTagPartialHelper(allMother, daughters, missedParticles);
 
 1195      if (daughters.size() > 0) 
return 1000;
 
 1197      if (missedParticles.size() == 1) {
 
 1198        if (missedParticles[0]->getPDG() == sigPDGCode) 
return 1;
 
 1200      } 
else if (missedParticles.size() > 1) {
 
 1207    VARIABLE_GROUP(
"MC matching and MC truth");
 
 1208    REGISTER_VARIABLE(
"isSignal", isSignal,
 
 1209                      "1.0 if Particle is correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found. \n" 
 1210                      "It behaves according to DecayStringGrammar.");
 
 1211    REGISTER_VARIABLE(
"isSignalAcceptWrongFSPs", isSignalAcceptWrongFSPs,
 
 1212                      "1.0 if Particle is almost correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found.\n" 
 1213                      "Misidentification of charged FSP is allowed.");
 
 1214    REGISTER_VARIABLE(
"isPrimarySignal", isPrimarySignal,
 
 1215                      "1.0 if Particle is correctly reconstructed (SIGNAL) and primary, 0.0 if not, and NaN if no related MCParticle could be found");
 
 1216    REGISTER_VARIABLE(
"isSignalAcceptBremsPhotons", isSignalAcceptBremsPhotons,
 
 1217                      "1.0 if Particle is correctly reconstructed (SIGNAL), 0.0 if not, and NaN if no related MCParticle could be found.\n" 
 1218                      "Particles with gamma daughters attached through the bremsstrahlung recovery modules are allowed.");
 
 1219    REGISTER_VARIABLE(
"ccbarTagEventStatus", ccbarTagEventStatus,
 
 1220                      "Event status for ccbarTag, returns 100 if there is no signal particle in the event, 200 if it was partially absorbed by tag and 0 otherwise.");
 
 1221    REGISTER_VARIABLE(
"ccbarTagSignal", ccbarTagSignal, R
"DOC( 
 1222                      1 if ccbar tag quasi particle is 'correctly' reconstructed (SIGNAL) in a ccbar event, 
 1223                      otherwise the following encoding indicating the quality of MC match is passed: 
 1225                      * first digit entails info about event particles not contained in the tag: 0 = none missed, 1 = one signal particle is missed (correct), 2 = one non-signal particle is missed, 3 = multiple missed particles, 
 1226                      * second digit corresponds to daughter truth matching errors: 10 = non-matched daughter, 20 = non-common mother or background particle, 30 = severe mcError encountered, 40 = decay in flight, 50 = missing neutrino, 60 = missing gamma, 
 1227                      * third digit corresponds to ccbarTagEventStatus: 100 = no signal particles left in event, 200 = partially absorbed by tag, 0 = at least one signal particle left in event, 
 1228                      * fourth digit is 1000 if the tag absorbed something too much (like a particle coming from beam background). 
 1231    REGISTER_VARIABLE("ccbarTagSignalSimplified", ccbarTagSignalSimplified,
 
 1232                      "Simplified version of ccbarTagSignal without the information of ccbarTagEventStatus.");
 
 1233    REGISTER_VARIABLE(
"genMotherPDG", genMotherPDG,
 
 1234                      "Check the PDG code of a particles MC mother particle");
 
 1235    REGISTER_VARIABLE(
"genMotherPDG(i)", genNthMotherPDG,
 
 1236                      "Check the PDG code of a particles n-th MC mother particle by providing an argument. 0 is first mother, 1 is grandmother etc.  :noindex:");
 
 1238    REGISTER_VARIABLE(
"genQ2PmPd(i,j,...)", genQ2PmPd, R
"DOC( 
 1239                       Returns the generated four momentum transfer squared :math:`q^2` calculated as :math:`q^2 = (p_m - p_{d_i} - p_{d_j} - ...)^2`. 
 1241                       Here :math:`p_m` is the four momentum of the given (mother) particle, 
 1242                       and :math:`p_{d_{i,j,...}}` are the daughter particles with indices given as arguments . 
 1243                       The ordering of daughters is as defined in the DECAY.DEC file used in the generation, with the numbering starting at :math:`N=0`. 
 1245                       Returns NaN if no related MCParticle could be found. 
 1246                       Returns NaN if any of the given indices is larger than the number of daughters of the given particle. 
 1248                       )DOC", ":math:`[\\text{GeV}/\\text{c}]^2`");
 
 1250    REGISTER_VARIABLE(
"genMotherID", genMotherIndex,
 
 1251                      "Check the array index of a particles generated mother");
 
 1252    REGISTER_VARIABLE(
"genMotherID(i)", genNthMotherIndex,
 
 1253                      "Check the array index of a particle n-th MC mother particle by providing an argument. 0 is first mother, 1 is grandmother etc. :noindex:");
 
 1257    REGISTER_VARIABLE(
"isBBCrossfeed", isBBCrossfeed,
 
 1258                      "Returns 1 for crossfeed in reconstruction of given B meson, 0 for no crossfeed and NaN for no true B meson or failed truthmatching.");
 
 1259    REGISTER_VARIABLE(
"ancestorBIndex", ancestorBIndex,
 
 1260                      "Returns array index of B ancestor, or -1 if no B or no MC-matching is found.");
 
 1261    REGISTER_VARIABLE(
"genMotherP", genMotherP,
 
 1262                      "Generated momentum of a particles MC mother particle\n\n", 
"GeV/c");
 
 1263    REGISTER_VARIABLE(
"genParticleID", genParticleIndex,
 
 1264                      "Check the array index of a particle's related MCParticle");
 
 1265    REGISTER_VARIABLE(
"isSignalAcceptMissingNeutrino",
 
 1266                      isSignalAcceptMissingNeutrino,
 
 1267                      "Same as isSignal, but also accept missing neutrino");
 
 1268    REGISTER_VARIABLE(
"isSignalAcceptMissingMassive",
 
 1269                      isSignalAcceptMissingMassive,
 
 1270                      "Same as isSignal, but also accept missing massive particle");
 
 1271    REGISTER_VARIABLE(
"isSignalAcceptMissingGamma",
 
 1272                      isSignalAcceptMissingGamma,
 
 1273                      "Same as isSignal, but also accept missing gamma, such as B -> K* gamma, pi0 -> gamma gamma");
 
 1274    REGISTER_VARIABLE(
"isSignalAcceptMissing",
 
 1275                      isSignalAcceptMissing,
 
 1276                      "Same as isSignal, but also accept missing particle");
 
 1277    REGISTER_VARIABLE(
"isMisidentified", isMisidentified,
 
 1278                      "Return 1 if the particle is misidentified: at least one of the final state particles has the wrong PDG code assignment (including wrong charge), 0 if PDG code is fine, and NaN if no related MCParticle could be found.");
 
 1279    REGISTER_VARIABLE(
"isWrongCharge", isWrongCharge,
 
 1280                      "Return 1 if the charge of the particle is wrongly assigned, 0 if it's the correct charge, and NaN if no related MCParticle could be found.");
 
 1281    REGISTER_VARIABLE(
"isCloneTrack", isCloneTrack,
 
 1282                      "Return 1 if the charged final state particle comes from a cloned track, 0 if not a clone. Returns NAN if neutral, composite, or MCParticle not found (like for data or if not MCMatched)");
 
 1283    REGISTER_VARIABLE(
"isOrHasCloneTrack", isOrHasCloneTrack,
 
 1284                      "Return 1 if the particle is a clone track or has a clone track as a daughter, 0 otherwise.");
 
 1285    REGISTER_VARIABLE(
"mcPDG", particleMCMatchPDGCode,
 
 1286                      "The PDG code of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).");
 
 1287    REGISTER_VARIABLE(
"mcErrors", particleMCErrors,
 
 1288                      "The bit pattern indicating the quality of MC match (see MCMatching::MCErrorFlags)");
 
 1289    REGISTER_VARIABLE(
"mcMatchWeight", particleMCMatchWeight,
 
 1290                      "The weight of the Particle -> MCParticle relation (only for the first Relation = largest weight).");
 
 1291    REGISTER_VARIABLE(
"nMCMatches", particleNumberOfMCMatch,
 
 1292                      "The number of relations of this Particle to MCParticle.");
 
 1293    REGISTER_VARIABLE(
"mcDecayTime", particleMCMatchDecayTime,
 
 1294                      "The decay time of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
 
 1296    REGISTER_VARIABLE(
"mcLifeTime", particleMCMatchLifeTime,
 
 1297                      "The life time of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
 
 1299    REGISTER_VARIABLE(
"mcPX", particleMCMatchPX,
 
 1300                      "The px of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
 
 1302    REGISTER_VARIABLE(
"mcPY", particleMCMatchPY,
 
 1303                      "The py of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
 
 1305    REGISTER_VARIABLE(
"mcPZ", particleMCMatchPZ,
 
 1306                      "The pz of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
 
 1308    REGISTER_VARIABLE(
"mcPT", particleMCMatchPT,
 
 1309                      "The pt of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
 
 1311    REGISTER_VARIABLE(
"mcE", particleMCMatchE,
 
 1312                      "The energy of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
 
 1314    REGISTER_VARIABLE(
"mcP", particleMCMatchP,
 
 1315                      "The total momentum of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
 
 1317    REGISTER_VARIABLE(
"mcPhi", particleMCMatchPhi,
 
 1318                      "The phi of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
 
 1320    REGISTER_VARIABLE(
"mcTheta", particleMCMatchTheta,
 
 1321                      "The theta of matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).\n\n",
 
 1323    REGISTER_VARIABLE(
"nMCDaughters", mcParticleNDaughters,
 
 1324                      "The number of daughters of the matched MCParticle, NaN if no match. Requires running matchMCTruth() on the reconstructed particles, or a particle list filled with generator particles (MCParticle objects).");
 
 1325    REGISTER_VARIABLE(
"mcRecoilMass", particleMCRecoilMass,
 
 1326                      "The mass recoiling against the particles attached as particle's daughters calculated using MC truth values.\n\n",
 
 1327                      "GeV/:math:`\\text{c}^2`");
 
 1328    REGISTER_VARIABLE(
"mcCosThetaBetweenParticleAndNominalB",
 
 1329                      particleMCCosThetaBetweenParticleAndNominalB,
 
 1330                      "Cosine of the angle in CMS between momentum the particle and a nominal B particle. In this calculation, the momenta of all descendant neutrinos are subtracted from the B momentum.");
 
 1333    REGISTER_VARIABLE(
"mcSecPhysProc", mcParticleSecondaryPhysicsProcess,
 
 1335Returns the secondary physics process flag, which is set by Geant4 on secondary particles. It indicates the type of process that produced the particle. 
 1337Returns NaN if the particle is not matched to a MCParticle. 
 1339Returns -1 in case of unknown process. 
 1341Returns 0 if the particle is primary, i.e. produced by the event generator and not Geant4. Particles produced by Geant4 (i.e. secondary particles) include those produced in interaction with detector material, Bremsstrahlung, and the decay products of long-lived particles (e.g. muons, pions, K_S0, K_L0, Lambdas, ...). 
 1343List of possible values (taken from the Geant4 source of 
 1344`G4DecayProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/decay/include/G4DecayProcessType.hh>`_, 
 1345`G4HadronicProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/hadronic/management/include/G4HadronicProcessType.hh>`_, 
 1346`G4TransportationProcessType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/transportation/include/G4TransportationProcessType.hh>`_ and 
 1347`G4EmProcessSubType <https://github.com/Geant4/geant4/blob/v10.6.3/source/processes/electromagnetic/utils/include/G4EmProcessSubType.hh>`_) 
 1349* 1 Coulomb scattering 
 1352* 4 Pair production by charged 
 1354* 6 Annihilation to mu mu 
 1355* 7 Annihilation to hadrons 
 1357* 9 Electron general process 
 1358* 10 Multiple scattering 
 1360* 12 Photo-electric effect 
 1361* 13 Compton scattering 
 1362* 14 Gamma conversion 
 1363* 15 Gamma conversion to mu mu 
 1364* 16 Gamma general process 
 1367* 23 Synchrotron radiation 
 1368* 24 Transition radiation 
 1370* 92 Coupled transportation 
 1372* 121 Hadron inelastic 
 1374* 132 Mu atomic capture 
 1378* 161 Charge exchange 
 1380* 202 Decay with spin 
 1381* 203 Decay (pion make spin) 
 1382* 210 Radioactive decay 
 1387.. note:: This is what `modularAnalysis.printMCParticles` shows as ``creation process`` when ``showStatus`` is set to ``True``. 
 1389    REGISTER_VARIABLE("mcParticleStatus", mcParticleStatus,
 
 1390                      "Returns status bits of related MCParticle or NaN if MCParticle relation is not set.");
 
 1391    REGISTER_VARIABLE(
"mcPrimary", particleMCPrimaryParticle,
 
 1392                      "Returns 1 if Particle is related to primary MCParticle, 0 if Particle is related to non - primary MCParticle, " 
 1393                      "NaN if Particle is not related to MCParticle.");
 
 1394    REGISTER_VARIABLE(
"mcVirtual", particleMCVirtualParticle,
 
 1395                      "Returns 1 if Particle is related to virtual MCParticle, 0 if Particle is related to non - virtual MCParticle, " 
 1396                      "NaN if Particle is not related to MCParticle.")
 
 1397    REGISTER_VARIABLE(
"mcInitial", particleMCInitialParticle,
 
 1398                      "Returns 1 if Particle is related to initial MCParticle, 0 if Particle is related to non - initial MCParticle, " 
 1399                      "NaN if Particle is not related to MCParticle.")
 
 1400    REGISTER_VARIABLE(
"mcISR", particleMCISRParticle,
 
 1401                      "Returns 1 if Particle is related to ISR MCParticle, 0 if Particle is related to non - ISR MCParticle, " 
 1402                      "NaN if Particle is not related to MCParticle.")
 
 1403    REGISTER_VARIABLE(
"mcFSR", particleMCFSRParticle,
 
 1404                      "Returns 1 if Particle is related to FSR MCParticle, 0 if Particle is related to non - FSR MCParticle ," 
 1405                      "NaN if Particle is not related to MCParticle.")
 
 1406    REGISTER_VARIABLE(
"mcPhotos", particleMCPhotosParticle,
 
 1407                      "Returns 1 if Particle is related to Photos MCParticle, 0 if Particle is related to non - Photos MCParticle, " 
 1408                      "NaN if Particle is not related to MCParticle.")
 
 1409    REGISTER_VARIABLE(
"generatorEventWeight", generatorEventWeight,
 
 1410                      "[Eventbased] Returns the event weight produced by the event generator")
 
 1412    REGISTER_VARIABLE(
"genNStepsToDaughter(i)", genNStepsToDaughter,
 
 1413                      "Returns number of steps to i-th daughter from the particle at generator level. " 
 1414                      "NaN if no MCParticle is associated to the particle or i-th daughter. " 
 1415                      "NaN if i-th daughter does not exist.");
 
 1416    REGISTER_VARIABLE(
"genNMissingDaughter(PDG)", genNMissingDaughter,
 
 1417                      "Returns the number of missing daughters having assigned PDG codes. " 
 1418                      "NaN if no MCParticle is associated to the particle.");
 
 1419    REGISTER_VARIABLE(
"Eher", getHEREnergy, R
"DOC( 
 1420[Eventbased] The nominal HER energy used by the generator. 
 1422.. warning:: This variable does not make sense for data. 
 1425    REGISTER_VARIABLE(
"Eler", getLEREnergy, R
"DOC( 
 1426[Eventbased] The nominal LER energy used by the generator. 
 1428.. warning:: This variable does not make sense for data. 
 1431    REGISTER_VARIABLE(
"XAngle", getCrossingAngleX, R
"DOC( 
 1432[Eventbased] The nominal beam crossing angle in the x-z plane from generator level beam kinematics. 
 1434.. warning:: This variable does not make sense for data. 
 1437    REGISTER_VARIABLE(
"YAngle", getCrossingAngleY, R
"DOC( 
 1438[Eventbased] The nominal beam crossing angle in the y-z plane from generator level beam kinematics. 
 1440.. warning:: This variable does not make sense for data. 
 1444    VARIABLE_GROUP(
"Generated tau decay information");
 
 1445    REGISTER_VARIABLE(
"tauPlusMCMode", tauPlusMcMode,
 
 1446                      "[Eventbased] Decay ID for the positive tau lepton in a tau pair generated event.");
 
 1447    REGISTER_VARIABLE(
"tauMinusMCMode", tauMinusMcMode,
 
 1448                      "[Eventbased] Decay ID for the negative tau lepton in a tau pair generated event.");
 
 1449    REGISTER_VARIABLE(
"tauPlusMCProng", tauPlusMcProng,
 
 1450                      "[Eventbased] Prong for the positive tau lepton in a tau pair generated event.");
 
 1451    REGISTER_VARIABLE(
"tauMinusMCProng", tauMinusMcProng,
 
 1452                      "[Eventbased] Prong for the negative tau lepton in a tau pair generated event.");
 
 1453    REGISTER_VARIABLE(
"tauPlusEgstar", tauPlusEgstar,
 
 1454                      "[Eventbased] Energy of radiated gamma from positive tau lepton in a tau pair generated event.");
 
 1455    REGISTER_VARIABLE(
"tauMinusEgstar", tauMinusEgstar,
 
 1456                      "[Eventbased] Energy of radiated gamma from negative tau lepton in a tau pair generated event.");
 
 1458    VARIABLE_GROUP(
"MC particle seen in subdetectors");
 
 1459    REGISTER_VARIABLE(
"isReconstructible", isReconstructible,
 
 1460                      "Checks charged particles were seen in the SVD and neutrals in the ECL, returns 1.0 if so, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
 
 1461    REGISTER_VARIABLE(
"seenInPXD", seenInPXD,
 
 1462                      "Returns 1.0 if the MC particle was seen in the PXD, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
 
 1463    REGISTER_VARIABLE(
"isTrackFound", isTrackFound,
 
 1464                      "works on charged stable particle list created from MCParticles, returns NaN if not ; returns 1.0 if there is a reconstructed track related to the charged stable MCParticle with the correct charge, return -1.0 if the reconstructed track has the wrong charge, return 0.0 when no reconstructed track is found.");
 
 1465    REGISTER_VARIABLE(
"seenInSVD", seenInSVD,
 
 1466                      "Returns 1.0 if the MC particle was seen in the SVD, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
 
 1467    REGISTER_VARIABLE(
"seenInCDC", seenInCDC,
 
 1468                      "Returns 1.0 if the MC particle was seen in the CDC, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
 
 1469    REGISTER_VARIABLE(
"seenInTOP", seenInTOP,
 
 1470                      "Returns 1.0 if the MC particle was seen in the TOP, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
 
 1471    REGISTER_VARIABLE(
"seenInECL", seenInECL,
 
 1472                      "Returns 1.0 if the MC particle was seen in the ECL, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
 
 1473    REGISTER_VARIABLE(
"seenInARICH", seenInARICH,
 
 1474                      "Returns 1.0 if the MC particle was seen in the ARICH, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
 
 1475    REGISTER_VARIABLE(
"seenInKLM", seenInKLM,
 
 1476                      "Returns 1.0 if the MC particle was seen in the KLM, 0.0 if not, NaN for composite particles or if no related MCParticle could be found. Useful for generator studies, not for reconstructed particles.");
 
 1478    VARIABLE_GROUP(
"MC Matching for ECLClusters");
 
 1479    REGISTER_VARIABLE(
"clusterMCMatchWeight", particleClusterMatchWeight,
 
 1480                      "Returns the weight of the ECLCluster -> MCParticle relation for the MCParticle matched to the particle. " 
 1481                      "Returns NaN if: no cluster is related to the particle, the particle is not MC matched, or if there are no mcmatches for the cluster. " 
 1482                      "Returns -1 if the cluster *was* matched to particles, but not the match of the particle provided.");
 
 1483    REGISTER_VARIABLE(
"clusterBestMCMatchWeight", particleClusterBestMCMatchWeight,
 
 1484                      "Returns the weight of the ECLCluster -> MCParticle relation for the relation with the largest weight.");
 
 1485    REGISTER_VARIABLE(
"clusterBestMCPDG", particleClusterBestMCPDGCode,
 
 1486                      "Returns the PDG code of the MCParticle for the ECLCluster -> MCParticle relation with the largest weight.");
 
 1487    REGISTER_VARIABLE(
"clusterTotalMCMatchWeight", particleClusterTotalMCMatchWeight,
 
 1488                      "Returns the sum of all weights of the ECLCluster -> MCParticles relations.");
 
 1490    REGISTER_VARIABLE(
"clusterTotalMCMatchWeightForKlong", particleClusterTotalMCMatchWeightForKlong,
 
 1491                      "Returns the sum of all weights of the ECLCluster -> MCParticles relations when MCParticle is a Klong or daughter of a Klong");
 
 1492    REGISTER_VARIABLE(
"clusterTotalMCMatchWeightForBestKlong", particleClusterTotalMCMatchWeightForBestKlong,
 
 1493                      "Returns the sum of all weights of the ECLCluster -> MCParticles relations when MCParticle is the same Klong or daughter of the Klong. If multiple MC Klongs are related to the ECLCluster, returns the sum of weights for the best matched Klong.");
 
int getPDGCode() const
PDG code.
static const ParticleSet chargedStableSet
set of charged stable particles
static const double doubleNaN
quiet_NaN
static const ParticleType photon
photon particle
@ c_IsFSRPhoton
bit 7: Particle is from final state radiation
@ c_Initial
bit 5: Particle is initial such as e+ or e- and not going to Geant4
@ c_IsPHOTOSPhoton
bit 8: Particle is an radiative photon from PHOTOS
@ c_PrimaryParticle
bit 0: Particle is primary particle.
@ c_IsVirtual
bit 4: Particle is virtual and not going to Geant4.
@ c_IsISRPhoton
bit 6: Particle is from initial state radiation
static const ReferenceFrame & GetCurrent()
Get current rest frame.
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'.
@ c_MissFSR
A Final State Radiation (FSR) photon is not reconstructed (based on MCParticle::c_IsFSRPhoton).
@ c_MissNeutrino
A neutrino is missing (not reconstructed).
@ c_Correct
This Particle and all its daughters are perfectly reconstructed.
@ c_DecayInFlight
A Particle was reconstructed from the secondary decay product of the actual particle.
@ c_MissingResonance
The associated MCParticle decay contained additional non-final-state particles (e....
@ c_MissPHOTOS
A photon created by PHOTOS was not reconstructed (based on MCParticle::c_IsPHOTOSPhoton)
@ c_MissGamma
A photon (not FSR) is missing (not reconstructed).
@ c_MisID
One of the charged final state particles is mis-identified, i.e.
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 void fillGenMothers(const Belle2::MCParticle *mcP, std::vector< int > &genMCPMothers)
Fills vector with array (1-based) indices of all generator ancestors of given MCParticle.