diff --git a/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/IMCTruthClassifier.h b/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/IMCTruthClassifier.h new file mode 100755 index 0000000000000000000000000000000000000000..2fb1d51056811dd3da76e8b6fd03a798889390dc --- /dev/null +++ b/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/IMCTruthClassifier.h @@ -0,0 +1,118 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// IMCTruthClassifierDev.h, (c) ATLAS Detector software 2008 +/////////////////////////////////////////////////////////////////// + +#ifndef MCTRUTHCLASSIFIER_IMCTRUTHCLASSIFIER_H +#define MCTRUTHCLASSIFIER_IMCTRUTHCLASSIFIER_H + +/** @class IegammaMCTruthclassifier + Interface for the PhysicsAnalysis/MCTruthClassifier/MCTruthclassifier + + @author Frederic Derue derue@lpnhe.in2p3.fr + +CREATED : 01/09/2008 +MODIFIED : +*/ + +// Gaudi +#include "GaudiKernel/IAlgTool.h" +#include "MCTruthClassifier/MCTruthClassifierDefs.h" +#include <vector> + +// EDM includes +#include "xAODTruth/TruthParticle.h" +#include "xAODEgamma/Electron.h" +#include "xAODEgamma/Photon.h" +#include "xAODMuon/Muon.h" +#include "xAODJet/Jet.h" + +namespace HepMC { + class GenParticle; +} + +static const InterfaceID IID_IMCTruthClassifier("IMCTruthClassifier", 1, 0); + +class IMCTruthClassifier : virtual public IAlgTool { + + public: + /** Virtual destructor */ + virtual ~IMCTruthClassifier(){}; + + /** AlgTool interface methods */ + static const InterfaceID& interfaceID(); + + virtual StatusCode initialize() = 0; + virtual StatusCode execute() = 0; + virtual StatusCode finalize() = 0; + + //interface to GenParticle + virtual std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> particleTruthClassifier(const HepMC::GenParticle *)= 0; + // + virtual std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> particleTruthClassifier(const xAOD::TruthParticle *)= 0; + virtual std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> particleTruthClassifier(const xAOD::TrackParticle *)= 0; + virtual std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> particleTruthClassifier(const xAOD::Electron* )= 0; + virtual std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> particleTruthClassifier(const xAOD::Photon* )= 0; + virtual std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> particleTruthClassifier(const xAOD::Muon* )= 0; + virtual std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> particleTruthClassifier(const xAOD::CaloCluster* )=0; + virtual std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> particleTruthClassifier(const xAOD::Jet*, bool DR )= 0; + + virtual std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> trackClassifier(const xAOD::TrackParticle *) = 0; + + virtual float getProbTrktoTruth() = 0; + + + virtual MCTruthPartClassifier::ParticleOutCome getParticleOutCome() = 0; + + //virtual const xAOD::TruthParticle* getTruthParticle(const HepMC::GenParticle*) = 0; + + //virtual const HepMC::GenParticle* getGenPart(const xAOD::TruthParticle*) = 0; + // virtual const HepMC::GenParticle* getGenPart(const xAOD::TrackParticle *) = 0; + //virtual const HepMC::GenParticle* getGenPart() = 0; + virtual const xAOD::TruthParticle* getGenPart(const xAOD::TrackParticle *) = 0; + virtual const xAOD::TruthParticle* getGenPart() = 0; + + //virtual const HepMC::GenParticle* getMother() = 0; + virtual const xAOD::TruthParticle* getMother() = 0; + virtual int getMotherPDG() = 0; + virtual int getMotherBarcode() = 0; + virtual const xAOD::TruthParticle* getPhotonMother() = 0; + virtual int getPhotonMotherPDG() = 0; + virtual int getPhotonMotherBarcode() = 0; + virtual std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> + checkOrigOfBkgElec(const xAOD::TruthParticle*) = 0; + virtual const xAOD::TruthParticle* getBkgElecMother() = 0; + + virtual std::vector<const xAOD::TruthParticle*>* getTauFinalState() = 0; + + virtual float getdeltaRMatch() = 0; + virtual void setdeltaRMatchCut(float) = 0; + virtual float getdeltaPhiMatch() = 0; + virtual void setdeltaPhiMatchCut(float )= 0; + virtual void setNumOfSiHitsCut(uint8_t ) = 0; + virtual uint8_t getNumOfSiHits() = 0; + virtual void setPhtdRMatchToTrCut(float) = 0; + virtual void setFwrdEledRMatchToTrCut(float ) = 0; + + virtual std::vector<const xAOD::TruthParticle*> getEGPartPntr() = 0; + virtual std::vector<float> getEGPartdR() = 0; + virtual std::vector<std::pair<MCTruthPartClassifier::ParticleType,MCTruthPartClassifier::ParticleOrigin> > getEGPartClas() = 0; + + + + virtual std::vector<const xAOD::TrackParticle*> getCnvPhotTrkPtr() = 0; + virtual std::vector<const xAOD::TruthParticle*> getCnvPhotTrkToTruthPart() = 0; + virtual std::vector<MCTruthPartClassifier::ParticleType> getCnvPhotPartType() = 0; + virtual std::vector<MCTruthPartClassifier::ParticleOrigin> getCnvPhotPartOrig() = 0; + +}; + +inline const InterfaceID& IMCTruthClassifier::interfaceID() +{ + return IID_IMCTruthClassifier; +} + +#endif // MCTRUTHCLASSIFIER_IMCTRUTHCLASSIFIER_H diff --git a/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/MCTruthClassifier.h b/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/MCTruthClassifier.h new file mode 100644 index 0000000000000000000000000000000000000000..420027b016ddc88e3337e463e1ec8db0838b1137 --- /dev/null +++ b/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/MCTruthClassifier.h @@ -0,0 +1,257 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef MCTRUTHCLASSIFIER_MCTRUTHCLASSIFIER_H +#define MCTRUTHCLASSIFIER_MCTRUTHCLASSIFIER_H +/******************************************************************** + +NAME: MCTruthClassifier.h +PACKAGE: atlasoff/PhysicsAnalysis/MCTruthClassifier + +AUTHORS: O. Fedin +CREATED: Sep 2007 + +PURPOSE: + +Updated: +********************************************************************/ + +// INCLUDE HEADER FILES: +#include "GaudiKernel/ToolHandle.h" +#include "AthenaBaseComps/AthAlgTool.h" +// +#include "MCTruthClassifier/MCTruthClassifierDefs.h" +#include "MCTruthClassifier/IMCTruthClassifier.h" +// +// EDM includes +#include "xAODTruth/TruthParticleContainer.h" + +namespace HepMC { + class GenParticle; +} +// CLHEP +#include "HepPDT/ParticleDataTable.hh" + +class IExtrapolateToCaloTool; +class CaloDepthTool; + +class MCTruthClassifier : public AthAlgTool, virtual public IMCTruthClassifier { + + public: + // constructor + MCTruthClassifier(const std::string& type, const std::string& name, const IInterface* parent); + + // destructor + ~MCTruthClassifier(); + + // Gaudi algorithm hooks + + StatusCode initialize(); + virtual StatusCode execute(); + StatusCode finalize(); + + //temporary interface to old EDM + std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> particleTruthClassifier(const HepMC::GenParticle *); + + std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> particleTruthClassifier(const xAOD::TruthParticle *); + std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> particleTruthClassifier(const xAOD::TrackParticle *); + std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> particleTruthClassifier(const xAOD::Electron* ); + std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> particleTruthClassifier(const xAOD::Photon* ); + std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> particleTruthClassifier(const xAOD::Muon* ); + std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> particleTruthClassifier(const xAOD::CaloCluster* ); + std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> particleTruthClassifier(const xAOD::Jet*, bool DR ); + + // It is just to keep backward compatibility - don't use this methode. + std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> trackClassifier(const xAOD::TrackParticle *); + + + MCTruthPartClassifier::ParticleOutCome getParticleOutCome(){return m_ParticleOutCome;} + + float getProbTrktoTruth(){return m_probability;} + + const xAOD::TruthParticle* getGenPart(const xAOD::TrackParticle *); + const xAOD::TruthParticle* getGenPart(){return m_thePart;} + + const xAOD::TruthParticle* getMother(const xAOD::TruthParticle*); + const xAOD::TruthParticle* getMother(){return m_Mother;} + + int getMotherPDG(){return m_MotherPDG;}; + int getMotherBarcode(){return m_MotherBarcode;}; + + const xAOD::TruthParticle* getPhotonMother(){return m_PhotonMother;} + int getPhotonMotherPDG(){return m_PhotonMotherPDG;} + int getPhotonMotherBarcode(){return m_PhotonMotherBarcode;} + + std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> + checkOrigOfBkgElec(const xAOD::TruthParticle* thePart); + + const xAOD::TruthParticle* getBkgElecMother(){return m_BkgElecMother;} + + std::vector<const xAOD::TruthParticle*>* getTauFinalState(){return &m_tauFinalStatePart;} + + + float getdeltaRMatch(){return m_deltaRMatch;} + void setdeltaRMatchCut(float m_deltaRMatch){m_deltaRMatchCut=m_deltaRMatch; return;} + float getdeltaPhiMatch(){return m_deltaPhi;} + void setdeltaPhiMatchCut(float m_deltaPhi){m_deltaPhiMatchCut=m_deltaPhi; return;} + + void setNumOfSiHitsCut(uint8_t m_NumOfSiHits){m_NumOfSiHitsCut=m_NumOfSiHits; return;} + uint8_t getNumOfSiHits(){return m_NumOfSiHits;} + + void setPhtdRMatchToTrCut(float m_phtdRtoTr){m_phtdRtoTrCut=m_phtdRtoTr; return;} + void setFwrdEledRMatchToTrCut(float m_fwrdRtoTr){m_fwrdEledRtoTrCut=m_fwrdRtoTr; return;} + + std::vector<const xAOD::TruthParticle*> getEGPartPntr(){return m_egPartPtr;} + std::vector<float> getEGPartdR(){return m_egPartdR;} + std::vector<std::pair<MCTruthPartClassifier::ParticleType,MCTruthPartClassifier::ParticleOrigin> > getEGPartClas(){return m_egPartClas;} + + std::vector<const xAOD::TrackParticle*> getCnvPhotTrkPtr() {return m_cnvPhtTrkPtr;} + std::vector<const xAOD::TruthParticle*> getCnvPhotTrkToTruthPart(){return m_cnvPhtTrPart;} + std::vector<MCTruthPartClassifier::ParticleType> getCnvPhotPartType() {return m_cnvPhtPartType;} + std::vector<MCTruthPartClassifier::ParticleOrigin> getCnvPhotPartOrig() {return m_cnvPhtPartOrig;} + + private: + + float detEta(float x, float y ) {return fabs(x-y);} + float detPhi(float , float ); + float rCone (float x, float y ){return sqrt(x*x + y*y);} + + MCTruthPartClassifier::ParticleType defTypeOfElectron(MCTruthPartClassifier::ParticleOrigin); + MCTruthPartClassifier::ParticleOrigin defOrigOfElectron(const xAOD::TruthParticleContainer* m_xTruthParticleContainer ,const xAOD::TruthParticle*); + MCTruthPartClassifier::ParticleOutCome defOutComeOfElectron(const xAOD::TruthParticle*); + + MCTruthPartClassifier::ParticleType defTypeOfMuon(MCTruthPartClassifier::ParticleOrigin); + MCTruthPartClassifier::ParticleOrigin defOrigOfMuon(const xAOD::TruthParticleContainer* m_xTruthParticleContainer ,const xAOD::TruthParticle*); + MCTruthPartClassifier::ParticleOutCome defOutComeOfMuon(const xAOD::TruthParticle*); + + MCTruthPartClassifier::ParticleType defTypeOfTau(MCTruthPartClassifier::ParticleOrigin); + MCTruthPartClassifier::ParticleOrigin defOrigOfTau(const xAOD::TruthParticleContainer* m_xTruthParticleContainer ,const xAOD::TruthParticle*); + MCTruthPartClassifier::ParticleOutCome defOutComeOfTau(const xAOD::TruthParticle*); + + MCTruthPartClassifier::ParticleType defTypeOfPhoton(MCTruthPartClassifier::ParticleOrigin); + MCTruthPartClassifier::ParticleOrigin defOrigOfPhoton(const xAOD::TruthParticleContainer* m_xTruthParticleContainer ,const xAOD::TruthParticle*); + MCTruthPartClassifier::ParticleOutCome defOutComeOfPhoton(const xAOD::TruthParticle*); + + + MCTruthPartClassifier::ParticleOrigin defHadronType(long); + bool isHadron(const xAOD::TruthParticle*); + MCTruthPartClassifier::ParticleType defTypeOfHadron(long); + + MCTruthPartClassifier::ParticleOrigin convHadronTypeToOrig(MCTruthPartClassifier::ParticleType pType); + + const xAOD::TruthVertex* findEndVert(const xAOD::TruthParticle*); + bool isHardScatVrtx(const xAOD::TruthVertex* ); + + std::vector<const xAOD::TruthParticle*> findFinalStatePart(const xAOD::TruthVertex*); + + double partCharge(const xAOD::TruthParticle*); + bool genPartToCalo(const xAOD::CaloCluster* , const xAOD::TruthParticle* , bool, double&, bool& ); + const xAOD::TruthParticle* egammaClusMatch(const xAOD::CaloCluster*, bool ); + + void findAllJetMothers(const xAOD::TruthParticle* thePart,std::set<const xAOD::TruthParticle*>&); + MCTruthPartClassifier::ParticleOrigin defJetOrig(std::set<const xAOD::TruthParticle*>); + + inline double deltaR(const xAOD::TruthParticle& v1, const xAOD::Jet & v2) { + double dphi = std::fabs(v1.phi()-v2.phi()) ; + dphi = (dphi<=M_PI)? dphi : 2*M_PI-dphi; + double deta = std::fabs(v1.eta()-v2.eta()) ; + return std::sqrt(dphi*dphi+deta*deta) ; + } + + /** Return true if genParticle and truthParticle have the same pdgId, barcode and status **/ + const xAOD::TruthParticle* barcode_to_particle(const xAOD::TruthParticleContainer*,int ); + + //for old EDM + bool compareTruthParticles(const HepMC::GenParticle *genPart, const xAOD::TruthParticle *truthPart); + + + const xAOD::TrackParticleContainer * m_trackTES; + const xAOD::TruthParticleContainer * m_xTruthParticleContainer; + + const xAOD::TruthParticle* m_thePart; + const xAOD::TruthParticle* m_Mother; + + int m_MotherPDG; + int m_MotherStatus; + long m_MotherBarcode; + int m_NumOfParents; + int m_NumOfDaug; + + const xAOD::TruthVertex* m_MothOriVert; + const xAOD::TruthVertex* m_partOriVert; + + bool m_isPrompt; + + + const xAOD::TruthParticle* m_PhotonMother; + int m_PhotonMotherPDG; + long m_PhotonMotherBarcode; + long m_PhotonMotherStatus; + + + const xAOD::TruthParticle* m_BkgElecMother; + + + std::vector<const xAOD::TruthParticle*> m_tauFinalStatePart; + + float m_deltaRMatch; + float m_deltaPhi; + float m_NumOfSiHits; + float m_probability; + + float m_phtdRtoTr; + bool m_first; + bool m_useBremRefitTrk; + + + std::vector<const xAOD::TruthParticle*> m_egPartPtr; + std::vector<float> m_egPartdR; + std::vector<std::pair<MCTruthPartClassifier::ParticleType,MCTruthPartClassifier::ParticleOrigin> > m_egPartClas; + + + MCTruthPartClassifier::ParticleOutCome m_ParticleOutCome; + + std::vector< const xAOD::TrackParticle*> m_cnvPhtTrkPtr; + std::vector<const xAOD::TruthParticle*> m_cnvPhtTrPart; + std::vector<MCTruthPartClassifier::ParticleType> m_cnvPhtPartType; + std::vector<MCTruthPartClassifier::ParticleOrigin> m_cnvPhtPartOrig; + + const HepPDT::ParticleDataTable* m_particleTable; + + + ToolHandle<IExtrapolateToCaloTool> m_extrapolateToCalo; + /** @brief Tool to retrieve the calorimeter depth (for track extrapolation)*/ + ToolHandle<CaloDepthTool> m_calodepth; + +//------------------------------------------------------------------------ +// configurable data members +//------------------------------------------------------------------------ + + std::string m_trackParticleContainerName; + std::string m_trackGSFParticleContainerName; + std::string m_xaodTruthParticleContainerName ; + std::string m_truthLinkVecName; + + float m_deltaRMatchCut; + float m_deltaPhiMatchCut; + int m_NumOfSiHitsCut; + + float m_phtdRtoTrCut; + + float m_fwrdEledRtoTrCut; + float m_pTChargePartCut; + float m_pTNeutralPartCut; + float m_partExtrConeEta; + float m_partExtrConePhi; + float m_phtClasConePhi; + float m_phtClasConeEta; + bool m_inclG4part; + bool m_ROICone; + bool m_inclEgammaPhoton; + bool m_inclEgammaFwrdEle; + bool m_LQpatch; + bool m_forceNotUseBremRefitTrk; + float m_jetPartDRMatch; +}; +#endif // MCTRUTHCLASSIFIER_MCTRUTHCLASSIFIER_H diff --git a/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/MCTruthClassifierDefs.h b/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/MCTruthClassifierDefs.h new file mode 100644 index 0000000000000000000000000000000000000000..631a492fc91727c2a1f3c7287595e32ff34b89e4 --- /dev/null +++ b/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/MCTruthClassifierDefs.h @@ -0,0 +1,265 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef MCTRUTHCLASSIFIER_MCTRUTHCLASSIFIERDEFS_H +#define MCTRUTHCLASSIFIER_MCTRUTHCLASSIFIERDEFS_H +/******************************************************************** + +NAME: MCTruthClassifierDefs.h +PACKAGE: atlasoff/PhysicsAnalysis/MCTruthClassifier + +AUTHORS: O. Fedin +CREATED: Oct 2007 + +PURPOSE: + +Updated: +********************************************************************/ +#include <vector> +#include <string> +// +#define PARTICLETYPES 39 +#define PARTICLEORIGIN 46 +#define PARTICLEOUTCOME 12 + +namespace MCTruthPartClassifier { + + enum ParticleType { + + Unknown = 0, + UnknownElectron = 1, + IsoElectron = 2, + NonIsoElectron = 3, + BkgElectron = 4, + UnknownMuon = 5, + IsoMuon = 6, + NonIsoMuon = 7, + BkgMuon = 8, + UnknownTau = 9, + IsoTau = 10, + NonIsoTau = 11, + BkgTau = 12, + UnknownPhoton = 13, + IsoPhoton = 14, + NonIsoPhoton = 15, + BkgPhoton = 16, + Hadron = 17, + Neutrino = 18, + NuclFrag = 19, + NonPrimary = 20, + GenParticle = 21, + SUSYParticle = 22, + BBbarMesonPart = 23, + BottomMesonPart = 24, + CCbarMesonPart = 25, + CharmedMesonPart = 26, + BottomBaryonPart = 27, + CharmedBaryonPart = 28, + StrangeBaryonPart = 29, + LightBaryonPart = 30, + StrangeMesonPart = 31, + LightMesonPart = 32, + BJet = 33, + CJet = 34, + LJet = 35, + GJet = 36, + TauJet = 37, + UnknownJet = 38 + }; + + enum ParticleOrigin { + + NonDefined = 0, + + SingleElec = 1, + SingleMuon = 2, + SinglePhot = 3, + SingleTau = 4, + + + PhotonConv = 5, + DalitzDec = 6, + ElMagProc = 7, + Mu = 8, + TauLep = 9, + top = 10, + QuarkWeakDec = 11, + WBoson = 12, + ZBoson = 13, + Higgs = 14, + HiggsMSSM = 15, + HeavyBoson = 16, + WBosonLRSM = 17, + NuREle = 18, + NuRMu = 19, + NuRTau = 20, + LQ = 21, + + SUSY = 22, + LightMeson = 23, + StrangeMeson = 24, + CharmedMeson = 25, + BottomMeson = 26, + CCbarMeson = 27, + JPsi = 28, + BBbarMeson = 29, + LightBaryon = 30, + StrangeBaryon = 31, + CharmedBaryon = 32, + BottomBaryon = 33, + PionDecay = 34, + KaonDecay = 35, + BremPhot = 36, + PromptPhot = 37, + UndrPhot = 38, + ISRPhot = 39, + FSRPhot = 40, + NucReact = 41, + PiZero = 42, + DiBoson = 43, + ZorHeavyBoson = 44, + QCD = 45 + }; + + enum ParticleOutCome { + NonDefinedOutCome = 0, + UnknownOutCome = 1, + UnConverted = 2, + Converted = 3, + NonInteract = 4, + NuclInteraction = 5, + ElectrMagInter = 6, + DecaytoElectron = 7, + DecaytoMuon = 8, + OneProng = 9, + ThreeProng = 10, + FiveProng = 11 + }; + + + + struct ParticleDef { + + /** the vector of patricle types */ + std::vector<std::string> sParticleType; + /** the vector of patricle origin */ + std::vector<std::string> sParticleOrigin; + /** the vector of patricle out come */ + std::vector<std::string> sParticleOutCome; + + /**Default constructor*/ + ParticleDef() + { + sParticleType.reserve(PARTICLETYPES); + + sParticleType.push_back("Unknown"); + sParticleType.push_back("UnknownElectron"); + sParticleType.push_back("IsoElectron"); + sParticleType.push_back("NonIsoElectron"); + sParticleType.push_back("BkgElectron"); + sParticleType.push_back("UnknownMuon"); + sParticleType.push_back("IsoMuon"); + sParticleType.push_back("NonIsoMuon"); + sParticleType.push_back("BkgMuon"); + sParticleType.push_back("UnknownTau"); + sParticleType.push_back("IsoTau"); + sParticleType.push_back("NonIsoTau"); + sParticleType.push_back("BkgTau"); + sParticleType.push_back("UnknownPhoton"); + sParticleType.push_back("IsoPhoton"); + sParticleType.push_back("NonIsoPhoton"); + sParticleType.push_back("BkgPhoton"); + sParticleType.push_back("Hadron"); + sParticleType.push_back("Neutrino"); + sParticleType.push_back("NuclFrag"); + sParticleType.push_back("NonPrimary"); + sParticleType.push_back("GenParticle"); + sParticleType.push_back("SUSYParticle"); + sParticleType.push_back("BBbarMesonPart"); + sParticleType.push_back("BottomMesonPart"); + sParticleType.push_back("CCbarMesonPart"); + sParticleType.push_back("CharmedMesonPart"); + sParticleType.push_back("BottomBaryonPart"); + sParticleType.push_back("CharmedBaryonPart"); + sParticleType.push_back("StrangeBaryonPart"); + sParticleType.push_back("LightBaryonPart"); + sParticleType.push_back("StrangeMesonPart"); + sParticleType.push_back("LightMesonPart"); + sParticleType.push_back("BJet"); + sParticleType.push_back("CJet"); + sParticleType.push_back("LJet"); + sParticleType.push_back("GJet"); + sParticleType.push_back("TauJet"); + sParticleType.push_back("UnknownJet"); + + sParticleOrigin.reserve(PARTICLEORIGIN); + sParticleOrigin.push_back("NonDefined"); + sParticleOrigin.push_back("SingleElec"); + sParticleOrigin.push_back("SingleMuon"); + sParticleOrigin.push_back("SinglePhot"); + sParticleOrigin.push_back("SingleTau"); + sParticleOrigin.push_back("PhotonConv"); + sParticleOrigin.push_back("DalitzDec"); + sParticleOrigin.push_back("ElMagProc"); + sParticleOrigin.push_back("Mu"); + sParticleOrigin.push_back("TauLep"); + sParticleOrigin.push_back("top"); + sParticleOrigin.push_back("QuarkWeakDec"); + sParticleOrigin.push_back("WBoson"); + sParticleOrigin.push_back("ZBoson"); + sParticleOrigin.push_back("Higgs"); + sParticleOrigin.push_back("HiggsMSSM"); + sParticleOrigin.push_back("WZMSSM"); + sParticleOrigin.push_back("WBosonLRSM"); + sParticleOrigin.push_back("NuREle"); + sParticleOrigin.push_back("NuRMu "); + sParticleOrigin.push_back("NuRTau"); + sParticleOrigin.push_back("LQ"); + sParticleOrigin.push_back("SUSY"); + sParticleOrigin.push_back("LightMeson"); + sParticleOrigin.push_back("StrangeMeson"); + sParticleOrigin.push_back("CharmedMeson"); + sParticleOrigin.push_back("BottomMeson"); + sParticleOrigin.push_back("CCbarMeson"); + sParticleOrigin.push_back("JPsi"); + sParticleOrigin.push_back("BBbarMeson"); + sParticleOrigin.push_back("LightBaryon"); + sParticleOrigin.push_back("StrangeBaryon"); + sParticleOrigin.push_back("CharmedBaryon"); + sParticleOrigin.push_back("BottomBaryon"); + sParticleOrigin.push_back("PionDecay"); + sParticleOrigin.push_back("KaonDecay"); + sParticleOrigin.push_back("BremPhot"); + sParticleOrigin.push_back("PromptPhot"); + sParticleOrigin.push_back("UndrPhot"); + sParticleOrigin.push_back("ISRPhot"); + sParticleOrigin.push_back("FSRPhot"); + sParticleOrigin.push_back("NucReact"); + sParticleOrigin.push_back("PiZero"); + sParticleOrigin.push_back("DiBoson"); + sParticleOrigin.push_back("ZorHeavyBoson"); + sParticleOrigin.push_back("QCD"); + + sParticleOutCome.reserve(PARTICLEOUTCOME); + sParticleOutCome.push_back("NonDefinedOutCome"); + sParticleOutCome.push_back("UnknownOutCome"); + sParticleOutCome.push_back("UnConverted"); + sParticleOutCome.push_back("Converted"); + sParticleOutCome.push_back("NonInteract"); + sParticleOutCome.push_back("NuclInteraction"); + sParticleOutCome.push_back("ElectrMagInter"); + sParticleOutCome.push_back("DecaytoElectron"); + sParticleOutCome.push_back("DecaytoMuon"); + sParticleOutCome.push_back("OneProng"); + sParticleOutCome.push_back("ThreeProng"); + sParticleOutCome.push_back("FiveProng"); + + + } + + }; + +} + +#endif // MCTRUTHCLASSIFIER_MCTRUTHCLASSIFIERDEFS_H diff --git a/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/MCTruthClassifierDict.h b/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/MCTruthClassifierDict.h new file mode 100644 index 0000000000000000000000000000000000000000..8817167b5d48ed414bfc9addafc1a74821f34c50 --- /dev/null +++ b/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/MCTruthClassifierDict.h @@ -0,0 +1,14 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef MCTRUTHCLASSIFIER_MCTRUTHCLASSIFIERDICT_H +#define MCTRUTHCLASSIFIER_MCTRUTHCLASSIFIERDICT_H +/** +* @file MCTruthClassifierDict.h +*/ + +//<<<<<< INCLUDES >>>>>> +#include "MCTruthClassifier/IMCTruthClassifier.h" + +#endif // MCTRUTHCLASSIFIER_MCTRUTHCLASSIFIERDICT_H diff --git a/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/MCTruthClassifierEnumsDict.h b/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/MCTruthClassifierEnumsDict.h new file mode 100644 index 0000000000000000000000000000000000000000..d47e41984d9af2ec3d1c3fe2c5a6ab2f1db39258 --- /dev/null +++ b/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/MCTruthClassifierEnumsDict.h @@ -0,0 +1,19 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef MCTRUTHCLASSIFIER_MCTRUTHCLASSIFIERENUMSDICT_H +#define MCTRUTHCLASSIFIER_MCTRUTHCLASSIFIERENUMSDICT_H + +#include "MCTruthClassifier/MCTruthClassifierDefs.h" + + namespace MCTruthClassifierEnumsDict { + + struct tmp { + std::pair<MCTruthPartClassifier::ParticleType, + MCTruthPartClassifier::ParticleOrigin> m_1; + }; + +} //> end namespace + +#endif // !MCTRUTHCLASSIFIER_MCTRUTHCLASSIFIERENUMSDICT_H diff --git a/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/selection.xml b/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/selection.xml new file mode 100644 index 0000000000000000000000000000000000000000..a344939623f84f5606a479b14790a5b2b39248eb --- /dev/null +++ b/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/selection.xml @@ -0,0 +1,3 @@ +<lcgdict> + <class name="IMCTruthClassifier" /> +</lcgdict> diff --git a/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/selectionEnums.xml b/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/selectionEnums.xml new file mode 100644 index 0000000000000000000000000000000000000000..cde4959a3eec322602897fa4b3e0eab238569b1c --- /dev/null +++ b/PhysicsAnalysis/MCTruthClassifier/MCTruthClassifier/selectionEnums.xml @@ -0,0 +1,8 @@ +<lcgdict> + <enum pattern="MCTruthPartClassifier::*"/> + <variable pattern="MCTruthPartClassifier::*"/> + <struct pattern="MCTruthPartClassifier::*"/> + + <class name="std::pair<MCTruthPartClassifier::ParticleType,MCTruthPartClassifier::ParticleOrigin>" /> + +</lcgdict> diff --git a/PhysicsAnalysis/MCTruthClassifier/cmt/requirements b/PhysicsAnalysis/MCTruthClassifier/cmt/requirements new file mode 100644 index 0000000000000000000000000000000000000000..2cb3af68f298358b8a7a8b68303107a2962b89b5 --- /dev/null +++ b/PhysicsAnalysis/MCTruthClassifier/cmt/requirements @@ -0,0 +1,60 @@ +package MCTruthClassifier + +author Oleg Fedin <Oleg.Fedin@cern.ch> + +use AtlasPolicy AtlasPolicy-* +# use StoreGate StoreGate-* Control +use AthenaBaseComps AthenaBaseComps-* Control +use GaudiInterface GaudiInterface-* External +use HepPDT v* LCG_Interfaces + +use xAODTruth xAODTruth-* Event/xAOD +use xAODEgamma xAODEgamma-* Event/xAOD +use xAODMuon xAODMuon-* Event/xAOD +use xAODJet xAODJet-* Event/xAOD + +private +use xAODTracking xAODTracking-* Event/xAOD +use xAODCaloEvent xAODCaloEvent-* Event/xAOD +use GeneratorObjects GeneratorObjects-* Generators +use AtlasHepMC AtlasHepMC-* External +use RecoToolInterfaces RecoToolInterfaces-* Reconstruction/RecoTools +use CaloDetDescr CaloDetDescr-* Calorimeter +use TrkEventPrimitives TrkEventPrimitives-* Tracking/TrkEvent + +apply_pattern declare_python_modules files="*.py" + +# pattern dual_use_library must be declared public +# so that clients can link against its public library +public +apply_pattern dual_use_library files=*.cxx +end_public + +# The following use is to get the lcgdict pattern. +# This is "hidden" behind "private" and "no_auto_imports" to keep +# clients of EventInfo from seeing excess dependencies +private +use AtlasReflex AtlasReflex-* External -no_auto_imports + +# Pattern to build the dict lib. User should create a single header +# file: <package>Dict.h which includes all other .h files. See EventInfoDict +# A selection file must be created by hand. This file lists the +# classes to be added to the dictionary, and which fields are +# transient. It should be put in ../<package> dir and is conventionally called +# selection.xml. + +# Must temporarily omit emission of methods - fails +apply_pattern lcgdict dict=MCTruthClassifier selectionfile=selection.xml headerfiles="../MCTruthClassifier/MCTruthClassifierDict.h" + + +# Split the enums off into a separate dictionary, +# so that we can get them from python without having to load all the EDM +# classes. + +apply_pattern lcgdict dict=MCTruthClassifierEnums \ +selectionfile=selectionEnums.xml \ +headerfiles="../MCTruthClassifier/MCTruthClassifierEnumsDict.h" + + +#remove use_linkopts +macro MCTruthClassifierEnumsDict_shlibflags "$(componentshr_linkopts) $(Reflex_linkopts) $(egammaInterfaces_extra_shlibflags)" diff --git a/PhysicsAnalysis/MCTruthClassifier/python/MCTruthClassifierBase.py b/PhysicsAnalysis/MCTruthClassifier/python/MCTruthClassifierBase.py new file mode 100755 index 0000000000000000000000000000000000000000..aee01b5b779811d6dff338a77ab3a76910f61520 --- /dev/null +++ b/PhysicsAnalysis/MCTruthClassifier/python/MCTruthClassifierBase.py @@ -0,0 +1,67 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +from AthenaCommon.Logging import logging +from AthenaCommon.SystemOfUnits import * +from AthenaCommon.Constants import * +from AthenaCommon.BeamFlags import jobproperties +import traceback +import EventKernel.ParticleDataType + +from RecExConfig.Configured import Configured +from InDetRecExample.InDetKeys import InDetKeys +from AthenaCommon.DetFlags import DetFlags + + + + +mlog = logging.getLogger ('MCTruthCalssifierBase.py::configure:') +mlog.info('entering') + +from AthenaCommon.AppMgr import ToolSvc + + +# configure tools for ID on +#if DetFlags.detdescr.ID_on() : + +# Configure the extrapolator +from TrkExTools.AtlasExtrapolator import AtlasExtrapolator +theAtlasExtrapolator=AtlasExtrapolator(name = 'egammaExtrapolator') +theAtlasExtrapolator.DoCaloDynamic = False # this turns off dynamic calculation of eloss in calorimeters +# all left to MaterialEffects/EnergyLossUpdators + +from TrkExTools.TrkExToolsConf import Trk__MaterialEffectsUpdator as MaterialEffectsUpdator +AtlasMaterialEffectsUpdator = MaterialEffectsUpdator(name = 'AtlasMaterialEffectsUpdator') +ToolSvc += AtlasMaterialEffectsUpdator #default material effects updator +NoElossMaterialEffectsUpdator = MaterialEffectsUpdator(name = 'NoElossMaterialEffectsUpdator') +NoElossMaterialEffectsUpdator.EnergyLoss = False +ToolSvc += NoElossMaterialEffectsUpdator + +# setup MaterialEffectsUpdator arrays +MyUpdators = [] +# MyUpdators += [AtlasMaterialEffectsUpdator] # for ID +MyUpdators += [NoElossMaterialEffectsUpdator] # for ID +MyUpdators += [NoElossMaterialEffectsUpdator] # for Calo +MyUpdators += [NoElossMaterialEffectsUpdator] # for muon +# MyUpdators += [NoElossMaterialEffectsUpdator] # for muon + +MySubUpdators = [] +MySubUpdators += [NoElossMaterialEffectsUpdator.name()] # for ID +# MySubUpdators += [AtlasMaterialEffectsUpdator.name()] # for ID +MySubUpdators += [NoElossMaterialEffectsUpdator.name()] # for Calo +MySubUpdators += [NoElossMaterialEffectsUpdator.name()] # for muon + +theAtlasExtrapolator.MaterialEffectsUpdators = MyUpdators +theAtlasExtrapolator.SubMEUpdators = MySubUpdators +ToolSvc+=theAtlasExtrapolator + +# add tool ExtrapolateTrackToCalo +from TrackToCalo.TrackToCaloConf import ExtrapolateToCaloTool +exToCalo = ExtrapolateToCaloTool(name = "exToCalo", + Extrapolator = theAtlasExtrapolator) +ToolSvc+=exToCalo + +from MCTruthClassifier.MCTruthClassifierConf import MCTruthClassifier +MCTruthClassifier = MCTruthClassifier(name = 'MCTruthClassifier', + ExtrapolateToCaloTool = exToCalo) + +ToolSvc += MCTruthClassifier diff --git a/PhysicsAnalysis/MCTruthClassifier/src/MCTruthClassifier.cxx b/PhysicsAnalysis/MCTruthClassifier/src/MCTruthClassifier.cxx new file mode 100644 index 0000000000000000000000000000000000000000..d8dfba5b9bddfcb0bab692c31ef937ea70ae2b21 --- /dev/null +++ b/PhysicsAnalysis/MCTruthClassifier/src/MCTruthClassifier.cxx @@ -0,0 +1,2698 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/******************************************************************************** + +NAME: MCTruthClassifier.cxx +PACKAGE: atlasoff/PhysicsAnalysis/MCTruthClassifier + +AUTHORS: O. Fedin +CREATED: Sep 2007 + +PURPOSE: to classify truth particles according to their origin. Based on + the truth particle classification the tool provide classification of + ID and combined muon tracks, egamma electrons (including forward + electrons) and egamma photons. Both AOD and ESD files can be used. + See for details: + https://twiki.cern.ch/twiki/bin/view/AtlasProtected/EgammaMCTruthClassifier + +Updated: +********************************************************************************/ + +// INCLUDE HEADER FILES: +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/IPartPropSvc.h" +// +#include "MCTruthClassifier/MCTruthClassifier.h" +// +// EDM includes +#include "xAODTracking/TrackParticle.h" +#include "xAODTruth/TruthVertex.h" +#include "xAODCaloEvent/CaloCluster.h" +//extrapolation +#include "RecoToolInterfaces/IExtrapolateToCaloTool.h" +#include "CaloDetDescr/CaloDepthTool.h" +#include "TrkEventPrimitives/PropDirection.h" +// for jet classification +// #include "JetEvent/JetINav4MomAssociation.h" +#include "xAODTruth/TruthParticleContainer.h" +// +#include "xAODEgamma/EgammaxAODHelpers.h" +// +// Link between HepMC and xAODTruth - need for old EDM +#include "GeneratorObjects/xAODTruthParticleLink.h" +#include "HepMC/GenParticle.h" + +#include <math.h> +#include <iostream> +#include <iomanip> + +using CLHEP::GeV; +using namespace MCTruthPartClassifier; +using namespace std; + +// ----------------------------------------------------------------------- +// Constructor +// ----------------------------------------------------------------------- +MCTruthClassifier::MCTruthClassifier(const std::string& type, + const std::string& name, + const IInterface* parent) + : AthAlgTool(type, name, parent), + m_extrapolateToCalo("") +{ + // declare Interface + declareInterface<IMCTruthClassifier>(this); + //--- + declareProperty("xAODTruthParticleContainerName" , m_xaodTruthParticleContainerName = "TruthParticle"); + declareProperty("xAODTruthLinkVector" , m_truthLinkVecName="xAODTruthLinks"); + //--- + declareProperty("deltaRMatchCut" , m_deltaRMatchCut = 0.2); + declareProperty("deltaPhiMatchCut" , m_deltaPhiMatchCut = 0.2); + declareProperty("NumOfSiHitsCut" , m_NumOfSiHitsCut = 3); + declareProperty("phtdRtoTrCut" , m_phtdRtoTrCut = 0.1); + + declareProperty("fwrdEledRtoTrCut" , m_fwrdEledRtoTrCut = 0.15); + + declareProperty("inclEgammaFwrdEle" , m_inclEgammaFwrdEle = true); + declareProperty("inclEgammaPhoton" , m_inclEgammaPhoton = true); + declareProperty("ROICone" , m_ROICone = false); + declareProperty("partExtrConePhi" , m_partExtrConePhi = 0.4); + declareProperty("partExtrConeEta" , m_partExtrConeEta = 0.2); + + declareProperty("phtClasConePhi" , m_phtClasConePhi = 0.05); + declareProperty("phtClasConeEta" , m_phtClasConeEta = 0.025); + + declareProperty("pTChargePartCut" , m_pTChargePartCut = 1.0); + declareProperty("pTNeutralPartCut" , m_pTNeutralPartCut = 0.); + declareProperty("inclG4part" , m_inclG4part = false); + + declareProperty( "ExtrapolateToCaloTool", m_extrapolateToCalo); + declareProperty( "LQpatch", m_LQpatch=false); + + declareProperty("jetPartDRMatch" , m_jetPartDRMatch = 0.4); + + const HepPDT::ParticleDataTable m_particleTable("PDG Table"); + +} + + + +// DESTRUCTOR: + +MCTruthClassifier::~MCTruthClassifier() +{ } + + +// INITIALIZE METHOD: + +StatusCode MCTruthClassifier::initialize() +{ + // MSGStream object to output messages from your algorithm + + MsgStream mlog( msgSvc(), name() ); + + ATH_MSG_INFO( " Initializing MCTruthClassifier" ); + + // Particle properties + IPartPropSvc* m_partPropSvc = 0; + static const bool CREATEINFOTTHERE(true); + StatusCode sc =service("PartPropSvc",m_partPropSvc,CREATEINFOTTHERE); + if (StatusCode::SUCCESS != sc) { + ATH_MSG_ERROR( " Can't get PartPropSvc" ); + return sc; + } else ATH_MSG_DEBUG( "get PartPropSvc" ); + + + // obtain PDT + m_particleTable=m_partPropSvc->PDT(); + + if( !m_extrapolateToCalo.empty()){ + if(m_inclEgammaPhoton||m_inclEgammaFwrdEle) { + + // Retrieve TrackToCalo tool for extrapolation to calorimeter + if ( m_extrapolateToCalo.retrieve().isFailure() ) { + + ATH_MSG_WARNING( "Cannot retrieve extrapolateToCaloTool " << m_extrapolateToCalo + << " - will not perform extrapolation." ); + + } else { + + ATH_MSG_DEBUG( "Retrieved track-to-calo tool " << m_extrapolateToCalo ); + // retrieved via the Extrapolator + m_calodepth = m_extrapolateToCalo->getCaloDepth(); + + if (!m_calodepth) { + ATH_MSG_DEBUG( "Cannot get CaloDepthTool " << m_extrapolateToCalo ); + return StatusCode::FAILURE; + } else ATH_MSG_DEBUG( "get CaloDepthTool " << m_extrapolateToCalo ); + + } + } + } + + return StatusCode::SUCCESS; + +} + + +// FINALIZE METHOD: + +StatusCode MCTruthClassifier::finalize() +{ + + return StatusCode::SUCCESS; + +} + +// ATHENA EXECUTE METHOD: + +StatusCode MCTruthClassifier::execute() +{ + return StatusCode::SUCCESS; +} + +//Old EDM interface +//--------------------------------------------------------------------------------------- +std::pair<ParticleType,ParticleOrigin> +MCTruthClassifier::particleTruthClassifier(const HepMC::GenParticle *thePart){ + //--------------------------------------------------------------------------------------- + ParticleType partType = Unknown; + ParticleOrigin partOrig = NonDefined; + + + if (!thePart) return std::make_pair(partType,partOrig); + + // Retrieve the links between HepMC and xAOD::TruthParticle + const xAODTruthParticleLinkVector* truthParticleLinkVec = 0; + if(evtStore()->retrieve(truthParticleLinkVec, m_truthLinkVecName).isFailure()){ + ATH_MSG_WARNING("Cannot retrieve TruthParticleLinkVector"); + return std::make_pair(partType,partOrig); + } + + for( const auto& entry : *truthParticleLinkVec ) { + if(entry->first.isValid() && entry->second.isValid() + && entry->first.cptr()->barcode() == thePart->barcode()) { + const xAOD::TruthParticle* truthParticle = *entry->second; + if ( !compareTruthParticles(thePart, truthParticle) ) { + //if the barcode/pdg id / status of the pair does not match + //return default + return std::make_pair(partType,partOrig); + } + return particleTruthClassifier(truthParticle); + } + } + + return std::make_pair(partType,partOrig); +} +//------------------------------------------------------------------------ +bool MCTruthClassifier::compareTruthParticles(const HepMC::GenParticle *genPart, + const xAOD::TruthParticle *truthPart){ + //------------------------------------------------------------------------ + if (!genPart || !truthPart) return false; + + if (genPart->barcode() != truthPart->barcode() || + genPart->pdg_id() != truthPart->pdgId() || + genPart->status() != truthPart->status()) { + ATH_MSG_DEBUG("HepMC::GenParticle and xAOD::TruthParticle do not match"); + return false; + } + + return true; + +} + +//--------------------------------------------------------------------------------------- +std::pair<ParticleType,ParticleOrigin> +MCTruthClassifier::particleTruthClassifier(const xAOD::TruthParticle *thePart){ + //--------------------------------------------------------------------------------------- + + + ATH_MSG_DEBUG( "Executing particleTruthClassifier" ); + + ParticleType partType = Unknown; + ParticleOrigin partOrig = NonDefined; + m_ParticleOutCome = NonDefinedOutCome; + m_tauFinalStatePart.clear(); + + m_partOriVert = 0; + m_Mother = 0; + m_MotherBarcode = 0; + m_MotherPDG = 0; + m_MotherStatus = 0; + m_MothOriVert = 0; + m_NumOfParents = 0; + m_NumOfDaug = 0; + m_PhotonMother = 0; + m_PhotonMotherPDG = 0; + m_PhotonMotherStatus = 0; + m_PhotonMotherBarcode = 0; + m_ParticleOutCome = UnknownOutCome; + m_BkgElecMother = 0; + + m_isPrompt = false; + + m_thePart = thePart; + //retrieve collection and get a pointer + + if(!thePart) return std::make_pair(partType,partOrig); + + const xAOD::TruthParticleContainer * m_xTruthParticleContainer; + StatusCode sc = evtStore()->retrieve(m_xTruthParticleContainer, m_xaodTruthParticleContainerName); + if (sc.isFailure()||!m_xTruthParticleContainer){ + ATH_MSG_WARNING( "No xAODTruthParticleContainer "<<m_xaodTruthParticleContainerName<<" found" ); + return std::make_pair(partType,partOrig); + } + + ATH_MSG_DEBUG( "xAODTruthParticleContainer " << m_xaodTruthParticleContainerName<<" successfully retrieved " ); + + + int iParticlePDG = thePart->pdgId(); + //status=10902 in Pythia? + if(thePart->status()!=1&&thePart->status()!=2&&thePart->status()!=10902) return std::make_pair(GenParticle,partOrig); + bool isPartHadr = isHadron(thePart); + if(thePart->status()==2&&(abs(iParticlePDG)!=15&&!isPartHadr)) return std::make_pair(GenParticle,partOrig); + + //SUSY datasets: tau(satus==2)->tau(satus==2) + if(thePart->status()==2&&abs(iParticlePDG)==15){ + const xAOD::TruthVertex* endVert = thePart->decayVtx(); + if(endVert!=0){ + int numOfDaught=endVert->nOutgoingParticles(); + if(numOfDaught==1&&abs(endVert->outgoingParticle(0)->pdgId())==15) return std::make_pair(GenParticle,partOrig); + } + } + + if(thePart->status()==1&&abs(iParticlePDG)<2000040&&abs(iParticlePDG)>1000001) return std::make_pair(SUSYParticle,partOrig); + + + if(thePart->status()==10902&&(abs(iParticlePDG)!=11&&abs(iParticlePDG)!=13&&abs(iParticlePDG)!=15&&abs(iParticlePDG)!=22)&&!isPartHadr) return std::make_pair(GenParticle,partOrig); + + + if(abs(iParticlePDG)==12||abs(iParticlePDG)==14||abs(iParticlePDG)==16) return std::make_pair(Neutrino,partOrig); + if(abs(iParticlePDG)>1000000000) return std::make_pair(NuclFrag,partOrig); + + if(abs(iParticlePDG)!=11&&abs(iParticlePDG)!=13&&abs(iParticlePDG)!=15&&abs(iParticlePDG)!=22&&!isPartHadr) return std::make_pair(partType,partOrig); + //don't consider generator particles + + const xAOD::TruthVertex* m_partOriVert=thePart->hasProdVtx() ? thePart->prodVtx():0; + + if( m_partOriVert!=0 ) { + for (unsigned int ipIn=0; ipIn<m_partOriVert->nIncomingParticles(); ++ipIn) { + const xAOD::TruthParticle* theMoth=m_partOriVert->incomingParticle(ipIn); + m_MotherPDG = theMoth->pdgId(); + m_MotherBarcode = theMoth->barcode(); + m_MotherStatus = theMoth->status(); + } + } + + if(m_partOriVert==0&&thePart->barcode()>1000000) return std::make_pair(NonPrimary,partOrig); + + if(m_partOriVert==0 && abs(iParticlePDG)==11) { + // to define electron out come status + partOrig = defOrigOfElectron(m_xTruthParticleContainer,thePart); + return std::make_pair(UnknownElectron,partOrig); + } else if(m_partOriVert==0 && abs(iParticlePDG)==13) { + // to define electron out come status + partOrig = defOrigOfMuon(m_xTruthParticleContainer,thePart); + return std::make_pair(UnknownMuon,partOrig); + } else if(m_partOriVert==0 && abs(iParticlePDG)==15) { + // to define electron out come status + partOrig = defOrigOfTau(m_xTruthParticleContainer,thePart); + return std::make_pair(UnknownTau,partOrig); + } else if(m_partOriVert==0 && abs(iParticlePDG)==22) { + // to define photon out come + partOrig = defOrigOfPhoton(m_xTruthParticleContainer,thePart); + return std::make_pair(UnknownPhoton,partOrig); + } + + + if(thePart->barcode()%1000000 == m_MotherBarcode%1000000) return std::make_pair(NonPrimary,partOrig); + + if(isPartHadr) return std::make_pair(Hadron,partOrig); + + if(m_partOriVert!=0&&m_MotherPDG==0&&m_partOriVert->nOutgoingParticles()==1&&m_partOriVert->nIncomingParticles()==0) { + if(abs(iParticlePDG)==11){m_ParticleOutCome=defOutComeOfElectron(thePart); return std::make_pair(IsoElectron,SingleElec);} + if(abs(iParticlePDG)==13){m_ParticleOutCome=defOutComeOfMuon(thePart); return std::make_pair(IsoMuon,SingleMuon); } + if(abs(iParticlePDG)==15){m_ParticleOutCome=defOutComeOfTau(thePart); return std::make_pair(IsoTau,SingleTau); } + if( iParticlePDG ==22){m_ParticleOutCome=defOutComeOfPhoton(thePart); return std::make_pair(IsoPhoton,SinglePhot); } + } + + + if( m_MotherPDG==iParticlePDG && m_MotherStatus==3 && thePart->status()==10902) return std::make_pair(GenParticle,partOrig); + + if(abs(iParticlePDG)==11){ + partOrig = defOrigOfElectron(m_xTruthParticleContainer,thePart); + partType = defTypeOfElectron(partOrig); + } else if(abs(iParticlePDG)==13) { + partOrig = defOrigOfMuon(m_xTruthParticleContainer,thePart); + partType = defTypeOfMuon(partOrig); + } else if(abs(iParticlePDG)==15) { + partOrig = defOrigOfTau(m_xTruthParticleContainer,thePart); + partType = defTypeOfTau(partOrig); + } else if(abs(iParticlePDG)==22){ + partOrig = defOrigOfPhoton(m_xTruthParticleContainer,thePart); + partType = defTypeOfPhoton( partOrig); + } + + ATH_MSG_DEBUG( "particleTruthClassifier succeeded " ); + return std::make_pair(partType,partOrig); +} + +//----------------------------------------------------------------------------------------- +std::pair<ParticleType,ParticleOrigin> +MCTruthClassifier::particleTruthClassifier(const xAOD::TrackParticle *trkPtr){ + //----------------------------------------------------------------------------------------- + + + ATH_MSG_DEBUG( "Executing trackClassifier" ); + + m_thePart = 0; + m_partOriVert = 0; + m_Mother = 0; + m_MotherBarcode = 0; + m_MotherPDG = 0; + m_MotherStatus = 0; + m_MothOriVert = 0; + m_NumOfParents = 0; + m_NumOfDaug = 0; + m_PhotonMother = 0; + m_PhotonMotherPDG = 0; + m_PhotonMotherStatus = 0; + m_PhotonMotherBarcode = 0; + m_BkgElecMother = 0; + m_ParticleOutCome = UnknownOutCome; + + m_isPrompt = false; + + m_deltaRMatch =-999.; + m_deltaPhi =-999.; + m_NumOfSiHits = 0; + m_probability = 0; + + ParticleType parttype = Unknown; + ParticleOrigin partorig = NonDefined; + + m_thePart=getGenPart(trkPtr); + + if(!m_thePart) return std::make_pair(parttype,partorig); + + + ATH_MSG_DEBUG( "trackClassifier succeeded " ); + return particleTruthClassifier(m_thePart); +} + +//----------------------------------------------------------------------------------------- +std::pair<ParticleType,ParticleOrigin> +MCTruthClassifier::trackClassifier(const xAOD::TrackParticle *trkPtr){ + //----------------------------------------------------------------------------------------- + // It is just to keep backward compatibility - don't use this methode. + ATH_MSG_DEBUG( "Executing trackClassifier" ); + return particleTruthClassifier(trkPtr); +} + +//----------------------------------------------------------------------------------------- +std::pair<ParticleType,ParticleOrigin> +MCTruthClassifier::particleTruthClassifier(const xAOD::Electron* elec){ + //----------------------------------------------------------------------------------------- + + + ATH_MSG_DEBUG( "Executing egamma electron Classifier" ); + + m_thePart = 0; + m_partOriVert = 0; + m_Mother = 0; + m_MotherBarcode = 0; + m_MotherPDG = 0; + m_MotherStatus = 0; + m_MothOriVert = 0; + m_NumOfParents = 0; + m_NumOfDaug = 0; + m_PhotonMother = 0; + m_PhotonMotherPDG = 0; + m_PhotonMotherStatus = 0; + m_PhotonMotherBarcode = 0; + m_BkgElecMother = 0; + m_ParticleOutCome = UnknownOutCome; + + m_deltaRMatch =-999.; + m_deltaPhi =-999.; + m_NumOfSiHits = 0; + m_probability = 0; + + ParticleType parttype = Unknown; + ParticleOrigin partorig = NonDefined; + + m_isPrompt = false; + + m_egPartPtr.clear(); + m_egPartdR.clear(); + m_egPartClas.clear(); + + + if(elec->author()&xAOD::EgammaParameters:: AuthorFwdElectron){ + + const xAOD::CaloCluster* clus=elec->caloCluster(); + m_thePart = egammaClusMatch(clus,true); + } else { + const xAOD::TrackParticle* trkPtr=elec->trackParticle(); + if(!trkPtr) {return std::make_pair(parttype,partorig);} + m_thePart=getGenPart(trkPtr); + if(!m_thePart) {return std::make_pair(parttype,partorig);} + } + + ATH_MSG_DEBUG( "egamma electron Classifier succeeded " ); + return particleTruthClassifier(m_thePart); + +} + +//----------------------------------------------------------------------------------------- +std::pair<ParticleType,ParticleOrigin> +MCTruthClassifier::particleTruthClassifier(const xAOD::Photon* phot){ + //----------------------------------------------------------------------------------------- + + + ATH_MSG_DEBUG( "Executing egamma photon Classifier" ); + + m_thePart = 0; + m_partOriVert = 0; + m_Mother = 0; + m_MotherBarcode = 0; + m_MotherPDG = 0; + m_MotherStatus = 0; + m_MothOriVert = 0; + m_NumOfParents = 0; + m_NumOfDaug = 0; + m_PhotonMother = 0; + m_PhotonMotherPDG = 0; + m_PhotonMotherStatus = 0; + m_PhotonMotherBarcode = 0; + m_BkgElecMother = 0; + m_ParticleOutCome = UnknownOutCome; + + m_deltaRMatch =-999.; + m_deltaPhi =-999.; + m_NumOfSiHits = 0; + m_probability = 0; + + ParticleType parttype = Unknown; + ParticleOrigin partorig = NonDefined; + + m_isPrompt = false; + + + m_cnvPhtTrkPtr.clear(); + m_cnvPhtTrPart.clear(); + m_cnvPhtPartType.clear(); + m_cnvPhtPartOrig.clear(); + + m_egPartPtr.clear(); + m_egPartdR.clear(); + m_egPartClas.clear(); + + const xAOD::CaloCluster* clus=phot->caloCluster(); + if(!clus) return std::make_pair(parttype,partorig); + if( fabs(clus->eta())> 10.0 ||fabs(clus->phi())> 6.28||(clus->et())<=0.) return std::make_pair(parttype,partorig); + + const xAOD::Vertex* VxCvPtr=phot->vertex(); + + if(VxCvPtr!=0) { + for(int itrk=0; itrk<(int) VxCvPtr->nTrackParticles(); itrk++){ + if(itrk>1) continue; + const xAOD::TrackParticle* trkPtr = VxCvPtr->trackParticle(itrk); + if(!trkPtr) continue; + m_cnvPhtTrkPtr.push_back(trkPtr); + const xAOD::TruthParticle* thePart=getGenPart(trkPtr); + + std::pair<ParticleType,ParticleOrigin> classif=particleTruthClassifier(thePart); + m_cnvPhtTrPart.push_back(thePart); + + //std::pair<ParticleType,ParticleOrigin> classif=particleTruthClassifier(trkPtr); + // m_cnvPhtTrPart.push_back(getGenPart()); + + m_cnvPhtPartType.push_back(classif.first); + m_cnvPhtPartOrig.push_back(classif.second); + } // end cycle itrk + + } // VxCvPtr!=0 + + + + m_thePart = egammaClusMatch(clus,false); + + + ATH_MSG_DEBUG( "egamma photon Classifier succeeded " ); + + return particleTruthClassifier(m_thePart); + +} +//----------------------------------------------------------------------------------------- +std::pair<ParticleType,ParticleOrigin> +MCTruthClassifier::particleTruthClassifier(const xAOD::Muon* mu ){ + //----------------------------------------------------------------------------------------- + + + ATH_MSG_DEBUG( "Executing muon Classifier" ); + + m_thePart = 0; + m_partOriVert = 0; + m_Mother = 0; + m_MotherBarcode = 0; + m_MotherPDG = 0; + m_MotherStatus = 0; + m_MothOriVert = 0; + m_NumOfParents = 0; + m_NumOfDaug = 0; + m_PhotonMother = 0; + m_PhotonMotherPDG = 0; + m_PhotonMotherStatus = 0; + m_PhotonMotherBarcode = 0; + m_BkgElecMother = 0; + m_ParticleOutCome = UnknownOutCome; + + m_isPrompt = false; + + m_deltaRMatch =-999.; + m_deltaPhi =-999.; + m_NumOfSiHits = 0; + m_probability = 0; + + ParticleType parttype = Unknown; + ParticleOrigin partorig = NonDefined; + + + //typedef ElementLink<xAOD::TruthParticleContainer> TruthLink_t; + const xAOD::TrackParticle* trkPtr=0; + + if( mu->primaryTrackParticleLink().isValid()) trkPtr = *mu->primaryTrackParticleLink(); + else if( mu->combinedTrackParticleLink().isValid() ) trkPtr = *mu->combinedTrackParticleLink(); + else if (mu->inDetTrackParticleLink().isValid()) trkPtr = *mu->combinedTrackParticleLink(); + else if( mu->muonSpectrometerTrackParticleLink().isValid() ) trkPtr = *mu->muonSpectrometerTrackParticleLink(); + + if(!trkPtr) return std::make_pair(parttype,partorig); + + m_thePart=getGenPart(trkPtr); + if(!m_thePart) return std::make_pair(parttype,partorig); + + + ATH_MSG_DEBUG( "muon Classifier succeeded " ); + return particleTruthClassifier(m_thePart); +} + +//----------------------------------------------------------------------------------------- +std::pair<ParticleType,ParticleOrigin> +MCTruthClassifier::particleTruthClassifier(const xAOD::CaloCluster* clus){ + //----------------------------------------------------------------------------------------- + + ATH_MSG_DEBUG( "Executing egamma photon Classifier with cluster Input" ); + + m_thePart = 0; + m_partOriVert = 0; + m_Mother = 0; + m_MotherBarcode = 0; + m_MotherPDG = 0; + m_MotherStatus = 0; + m_MothOriVert = 0; + m_NumOfParents = 0; + m_NumOfDaug = 0; + m_PhotonMother = 0; + m_PhotonMotherPDG = 0; + m_PhotonMotherStatus = 0; + m_PhotonMotherBarcode = 0; + m_BkgElecMother = 0; + m_ParticleOutCome = UnknownOutCome; + + m_deltaRMatch =-999.; + m_deltaPhi =-999.; + m_NumOfSiHits = 0; + m_probability = 0; + ParticleType parttype = Unknown; + ParticleOrigin partorig = NonDefined; + m_isPrompt = false; + m_egPartPtr.clear(); + m_egPartdR.clear(); + m_egPartClas.clear(); + + if(!clus) return std::make_pair(parttype,partorig); + if( fabs(clus->eta())> 10.0 ||fabs(clus->phi())> M_PI||(clus->et())<=0.) return std::make_pair(parttype,partorig); + + m_thePart = egammaClusMatch(clus,false); + + + ATH_MSG_DEBUG( "egamma photon Classifier succeeded " ); + + return particleTruthClassifier(m_thePart); +} +//----------------------------------------------------------------------------------------- +std::pair<ParticleType,ParticleOrigin> +MCTruthClassifier::particleTruthClassifier(const xAOD::Jet* jet, bool DR = true){ + //----------------------------------------------------------------------------------------- + + + ATH_MSG_DEBUG( "Executing Classifier with jet Input" ); + + m_thePart = 0; + m_deltaRMatch =-999.; + m_ParticleOutCome = UnknownOutCome; + ParticleType parttype = UnknownJet; + ParticleOrigin partorig = NonDefined; + ParticleType tempparttype = UnknownJet; + std::set<const xAOD::TruthParticle*> allJetMothers; + std::pair<ParticleType,ParticleOrigin> res; + + if(!jet) return std::make_pair(parttype,partorig); + + allJetMothers.clear(); + + // FIXME: uncomment + if (!DR) { // use ghost-associated particles + // retrieve a truth particle association + // const xAOD::JetINav4MomAssociation* truthA = jet->getAssociation<JetINav4MomAssociation>("TruthAssoc"); + // if (!truthA) return std::make_pair(parttype,partorig); + // + // // loop over truth particles within the JetINav4MomAssociation objects + // JetINav4MomAssociation::object_iter it = truthA->begin(); + // JetINav4MomAssociation::object_iter itE = truthA->end(); + // for( ; it !=itE; ++it) { + // const TruthParticle* tp = dynamic_cast<const TruthParticle*> (*it); + // const HepMC::GenParticle* thePart = tp->genParticle(); + // if(!tp) continue; + // // do not look at intermediate particles + // if (tp->status()!=2&&tp->status()!=3&&tp->status()!=10902) continue; + // // determine jet origin + // findAllJetMothers(thePart,allJetMothers); + // // determine jet type + // if (tp->status()==3) continue; + // // classify the particle + // tempparttype = particleTruthClassifier(thePart).first; + // if(tempparttype==Hadron) tempparttype=defTypeOfHadron(thePart->pdg_id()); + // // classify the jet + // if (tempparttype==BBbarMesonPart || tempparttype==BottomMesonPart || tempparttype==BottomBaryonPart) parttype = BJet; + // else if (tempparttype==CCbarMesonPart || tempparttype==CharmedMesonPart || tempparttype==CharmedBaryonPart) + // {if (parttype==BJet) {} else { parttype = CJet;}} + // else if (tempparttype==StrangeBaryonPart||tempparttype==LightBaryonPart||tempparttype==StrangeMesonPart||tempparttype==LightMesonPart) + // {if (parttype==BJet||parttype==CJet) {} else { parttype = LJet;}} + // else {if (parttype==BJet||parttype==CJet||parttype==LJet) {} else { parttype = UnknownJet;}} + // + // } // end loop over truth particles + // + // // end ghost-association case + // + } else { + + // use a DR matching scheme (default) + + // retrieve collection and get a pointer + const xAOD::TruthParticleContainer * m_xTruthParticleContainer; + StatusCode sc = evtStore()->retrieve(m_xTruthParticleContainer, m_xaodTruthParticleContainerName); + if (sc.isFailure()||!m_xTruthParticleContainer){ + ATH_MSG_WARNING( "No xAODTruthParticleContainer "<<m_xaodTruthParticleContainerName<<" found" ); + return std::make_pair(parttype,partorig); + } + + ATH_MSG_DEBUG( "xAODTruthParticleContainer " << m_xaodTruthParticleContainerName<<" successfully retrieved " ); + + + // find the matching truth particles + for(const auto thePart : *m_xTruthParticleContainer){ + // do not look at intermediate particles + if(thePart->status()!=2&&thePart->status()!=3&&thePart->status()!=10902) continue; + // match truth particles to the jet + if (deltaR((*thePart),(*jet)) > m_jetPartDRMatch) continue; + // determine jet origin + findAllJetMothers(thePart,allJetMothers); + // determine jet type + if(thePart->status()==3) continue; + // determine jet type + tempparttype = particleTruthClassifier(thePart).first; + if(tempparttype==Hadron) tempparttype=defTypeOfHadron(thePart->pdgId()); + // classify the jet + if (tempparttype==BBbarMesonPart || tempparttype==BottomMesonPart || tempparttype==BottomBaryonPart) + {parttype = BJet;} + else if (tempparttype==CCbarMesonPart || tempparttype==CharmedMesonPart || tempparttype==CharmedBaryonPart ) + {if (parttype==BJet) {} else { parttype = CJet;}} + else if (tempparttype==StrangeBaryonPart||tempparttype==LightBaryonPart||tempparttype==StrangeMesonPart||tempparttype==LightMesonPart) + {if (parttype==BJet||parttype==CJet) {} else { parttype = LJet;}} + else {if (parttype==BJet||parttype==CJet||parttype==LJet) {} else { parttype = UnknownJet;}} + + } // end loop over truth particles + + }// end DR scheme + + // clasify the jet origin + partorig = defJetOrig(allJetMothers); + + allJetMothers.clear(); + + ATH_MSG_DEBUG( " jet Classifier succeeded" ); + return std::make_pair(parttype,partorig); +} + +//--------------------------------------------------------------------------------- +ParticleOrigin MCTruthClassifier::defJetOrig(std::set<const xAOD::TruthParticle*> allJetMothers){ + //--------------------------------------------------------------------------------- + ParticleOrigin partOrig = NonDefined; + std::set<const xAOD::TruthParticle*>::iterator it; + + for (it=allJetMothers.begin(); it!=allJetMothers.end(); ++it) { + int pdg = abs((*it)->pdgId()); + if ( pdg == 6 ) { partOrig = top; } + if ( pdg == 23 ) { partOrig = ZBoson; } + if ( pdg == 24 && !(partOrig==top) ) { partOrig = WBoson; } + if ( (pdg < 6 || pdg == 21) && + !( partOrig==top || + partOrig==ZBoson || + partOrig==WBoson ) ) { partOrig = QCD; } + if ( pdg == 25 ) { partOrig = Higgs; return partOrig; } + if ( pdg == 35 || + pdg == 36 || + pdg == 37 ) { partOrig = HiggsMSSM; return partOrig; } + if ( pdg == 32 || + pdg == 33 || + pdg == 34 ) { partOrig = HeavyBoson; return partOrig; } + if ( pdg == 42 ) { partOrig = LQ; return partOrig; } + if ( pdg < 2000040 && + pdg > 1000001 ) { partOrig = SUSY; return partOrig; } + } + return partOrig; +} +//--------------------------------------------------------------------------------------------------------- +void MCTruthClassifier::findAllJetMothers(const xAOD::TruthParticle* thePart, + std::set<const xAOD::TruthParticle*>&allJetMothers){ + //--------------------------------------------------------------------------------------------------------- + const xAOD::TruthVertex* partOriVert = thePart->prodVtx(); + + if (partOriVert!=0) { + for(unsigned int ipIn=0;ipIn<partOriVert->nIncomingParticles();ipIn++){ + const xAOD::TruthParticle* theMoth=partOriVert->incomingParticle(ipIn); + allJetMothers.insert(theMoth); + findAllJetMothers(theMoth,allJetMothers); + } + } + return ; +} + +//----------------------------------------------------------------------------------------- +const xAOD::TruthParticle* MCTruthClassifier::getGenPart(const xAOD::TrackParticle *trk){ + //----------------------------------------------------------------------------------------- + //return GenParticle corresponding to given TrackParticle + + ATH_MSG_DEBUG( "Executing getGenPart " ); + + if (!trk) return 0; + + m_deltaRMatch =-999.; + m_deltaPhi =-999.; + m_NumOfSiHits = 0; + m_probability = 0; + + uint8_t NumOfPixHits = 0; + uint8_t NumOfSCTHits = 0; + typedef ElementLink<xAOD::TruthParticleContainer> TruthLink_t; + + static SG::AuxElement::Accessor<TruthLink_t> tPL ("truthParticleLink"); + if(tPL.isAvailable(*trk)){ + ATH_MSG_DEBUG("Track particle is not associated to truth particle"); + return 0; + } + + auto truthLink = tPL(*trk); + if (!truthLink.isValid()){ + ATH_MSG_INFO("Invalid link to truth particle"); + return 0; + } + + const xAOD::TruthParticle* theGenParticle=(*truthLink); + if (!theGenParticle){ + ATH_MSG_INFO("Could not find truth matching for track"); + return 0; + } + + static SG::AuxElement::Accessor<float > tMP ("truthMatchProbability"); + if(tMP.isAvailable(*trk)){ + m_probability = tMP(*trk); + } + else { + ATH_MSG_DEBUG("Truth match probability not available"); + } + + if(theGenParticle->status()==2||theGenParticle->status()==3){ + ATH_MSG_WARNING("track matched to the truth with status "<<theGenParticle->status()); + } + + if(theGenParticle->status()==2 && + (abs(theGenParticle->pdgId())==11||abs(theGenParticle->pdgId())==13)) + { + const xAOD::TruthVertex* EndVrtx=theGenParticle->decayVtx(); + const xAOD::TruthParticle* theGenPartTmp(0); + + if(EndVrtx!=0) + { + int itr=0; + do { + theGenPartTmp=0; + for(unsigned int ipOut=0; ipOut<EndVrtx->nOutgoingParticles();ipOut++){ + const xAOD::TruthParticle* theDaugt=EndVrtx->outgoingParticle(ipOut); + if(theDaugt->pdgId()==theGenParticle->pdgId()) theGenPartTmp=theDaugt; + if(theDaugt->pdgId()!=theGenParticle->pdgId()&&theDaugt->pdgId()!=22) + theGenPartTmp=0; + } + + if(theGenPartTmp!=0) EndVrtx = theGenPartTmp->decayVtx(); else EndVrtx = 0; + itr++; + if(itr>100) { ATH_MSG_WARNING ("getGenPart infinite while"); break;} + } while (theGenPartTmp->pdgId()==theGenParticle->pdgId()&&theGenPartTmp->status()==2&& + EndVrtx!=0); + if(theGenPartTmp!=0&&theGenPartTmp->pdgId()==theGenParticle->pdgId()) {theGenParticle=theGenPartTmp;} + + } + + } + + if (!trk->summaryValue(NumOfSCTHits, xAOD::numberOfSCTHits) ) + ATH_MSG_DEBUG("Could not retrieve number of SCT hits"); + if (!trk->summaryValue(NumOfPixHits, xAOD::numberOfPixelHits) ) + ATH_MSG_DEBUG("Could not retrieve number of Pixel hits"); + + m_NumOfSiHits=NumOfSCTHits+NumOfPixHits; + + m_deltaPhi = detPhi(theGenParticle->phi(),trk->phi()); + float deteta = detEta(theGenParticle->eta(),trk->eta()); + m_deltaRMatch = rCone(m_deltaPhi, deteta); + if(m_NumOfSiHits>m_NumOfSiHitsCut&&m_deltaRMatch >m_deltaRMatchCut) theGenParticle=NULL; + else if(m_NumOfSiHits<=m_NumOfSiHitsCut && m_deltaPhi > m_deltaPhiMatchCut) theGenParticle=NULL; + + ATH_MSG_DEBUG( "getGenPart succeeded " ); + return(theGenParticle); + +} + +//------------------------------------------------------------------------------- +ParticleType MCTruthClassifier::defTypeOfElectron(ParticleOrigin EleOrig){ + //------------------------------------------------------------------------------- + + + if( EleOrig == NonDefined) return UnknownElectron; + + if (EleOrig == WBoson || EleOrig == ZBoson || EleOrig == top || + EleOrig == SingleElec || EleOrig == Higgs || EleOrig == HiggsMSSM || + EleOrig == HeavyBoson || EleOrig == WBosonLRSM || EleOrig == NuREle || + EleOrig == NuRMu || EleOrig == NuRTau || EleOrig == LQ || + EleOrig == SUSY || EleOrig == DiBoson || EleOrig == ZorHeavyBoson || + m_isPrompt ) { + return IsoElectron; + } + if (EleOrig == JPsi || EleOrig == BottomMeson || + EleOrig == CharmedMeson || EleOrig == BottomBaryon || + EleOrig == CharmedBaryon || EleOrig == TauLep || + EleOrig == Mu || EleOrig == QuarkWeakDec){ + return NonIsoElectron; + } + return BkgElectron; + + +} + +//2345678901234567890123456789012345678901234567890123456789012345678901234567890 +//------------------------------------------------------------------------------- +ParticleOrigin MCTruthClassifier::defOrigOfElectron(const xAOD::TruthParticleContainer* m_mcTruthTES, + const xAOD::TruthParticle *thePart) +//------------------------------------------------------------------------------- +{ + + ATH_MSG_DEBUG( "Executing DefOrigOfElectron " ); + + int PriBarcode = thePart->barcode()%1000000; + const xAOD::TruthParticle* thePriPart = barcode_to_particle(m_mcTruthTES,PriBarcode); + if(!thePriPart) return NonDefined; + if(abs(thePriPart->pdgId())!=11) return NonDefined; + + const xAOD::TruthVertex* m_partOriVert = thePriPart->prodVtx(); + + //-- to define electron outcome status + m_ParticleOutCome = defOutComeOfElectron(thePriPart); + + if(!m_partOriVert) return NonDefined; + + m_NumOfParents=-1; + m_NumOfParents=m_partOriVert->nIncomingParticles(); + if(m_NumOfParents>1) + ATH_MSG_WARNING( "DefOrigOfElectron:: electron has more than one mother " ); + + m_Mother = getMother(thePriPart); + if(!m_Mother) return NonDefined; + m_MotherPDG = m_Mother->pdgId(); + m_MotherBarcode = m_Mother->barcode(); + m_MothOriVert = m_Mother->prodVtx(); + + //---patch to fix LQ dataset problem + if(m_LQpatch){ + if(abs(m_MotherPDG) == 11&&m_Mother->status()==2&&m_MothOriVert==0&&m_MotherPDG==thePriPart->pdgId()&& + m_NumOfParents == 1 &&(m_partOriVert->nOutgoingParticles()==1||m_partOriVert->nOutgoingParticles()==2) ) { + const xAOD::TruthParticle* theP(0); + int itr=0; + float dRMin(99999.); + do { + const xAOD::TruthParticle* thePtmp = barcode_to_particle(m_mcTruthTES,m_MotherBarcode-(itr+2)); + if(abs(thePtmp->pdgId())==11&&thePtmp->pdgId()==m_MotherPDG&&thePtmp->status()==3&&thePtmp->decayVtx()==0){ + float dphi=detPhi(m_Mother->phi(),thePtmp->phi()); + float deta=m_Mother->eta()-thePtmp->eta(); + float dR=rCone(dphi,deta); + if(dR<dRMin) {dRMin=dR; theP=thePtmp;}; + + } + itr++; + } while (itr<4); + + if(dRMin>0.1) theP=0; + if(theP!=0){ + thePriPart = theP; + m_Mother = getMother(thePriPart); + if(!m_Mother) return NonDefined; + m_MotherPDG = m_Mother->pdgId(); + m_MotherBarcode = m_Mother->barcode(); + m_MothOriVert = m_Mother->prodVtx(); + } + } + } + //---- + + + // to exclude interactions mu(barcode<10^6)->mu(barcode10^6)+e + bool samePart=false; + for (unsigned int ipOut=0; ipOut<m_partOriVert->nOutgoingParticles(); ++ipOut) { + const xAOD::TruthParticle* theDaug=m_partOriVert->outgoingParticle(ipOut); + if( m_MotherPDG==theDaug->pdgId()&&m_MotherBarcode%1000000==theDaug->barcode()%1000000) samePart=true; + } + + if( ( abs(m_MotherPDG)==13||abs(m_MotherPDG)==15||abs(m_MotherPDG)==24)&& m_MothOriVert!=0&&!samePart){ + long pPDG(0); + const xAOD::TruthParticle* MotherParent(0); + do { + pPDG=0; + MotherParent=getMother(m_Mother); + if(MotherParent) pPDG = MotherParent->pdgId(); + + if(abs(pPDG)==13 || abs(pPDG)==15 || abs(pPDG)==24) m_Mother = MotherParent; + + } while ((abs(pPDG)==13 || abs(pPDG)==15 || abs(pPDG)==24) ); + + if(abs(pPDG)==13 || abs(pPDG)==15 || abs(pPDG)==24 || abs(pPDG)==23 || + abs(pPDG)==25 || abs(pPDG)==35 || abs(pPDG)==36 || abs(pPDG)==37 || + abs(pPDG)==32 || abs(pPDG)==33 || abs(pPDG)==34 || abs(pPDG)==6 || + abs(pPDG)==9900024 || abs(pPDG)== 9900012 || abs(pPDG)== 9900014 || abs(pPDG)== 9900016 || + (abs(pPDG)<2000040&& abs(pPDG)>1000001)) m_Mother = MotherParent; + } + + + m_MotherPDG = m_Mother->pdgId(); + m_MotherBarcode = m_Mother->barcode(); + m_MotherStatus = m_Mother->status(); + m_partOriVert = m_Mother->decayVtx(); + m_MothOriVert = m_Mother->prodVtx(); + m_NumOfParents = m_partOriVert->nIncomingParticles(); + m_NumOfDaug = m_partOriVert->nOutgoingParticles(); + + + + int NumOfPhot(0),NumOfEl(0),NumOfPos(0),NumOfNucFr(0); + int NumOfquark(0),NumOfgluon(0),NumOfElNeut(0),NumOfLQ(0); + int NumOfMuPl(0),NumOfMuMin(0),NumOfMuNeut(0); + int NumOfTau(0),NumOfTauNeut(0); + long DaugType(0); + samePart=false; + + for (unsigned int ipOut=0; ipOut<m_partOriVert->nOutgoingParticles(); ++ipOut) { + const xAOD::TruthParticle* theDaug=m_partOriVert->outgoingParticle(ipOut); + DaugType = theDaug->pdgId(); + if( abs(DaugType) < 7 ) NumOfquark++; + if( abs(DaugType) == 21 ) NumOfgluon++; + if( abs(DaugType) == 12 ) NumOfElNeut++; + if( abs(DaugType) == 14 ) NumOfMuNeut++; + if( DaugType == 22 ) NumOfPhot++; + if( DaugType == 11 ) NumOfEl++; + if( DaugType ==-11 ) NumOfPos++; + if( DaugType == 13 ) NumOfMuMin++; + if( DaugType ==-13 ) NumOfMuPl++; + if( abs(DaugType) == 15 ) NumOfTau++; + if( abs(DaugType) == 16 ) NumOfTauNeut++; + + if( abs(DaugType) == 42 ) NumOfLQ++; + if( abs(DaugType) == abs(m_MotherPDG)&& + theDaug->barcode()%1000000 == m_MotherBarcode%1000000 ) samePart=true; + if(m_NumOfParents==1&&(m_MotherPDG==22||abs(m_MotherPDG)==11||abs(m_MotherPDG)==13||abs(m_MotherPDG)==211)&& + (DaugType > 1000000000||DaugType==0 ||DaugType == 2212||DaugType == 2112 || abs(DaugType) == 211|| abs(DaugType) == 111)) NumOfNucFr++; + } // cycle itrDaug + + + + if (m_MotherPDG == 22&&m_MothOriVert!=0){ + // get mother of photon + for (unsigned int ipIn=0; ipIn<m_MothOriVert->nIncomingParticles(); ++ipIn) { + const xAOD::TruthParticle* theMother=m_MothOriVert->outgoingParticle(ipIn); + m_PhotonMotherPDG = theMother->pdgId(); + m_PhotonMotherBarcode = theMother->barcode(); + m_PhotonMotherStatus = theMother->status(); + m_PhotonMother = theMother; + + } + } + + // if ( m_NumOfParents == 0 && m_NumOfDaug == 1 ) return SingleElec; + + + if ( (m_MotherPDG == 22 && m_NumOfDaug == 2 && NumOfEl == 1 && NumOfPos == 1)|| + (m_MotherPDG == 22 && m_NumOfDaug == 1 && (NumOfEl == 1 || NumOfPos == 1))) + return PhotonConv; + + + //e,gamma,pi+Nuclear->NuclearFragments+nuclons+e + if ( ( m_NumOfParents == 1&&(abs(m_MotherPDG)==22||abs(m_MotherPDG)==11||abs(m_MotherPDG)==15 )) + &&m_NumOfDaug>1&&NumOfNucFr!=0) return ElMagProc ; + + if ( m_NumOfParents == 1&&abs(m_MotherPDG)==211 + &&m_NumOfDaug>2&&NumOfNucFr!=0) return ElMagProc ; + + // nuclear photo fission + if ( m_MotherPDG == 22 && m_NumOfDaug > 4&&NumOfNucFr!=0) + return ElMagProc; + + // unknown process el(pos)->el+pos?? + if( abs(m_MotherPDG) == 11 && m_NumOfDaug == 2 && NumOfEl == 1 && NumOfPos == 1 ) + return ElMagProc; + + // unknown process el->el+el?? + if( m_MotherPDG == 11 && m_NumOfDaug == 2 && NumOfEl == 2 && NumOfPos == 0 ) + return ElMagProc; + // unknown process pos->pos+pos?? + if( m_MotherPDG == -11 && m_NumOfDaug == 2 && NumOfEl == 0 && NumOfPos == 2 ) + + return ElMagProc; + // unknown process pos/el->pos/el?? + if( abs(m_MotherPDG) == 11&&m_Mother->status()!=2&&m_MotherPDG==thePriPart->pdgId() && m_NumOfDaug == 1 &&!samePart) + return ElMagProc; + + // pi->pi+e+/e-; mu->mu+e+/e- ; + // gamma+ atom->gamma(the same) + e (compton scattering) + if( m_NumOfDaug == 2 && (NumOfEl == 1 || NumOfPos == 1 ) + && abs(m_MotherPDG)!=11&&samePart) return ElMagProc; + + + + if ( (m_MotherPDG == 111 && m_NumOfDaug == 3 && NumOfPhot == 1 && + NumOfEl == 1 && NumOfPos == 1)|| (m_MotherPDG == 111 && m_NumOfDaug == 4 && + NumOfPhot == 0 && NumOfEl == 2 && NumOfPos == 2) ) + return DalitzDec; + // Quark weak decay + if ( abs(m_MotherPDG)< 7 &&m_NumOfParents == 1&&m_NumOfDaug==3&&NumOfquark==1&&NumOfElNeut==1 ) return QuarkWeakDec; + + if( abs(m_MotherPDG) == 13&&NumOfNucFr!=0 ) return ElMagProc; + + + if( abs(m_MotherPDG)==6 ) return top; + + if( abs(m_MotherPDG)==24&&m_MothOriVert!=0&&m_MothOriVert->nIncomingParticles()!=0 ) { + + const xAOD::TruthVertex* prodVert = m_MothOriVert; + const xAOD::TruthParticle* ptrPart; + do { + ptrPart=prodVert->incomingParticle(0); + prodVert=ptrPart->prodVtx(); + } while(abs(ptrPart->pdgId())==24&&prodVert!=0); + + if(prodVert&&prodVert->nIncomingParticles()==1&&abs(ptrPart->pdgId())==9900012) return NuREle; + else if(prodVert&&prodVert->nIncomingParticles()==1&&abs(ptrPart->pdgId())==9900014) return NuRMu; + else if(prodVert&&prodVert->nIncomingParticles()==1&&abs(ptrPart->pdgId())==9900016) return NuRTau; + return WBoson; + }else if( abs(m_MotherPDG)==24) return WBoson; + + if( abs(m_MotherPDG)==23 ) return ZBoson; + + //-- Exotics + if( abs(m_MotherPDG)<7&&m_NumOfParents==2&&m_NumOfDaug==2&&NumOfEl==1&&NumOfPos==1&& + m_partOriVert->barcode()==-5){ + int pdg1 = m_partOriVert->incomingParticle(0)->pdgId(); + int pdg2 = m_partOriVert->incomingParticle(1)->pdgId(); + const xAOD::TruthVertex* TmpVert= m_partOriVert->outgoingParticle(0)->decayVtx(); + + if(abs(pdg1)==abs(pdg2)&&TmpVert->nIncomingParticles()==2) return ZorHeavyBoson; + } + + if(abs(m_MotherPDG)<7&&m_NumOfParents==2&&m_NumOfDaug==2&&(NumOfEl==1||NumOfPos==1)&& + NumOfElNeut==1&&m_partOriVert->barcode()==-5) { + const xAOD::TruthVertex* TmpVert= m_partOriVert->outgoingParticle(0)->decayVtx(); + if(TmpVert->nIncomingParticles()==2) return HeavyBoson; + } + + //MadGraphPythia ZWW*->lllnulnu + if(m_NumOfParents==1&&m_NumOfDaug>4&&(abs(m_MotherPDG)<7||m_MotherPDG==21)){ + + const xAOD::TruthParticle* thePartToCheck=thePriPart; + const xAOD::TruthParticle* theMother=thePriPart->prodVtx()->incomingParticle(0); + if( abs(theMother->pdgId())==11&&theMother->status()==2) thePartToCheck=theMother; + + bool isZboson=false; + bool isWboson=false; + bool skipnext=false; + + for (unsigned int ipOut=0; ipOut<m_partOriVert->nOutgoingParticles()-1; ++ipOut) { + const xAOD::TruthParticle* theDaug=m_partOriVert->outgoingParticle(ipOut); + const xAOD::TruthParticle* theNextDaug=m_partOriVert->outgoingParticle(ipOut+1); + + if(skipnext) {skipnext=false; continue;} + + if(abs(theDaug->pdgId())==11&&abs(theNextDaug->pdgId())==11 ) { + //Zboson + if(thePartToCheck==theDaug||thePartToCheck==theNextDaug) { isZboson=true; break;} + skipnext=true; + } else if(abs(theDaug->pdgId())==11&&abs(theNextDaug->pdgId())==12) { + //WBoson + if(thePartToCheck==theDaug||thePartToCheck==theNextDaug) { isWboson=true; break;} + skipnext=true; + } + } + if(isWboson) return WBoson; + if(isZboson) return ZBoson; + } + + //--Sherpa Z->ee + if(m_NumOfParents==2&&(m_NumOfDaug-NumOfquark-NumOfgluon)==2&&NumOfEl==1&&NumOfPos==1) return ZBoson; + + + //--Sherpa W->enu ?? + if(m_NumOfParents==2&&(m_NumOfDaug-NumOfquark-NumOfgluon)==2&&(NumOfEl==1||NumOfPos==1)&&NumOfElNeut==1) return WBoson; + + + //--Sherpa ZZ,ZW + if(m_NumOfParents==2&&(m_NumOfDaug-NumOfquark-NumOfgluon)==4&& + (NumOfEl+NumOfPos+NumOfMuPl+NumOfMuMin+NumOfTau+NumOfElNeut+NumOfMuNeut+NumOfTauNeut==4) ) { + int pdg1=m_partOriVert->incomingParticle(0)->pdgId(); + int pdg2=m_partOriVert->incomingParticle(1)->pdgId(); + if((abs(pdg1)==21&&abs(pdg2)==21)||(abs(pdg1)<7&&abs(pdg2)<7)|| + (pdg1==21&&abs(pdg2)<7)||(pdg2==21&&abs(pdg1)<7)) return DiBoson; + } + + + //-- McAtNLo + if( abs(m_MotherPDG)<7&&m_NumOfParents==2&&NumOfEl==1&&NumOfPos==1&&m_partOriVert->barcode()==-1){ + int pdg1=m_partOriVert->incomingParticle(0)->pdgId(); + int pdg2=m_partOriVert->incomingParticle(1)->pdgId(); + if(abs(pdg1)==abs(pdg2)) return ZBoson; + } + + if( abs(m_MotherPDG)==25 ) return Higgs; + + if( abs(m_MotherPDG)==35|| + abs(m_MotherPDG)==36|| + abs(m_MotherPDG)==37) return HiggsMSSM; + + if( abs(m_MotherPDG)==32|| + abs(m_MotherPDG)==33|| + abs(m_MotherPDG)==34) return HeavyBoson; + + if( abs(m_MotherPDG)==13) return Mu; + if( abs(m_MotherPDG)==15){ + + ParticleOrigin tauOrig= defOrigOfTau (m_mcTruthTES,m_Mother); + ParticleType tautype=defTypeOfTau(tauOrig); + if(tautype==IsoTau) return tauOrig; + else return TauLep; + } + + if(abs(m_MotherPDG)==9900024) return WBosonLRSM; + if(abs(m_MotherPDG)==9900012) return NuREle; + if(abs(m_MotherPDG)==9900014) return NuRMu; + if(abs(m_MotherPDG)==9900016) return NuRTau; + + if (abs(m_MotherPDG) == 42 || NumOfLQ!=0 ) return LQ; + + if( abs(m_MotherPDG)<2000040&& + abs(m_MotherPDG)>1000001) return SUSY; + + + ParticleType pType = defTypeOfHadron(m_MotherPDG); + if( (pType==BBbarMesonPart || pType==CCbarMesonPart ) + && m_MothOriVert!=0&&isHardScatVrtx(m_MothOriVert)) m_isPrompt=true; + + //---- + return convHadronTypeToOrig(pType); + +} + +//------------------------------------------------------------------------------- +ParticleType MCTruthClassifier::defTypeOfMuon(ParticleOrigin MuOrig){ + //------------------------------------------------------------------------------- + + + if( MuOrig == NonDefined) return UnknownMuon; + + + if (MuOrig == WBoson || MuOrig == ZBoson || MuOrig == top || + MuOrig == SingleMuon || MuOrig == Higgs || MuOrig == HiggsMSSM || + MuOrig == HeavyBoson || MuOrig == WBosonLRSM || MuOrig == NuREle || + MuOrig == NuRMu || MuOrig == NuRTau || MuOrig == LQ || + MuOrig == SUSY || MuOrig == DiBoson || MuOrig == ZorHeavyBoson || + m_isPrompt) + + return IsoMuon; + + if (MuOrig == JPsi || MuOrig == BottomMeson || + MuOrig == CharmedMeson || MuOrig == BottomBaryon || + MuOrig == CharmedBaryon || MuOrig == TauLep || + MuOrig == QuarkWeakDec) + return NonIsoMuon; + + // if (MuOrig == Pion || MuOrig == Kaon ) return DecayMuon; + return BkgMuon; + + +} + +//2345678901234567890123456789012345678901234567890123456789012345678901234567890 +//------------------------------------------------------------------------------- +ParticleOrigin MCTruthClassifier::defOrigOfMuon(const xAOD::TruthParticleContainer* m_mcTruthTES, + const xAOD::TruthParticle *thePart){ + //------------------------------------------------------------------------------- + + ATH_MSG_DEBUG( "Executing DefOrigOfMuon " ); + + int PriBarcode = thePart->barcode()%1000000; + const xAOD::TruthParticle* thePriPart =barcode_to_particle(m_mcTruthTES,PriBarcode); + if(!thePriPart) return NonDefined; + if(abs(thePriPart->pdgId())!=13) return NonDefined; + + const xAOD::TruthVertex* m_partOriVert = thePriPart->prodVtx(); + + + //-- to define muon outcome status + m_ParticleOutCome = defOutComeOfMuon(thePriPart); + + if(!m_partOriVert) return NonDefined; + + + m_NumOfParents=m_partOriVert->nIncomingParticles(); + if(m_NumOfParents>1) + ATH_MSG_WARNING ( "DefOrigOfMuon:: muon has more than one mother " ); + + + m_Mother = getMother(thePriPart); + if(!m_Mother) return NonDefined; + m_MothOriVert = m_Mother->prodVtx(); + m_MotherPDG = m_Mother->pdgId(); + m_MotherBarcode = m_Mother->barcode(); + + // to exclude interactions mu(barcode<10^6)->mu(barcode10^6)+e + // bool samePart=false; + //for (HepMC::GenVertex::particles_out_const_iterator + // itrDaug =m_partOriVert->particles_out_const_begin(); + // itrDaug!=m_partOriVert->particles_out_const_end(); ++itrDaug){ + // if( m_MotherPDG==(*itrDaug)->pdgId()&&m_MotherBarcode%1000000==(*itrDaug)->barcode()%1000000) samePart=true; + // } + + + if( ( abs(m_MotherPDG)==15||abs(m_MotherPDG)==24)&& m_MothOriVert!=0){ + long pPDG(0); + const xAOD::TruthParticle* MotherParent(0); + do { + pPDG=0; + MotherParent=getMother(m_Mother); + if(MotherParent) pPDG = MotherParent->pdgId(); + if(abs(pPDG)==13 || abs(pPDG)==15 || abs(pPDG)==24) m_Mother = MotherParent; + + } while ((abs(pPDG)==13 || abs(pPDG)==15 || abs(pPDG)==24) ); + + + if(abs(pPDG)==15 || abs(pPDG)==24 || abs(pPDG)==23 || abs(pPDG)==25 || + abs(pPDG)==35 || abs(pPDG)==36 || abs(pPDG)==37 || abs(pPDG)==32 || + abs(pPDG)==33 || abs(pPDG)==34 || abs(pPDG)==6 || + abs(pPDG)==9900024 || abs(pPDG)==9900012 || abs(pPDG)==9900014 || abs(pPDG)==9900016 || + (abs(pPDG)<2000040&& abs(pPDG)>1000001)) m_Mother = MotherParent; + + } + + m_MotherPDG = m_Mother->pdgId(); + m_MotherBarcode = m_Mother->barcode(); + m_MotherStatus = m_Mother->status(); + m_MothOriVert = m_Mother->prodVtx(); + m_partOriVert = m_Mother->decayVtx(); + m_NumOfParents = m_partOriVert->nIncomingParticles(); + m_NumOfDaug = m_partOriVert->nOutgoingParticles(); + + //--- + long DaugType(0); + int NumOfEl(0),NumOfPos(0); + int NumOfElNeut(0),NumOfMuNeut(0),NumOfLQ(0),NumOfquark(0),NumOfgluon(0); + int NumOfMuPl(0),NumOfMuMin(0); + int NumOfTau(0),NumOfTauNeut(0); + for(unsigned int ipOut=0;ipOut<m_partOriVert->nOutgoingParticles();ipOut++){ + const xAOD::TruthParticle * theDaug=m_partOriVert->outgoingParticle(ipOut); + DaugType = theDaug->pdgId(); + if( DaugType == 11 ) NumOfEl++; + if( DaugType ==-11 ) NumOfPos++; + if( DaugType == 13 ) NumOfMuMin++; + if( DaugType ==-13 ) NumOfMuPl++; + if( abs(DaugType) == 12 ) NumOfElNeut++; + if( abs(DaugType) == 14 ) NumOfMuNeut++; + if( abs(DaugType) == 15 ) NumOfTau++; + if( abs(DaugType) == 16 ) NumOfTauNeut++; + if( abs(DaugType) == 42 ) NumOfLQ++; + if( abs(DaugType) < 7 ) NumOfquark++; + if( abs(DaugType) == 21 ) NumOfgluon++; + } // cycle itrDaug + + + // if ( m_NumOfParents == 0 && m_NumOfDaug == 1 ) return SingleMuon; + + if ( abs(m_MotherPDG) == 211&&m_NumOfDaug == 2 && NumOfMuNeut == 1) + return PionDecay; + + if ( abs(m_MotherPDG) == 321&&m_NumOfDaug == 2 && NumOfMuNeut == 1) + return KaonDecay; + + if( abs(m_MotherPDG)==15 ) { + ParticleOrigin tauOrig= defOrigOfTau (m_mcTruthTES,m_Mother); + ParticleType tautype=defTypeOfTau(tauOrig); + if(tautype==IsoTau) return tauOrig; + else return TauLep; + } + + if( abs(m_MotherPDG)==6 ) return top; + + // Quark weak decay + if ( abs(m_MotherPDG)< 7 &&m_NumOfParents == 1&&m_NumOfDaug==3&&NumOfquark==1&&NumOfMuNeut==1 ) return QuarkWeakDec; + + if( abs(m_MotherPDG)==24&&m_MothOriVert!=0&&m_MothOriVert->nIncomingParticles()!=0 ) { + const xAOD::TruthVertex* prodVert = m_MothOriVert; + const xAOD::TruthParticle* itrP; + do { + itrP =prodVert->incomingParticle(0); + prodVert= itrP->prodVtx(); + } while(abs(itrP->pdgId())==24&&prodVert!=0); + + if(prodVert&&prodVert->nIncomingParticles()==1&&abs(itrP->pdgId())==9900012) return NuREle; + else if(prodVert&&prodVert->nIncomingParticles()==1&&abs(itrP->pdgId())==9900014) return NuRMu; + else if(prodVert&&prodVert->nIncomingParticles()==1&&abs(itrP->pdgId())==9900016) return NuRTau; + return WBoson; + } else if( abs(m_MotherPDG)==24) return WBoson; + + if( abs(m_MotherPDG)==23 ) return ZBoson; + + + + //-- Exotics + if( abs(m_MotherPDG)<7&&m_NumOfParents==2&&NumOfMuPl==1&&NumOfMuMin==1&& + NumOfEl+NumOfPos==0&&NumOfTau==0&&m_partOriVert->barcode()==-5){ + int pdg1= m_partOriVert->incomingParticle(0)->pdgId(); + int pdg2= m_partOriVert->incomingParticle(1)->pdgId(); + const xAOD::TruthParticle* theDaug =m_partOriVert->outgoingParticle(0); + const xAOD::TruthVertex* TmpVert=theDaug->decayVtx(); + if(abs(pdg1)==abs(pdg2)&&TmpVert->nIncomingParticles()==2) return ZorHeavyBoson; + } + + if(abs(m_MotherPDG)<7&&m_NumOfParents==2&&(NumOfMuMin==1||NumOfMuPl==1)&& + NumOfMuNeut==1&&NumOfEl+NumOfPos==0&&NumOfTau==0&&m_partOriVert->barcode()==-5) { + const xAOD::TruthParticle* theDaug =m_partOriVert->outgoingParticle(0); + const xAOD::TruthVertex* TmpVert=theDaug->decayVtx(); + if(TmpVert->nIncomingParticles()==2) return HeavyBoson; + } + + //MadGraphPythia ZWW*->lllnulnu + + if(m_NumOfParents==1&&m_NumOfDaug>4&&(abs(m_MotherPDG)<7||m_MotherPDG==21)){ + bool isZboson=false; + bool isWboson=false; + bool skipnext=false; + for(unsigned int ipOut=0;ipOut<m_partOriVert->nOutgoingParticles()-1;ipOut++){ + if(skipnext) {skipnext=false; continue;} + const xAOD::TruthParticle* theDaug=m_partOriVert->outgoingParticle(ipOut); + const xAOD::TruthParticle* theNextDaug=m_partOriVert->outgoingParticle(ipOut+1); + + if( abs(theDaug->pdgId())==13&&abs(theNextDaug->pdgId())==13) { + //Zboson + if(thePriPart==theDaug||thePriPart==theNextDaug) { isZboson=true; break;} + skipnext=true; + } else if(abs(theDaug->pdgId())==13&&abs(theNextDaug->pdgId())==14) { + //WBoson + if(thePriPart==theDaug||thePriPart==theNextDaug) { isWboson=true; break;} + skipnext=true; + } + } + if(isWboson) return WBoson; + if(isZboson) return ZBoson; + } + + //--Sherpa Z->mumu + if(m_NumOfParents==2&&(m_NumOfDaug-NumOfquark-NumOfgluon)==2&&NumOfMuPl==1&&NumOfMuMin==1) return ZBoson; + + //--Sherpa W->munu ?? + // if(m_NumOfParents==2&&(m_NumOfDaug-NumOfquark-NumOfgluon)==2&&(NumOfEl==1||NumOfPos==1)&&NumOfElNeut==1) return WBoson; + if(m_NumOfParents==2&&(m_NumOfDaug-NumOfquark-NumOfgluon)==2&&(NumOfMuPl==1||NumOfMuMin==1)&&NumOfMuNeut==1) return WBoson; + + + //--Sherpa ZZ,ZW + if(m_NumOfParents==2&&(m_NumOfDaug-NumOfquark-NumOfgluon)==4&& + (NumOfEl+NumOfPos+NumOfMuPl+NumOfMuMin+NumOfTau+NumOfElNeut+NumOfMuNeut+NumOfTauNeut==4) ) { + int pdg1=m_partOriVert->incomingParticle(0)->pdgId(); + int pdg2=m_partOriVert->incomingParticle(1)->pdgId(); + if((abs(pdg1)==21&&abs(pdg2)==21)||(abs(pdg1)<7&&abs(pdg2)<7)|| + (pdg1==21&&abs(pdg2)<7)||(pdg2==21&&abs(pdg1)<7)) return DiBoson; + } + + + //-- McAtNLo + if( abs(m_MotherPDG)<7&&m_NumOfParents==2&&NumOfMuPl==1&&NumOfMuMin==1&&m_partOriVert->barcode()==-1){ + int pdg1=m_partOriVert->incomingParticle(0)->pdgId(); + int pdg2=m_partOriVert->incomingParticle(0)->pdgId(); + if(abs(pdg1)==abs(pdg2)) return ZBoson; + } + + + if( abs(m_MotherPDG)==25 ) return Higgs; + + if( abs(m_MotherPDG)==35|| + abs(m_MotherPDG)==36|| + abs(m_MotherPDG)==37) return HiggsMSSM; + + if( abs(m_MotherPDG)==32|| + abs(m_MotherPDG)==33|| + abs(m_MotherPDG)==34) return HeavyBoson; + + if(abs(m_MotherPDG)==9900024) return WBosonLRSM; + if(abs(m_MotherPDG)==9900012) return NuREle; + if(abs(m_MotherPDG)==9900014) return NuRMu; + if(abs(m_MotherPDG)==9900016) return NuRTau; + + if (abs(m_MotherPDG) == 42 || NumOfLQ!=0 ) return LQ; + + if( abs(m_MotherPDG)<2000040&& + abs(m_MotherPDG)>1000001) return SUSY; + + + ParticleType pType = defTypeOfHadron(m_MotherPDG); + if( (pType==BBbarMesonPart || pType==CCbarMesonPart ) + && m_MothOriVert!=0&&isHardScatVrtx(m_MothOriVert)) m_isPrompt=true; + + return convHadronTypeToOrig(pType); + + +} +//------------------------------------------------------------------------------- +ParticleType MCTruthClassifier::defTypeOfTau(ParticleOrigin TauOrig){ + //------------------------------------------------------------------------------- + + + if( TauOrig == NonDefined) return UnknownTau; + + + if (TauOrig == WBoson || TauOrig == ZBoson || TauOrig == top || + TauOrig == SingleMuon || TauOrig == Higgs || TauOrig == HiggsMSSM || + TauOrig == HeavyBoson || TauOrig == WBosonLRSM || TauOrig == NuREle || + TauOrig == NuRMu || TauOrig == NuRTau || TauOrig == SUSY || + TauOrig == DiBoson || TauOrig == ZorHeavyBoson ) + return IsoTau; + + if (TauOrig == JPsi || TauOrig == BottomMeson || + TauOrig == CharmedMeson || TauOrig == BottomBaryon || + TauOrig == CharmedBaryon || TauOrig == QuarkWeakDec) + return NonIsoTau; + + return BkgTau; + + +} + +//2345678901234567890123456789012345678901234567890123456789012345678901234567890 +//------------------------------------------------------------------------------- +ParticleOrigin MCTruthClassifier::defOrigOfTau(const xAOD::TruthParticleContainer* m_mcTruthTES, + const xAOD::TruthParticle *thePart){ + //------------------------------------------------------------------------------- + + ATH_MSG_DEBUG( "Executing DefOrigOfTau " ); + + + int PriBarcode = thePart->barcode()%1000000; + const xAOD::TruthParticle* thePriPart = barcode_to_particle(m_mcTruthTES,PriBarcode); + if(!thePriPart) return NonDefined; + if(abs(thePriPart->pdgId())!=15) return NonDefined; + + const xAOD::TruthVertex* m_partOriVert = thePriPart->prodVtx(); + + + //-- to define tau outcome status + m_ParticleOutCome = defOutComeOfTau(thePriPart); + + if(!m_partOriVert) return NonDefined; + + m_NumOfParents=m_partOriVert->nIncomingParticles(); + if(m_NumOfParents>1) + ATH_MSG_WARNING( "DefOrigOfTau:: tau has more than one mother " ); + + m_Mother=getMother(thePriPart); + if(!m_Mother) return NonDefined; + m_MothOriVert = m_Mother->prodVtx(); + + const xAOD::TruthParticle* MotherParent(0); + if( abs(m_MotherPDG)==24 && m_MothOriVert!=0){ + MotherParent=getMother(m_Mother); + long pPDG(0); + if(MotherParent) pPDG = MotherParent->pdgId(); + if(abs(pPDG)==6) m_Mother = MotherParent; + } + + m_MotherPDG = m_Mother->pdgId(); + m_MotherBarcode = m_Mother->barcode(); + m_MotherStatus = m_Mother->status(); + m_MothOriVert = m_Mother->prodVtx(); + m_partOriVert = m_Mother->decayVtx(); + m_NumOfParents = m_partOriVert->nIncomingParticles(); + m_NumOfDaug = m_partOriVert->nOutgoingParticles(); + + + int NumOfPhot(0),NumOfEl(0),NumOfPos(0); + int NumOfquark(0),NumOfgluon(0),NumOfElNeut(0); + int NumOfMuPl(0),NumOfMuMin(0),NumOfMuNeut(0); + int NumOfTau(0),NumOfTauNeut(0); + long DaugType(0); + + for(unsigned int ipOut=0;ipOut<m_partOriVert->nOutgoingParticles(); ipOut++){ + DaugType = m_partOriVert->outgoingParticle(ipOut)->pdgId(); + if( abs(DaugType) < 7 ) NumOfquark++; + if( abs(DaugType) == 21 ) NumOfgluon++; + if( abs(DaugType) == 12 ) NumOfElNeut++; + if( abs(DaugType) == 14 ) NumOfMuNeut++; + if( DaugType == 22 ) NumOfPhot++; + if( DaugType == 11 ) NumOfEl++; + if( DaugType ==-11 ) NumOfPos++; + if( DaugType == 13 ) NumOfMuMin++; + if( DaugType ==-13 ) NumOfMuPl++; + if( abs(DaugType) == 15 ) NumOfTau++; + if( abs(DaugType) == 16 ) NumOfTauNeut++; + } + + // if ( m_NumOfParents == 0 && m_NumOfDaug == 1 ) return SingleTau; + + if( abs(m_MotherPDG)==6 ) return top; + + if( abs(m_MotherPDG)==24&&m_MothOriVert!=0&&m_MothOriVert->nIncomingParticles()!=0 ){ + + const xAOD::TruthVertex* prodVert = m_MothOriVert; + const xAOD::TruthParticle* itrP; + do { + itrP =prodVert->incomingParticle(0); + prodVert= itrP->prodVtx(); + } while(abs(itrP->pdgId())==24&&prodVert!=0); + + if(prodVert&&prodVert->nIncomingParticles()==1&&abs(itrP->pdgId())==9900012) return NuREle; + else if(prodVert&&prodVert->nIncomingParticles()==1&&abs(itrP->pdgId())==9900014) return NuRMu; + else if(prodVert&&prodVert->nIncomingParticles()==1&&abs(itrP->pdgId())==9900016) return NuRTau; + return WBoson; + } else if( abs(m_MotherPDG)==24) return WBoson; + + if( abs(m_MotherPDG)==23 ) return ZBoson; + + if(m_NumOfParents==1&&m_NumOfDaug>4&&(abs(m_MotherPDG)<7||m_MotherPDG==21)){ + bool isZboson=false; + bool isWboson=false; + bool skipnext=false; + for(unsigned int ipOut=0;m_partOriVert->nOutgoingParticles()-1;ipOut++){ + if(skipnext) {skipnext=false; continue;} + const xAOD::TruthParticle* theDaug=m_partOriVert->outgoingParticle(ipOut); + const xAOD::TruthParticle* theNextDaug=m_partOriVert->outgoingParticle(ipOut+1); + + if( abs(theDaug->pdgId())==15&&abs(theNextDaug->pdgId())==15) { + //Zboson + if(thePriPart==theDaug||thePriPart==theNextDaug) { isZboson=true; break;} + skipnext=true; + } else if(abs(theDaug->pdgId())==15&&abs(theNextDaug->pdgId())==16) { + //WBoson + if(thePriPart==theDaug||thePriPart==theNextDaug) { isWboson=true; break;} + skipnext=true; + } + } + if(isWboson) return WBoson; + if(isZboson) return ZBoson; + } + //--Sherpa Z->tautau + if(m_NumOfParents==2&&(m_NumOfDaug-NumOfquark-NumOfgluon)==2&&NumOfTau==2){ + int pdg1=m_partOriVert->incomingParticle(0)->pdgId(); + int pdg2=m_partOriVert->incomingParticle(1)->pdgId(); + if((abs(pdg1)==21&&abs(pdg2)==21)||(abs(pdg1)<7&&abs(pdg2)<7)|| + (pdg1==21&&abs(pdg2)<7)||(pdg2==21&&abs(pdg1)<7)) return ZBoson; + } + + //--Sherpa W->taunu new + if(m_NumOfParents==2&&(m_NumOfDaug-NumOfquark-NumOfgluon)==2&&NumOfTau==1&&NumOfTauNeut==1) return WBoson; + + + //--Sherpa ZZ,ZW + if(m_NumOfParents==2&&(m_NumOfDaug-NumOfquark-NumOfgluon)==4&& + (NumOfEl+NumOfPos+NumOfMuPl+NumOfMuMin+NumOfTau+NumOfElNeut+NumOfMuNeut+NumOfTauNeut==4) ) { + int pdg1=m_partOriVert->incomingParticle(0)->pdgId(); + int pdg2=m_partOriVert->incomingParticle(1)->pdgId(); + if((abs(pdg1)==21&&abs(pdg2)==21)||(abs(pdg1)<7&&abs(pdg2)<7)|| + (pdg1==21&&abs(pdg2)<7)||(pdg2==21&&abs(pdg1)<7)) return DiBoson; + } + + + if( abs(m_MotherPDG)==25 ) return Higgs; + + if( abs(m_MotherPDG)==35|| + abs(m_MotherPDG)==36|| + abs(m_MotherPDG)==37) return HiggsMSSM; + + if( abs(m_MotherPDG)==32|| + abs(m_MotherPDG)==33|| + abs(m_MotherPDG)==34) return HeavyBoson; + + + if(abs(m_MotherPDG)==9900024) return WBosonLRSM; + if(abs(m_MotherPDG)==9900016) return NuRTau; + + if( abs(m_MotherPDG)<2000040&& + abs(m_MotherPDG)>1000001) return SUSY; + + + if ( abs(m_MotherPDG) == 443 ) return JPsi; + + ParticleType pType = defTypeOfHadron(m_MotherPDG); + return convHadronTypeToOrig(pType); + +} + + +//------------------------------------------------------------------------------- +ParticleType MCTruthClassifier::defTypeOfPhoton(ParticleOrigin PhotOrig){ + //------------------------------------------------------------------------------- + + + + if (PhotOrig == NonDefined) return UnknownPhoton; + + if (PhotOrig == WBoson || PhotOrig == ZBoson || PhotOrig == SinglePhot || + PhotOrig == Higgs || PhotOrig == HiggsMSSM || PhotOrig == HeavyBoson || + PhotOrig == PromptPhot || PhotOrig == SUSY ) return IsoPhoton; + + if (PhotOrig == ISRPhot || PhotOrig == FSRPhot || PhotOrig == TauLep || + PhotOrig == Mu || PhotOrig == NuREle || PhotOrig == NuRMu || + PhotOrig == NuRTau ) + return NonIsoPhoton; + + + return BkgPhoton; + + +} +//2345678901234567890123456789012345678901234567890123456789012345678901234567890 +//------------------------------------------------------------------------------- +ParticleOrigin MCTruthClassifier::defOrigOfPhoton(const xAOD::TruthParticleContainer* m_mcTruthTES, + const xAOD::TruthParticle *thePart) +//------------------------------------------------------------------------------- +{ + + ATH_MSG_DEBUG( "Executing DefOrigOfPhoton " ); + + m_Mother = 0; + m_MotherPDG = 0; + m_MotherBarcode = 0; + m_MotherStatus = 0; + m_PhotonMotherPDG = 0; + m_PhotonMotherBarcode = 0; + + m_ParticleOutCome = UnknownOutCome; + + + int PriBarcode = thePart->barcode()%1000000; + + const xAOD::TruthParticle* thePriPart = barcode_to_particle(m_mcTruthTES,PriBarcode); + if(!thePriPart) return NonDefined; + if(abs(thePriPart->pdgId())!=22) return NonDefined; + + const xAOD::TruthVertex* m_partOriVert = thePriPart->prodVtx(); + + //-- to define photon outcome status + m_ParticleOutCome = defOutComeOfPhoton(thePriPart); + + if(!m_partOriVert) return NonDefined; + + + m_NumOfParents=m_partOriVert->nIncomingParticles(); + if(m_partOriVert->nIncomingParticles()>1) + ATH_MSG_WARNING( "DefOrigOfPhoton:: photon has more than one mother " ); + + m_Mother = getMother(thePriPart); + if(!m_Mother) return NonDefined; + m_MotherPDG = m_Mother->pdgId(); + m_MothOriVert = m_Mother->prodVtx(); + m_MotherBarcode = m_Mother->barcode(); + m_MotherStatus = m_Mother->status(); + m_partOriVert = m_Mother->decayVtx(); + m_NumOfParents = m_partOriVert->nIncomingParticles(); + m_NumOfDaug = m_partOriVert->nOutgoingParticles(); + + int NumOfNucFr(0),NumOfEl(0),NumOfPos(0),NumOfMu(0),NumOfTau(0), NumOfPht(0),NumOfLQ(0); + long DaugBarcode(0),DaugType(0), NumOfLep(0), NumOfNeut(0); + for(unsigned int ipOut=0;ipOut<m_partOriVert->nOutgoingParticles();ipOut++){ + + DaugType = m_partOriVert->outgoingParticle(ipOut)->pdgId(); + if(m_NumOfParents==1&&(m_MotherPDG==22||abs(m_MotherPDG)==11||abs(m_MotherPDG)==211)&& + (DaugType > 1000000000 ||DaugType==0 ||DaugType == 2212||DaugType == 2112)) NumOfNucFr++; + if(DaugType == 22) NumOfPht++; + if(DaugType == 11) NumOfEl++; + if(DaugType ==-11) NumOfPos++; + if(abs(DaugType) == 13) NumOfMu++; + if(abs(DaugType) == 15) NumOfTau++; + if(abs(DaugType) == 42) NumOfLQ++; + if(abs(DaugType) == 11||abs(DaugType) == 13||abs(DaugType) == 15) NumOfLep++; + if(abs(DaugType) == 12||abs(DaugType) == 14||abs(DaugType) == 16) NumOfNeut++; + + if(DaugType == m_MotherPDG ) DaugBarcode = m_partOriVert->outgoingParticle(ipOut)->barcode() ; + } // cycle itrDaug + + + + bool foundISR=false; + bool foundFSR=false; + + // if ( m_NumOfParents == 0 && m_NumOfDaug == 1 ) return SinglePhot; + + + if ( m_NumOfParents == 1 && m_NumOfDaug == 2 && + DaugBarcode%1000000==m_MotherBarcode%1000000 ) return BremPhot; + + if ( m_NumOfParents == 1 && m_NumOfDaug == 2 && + abs(m_MotherPDG)==11&& NumOfPht==2 ) return ElMagProc; + + + // decay of W,Z and Higgs to lepton with FSR generated by Pythia + if(m_NumOfParents == 1 && m_NumOfDaug==2&& + (abs(m_MotherPDG)==11||abs(m_MotherPDG)==13||abs(m_MotherPDG)==15)&& + DaugBarcode%1000000!=m_MotherBarcode%1000000&& m_MothOriVert!=0&&m_MothOriVert->nIncomingParticles()==1){ + int itr=0; + long PartPDG=0; + const xAOD::TruthVertex* prodVert = m_MothOriVert; + const xAOD::TruthVertex*Vert=0; + do { + Vert = prodVert; + for(unsigned int ipIn=0;ipIn<Vert->nIncomingParticles();ipIn++){ + PartPDG = abs(Vert->incomingParticle(ipIn)->pdgId()); + prodVert = Vert->incomingParticle(ipIn)->prodVtx(); + if(PartPDG==23||PartPDG==24||PartPDG==25) foundFSR=true; + }// cycle itrMother + itr++; + if(itr>100) {ATH_MSG_WARNING( "DefOrigOfPhoton:: infinite while" ); break;} + } while (prodVert!=0&&abs(m_MotherPDG)==PartPDG); + + if(foundFSR) return FSRPhot; + + } + + // Nucl reaction + // gamma+Nuclear=>gamma+Nucl.Fr+Nuclons+pions + // e+Nuclear=>e+gamma+Nucl.Fr+Nuclons+pions + // pi+Nuclear=>gamma+Nucl.Fr+Nuclons+pions + + if ( ( m_NumOfParents == 1&&abs((m_MotherPDG)==22||abs(m_MotherPDG)==11)&&m_NumOfDaug>2&&NumOfNucFr!=0)|| + ( m_NumOfParents == 1&&abs(m_MotherPDG)==211&&m_NumOfDaug>10&&NumOfNucFr!=0) || + ( m_NumOfParents == 1&&m_MotherPDG==22&&m_NumOfDaug>10&&m_MotherStatus==1)|| + ( m_NumOfParents == 1&&m_MotherPDG>1000000000) + ) return NucReact; + + if ( abs(m_MotherPDG)==13 && NumOfMu==0 ) return Mu; + + if ( abs(m_MotherPDG)==15 && NumOfTau==0 ) return TauLep; + + //-- to find prompt photon + if (abs(m_partOriVert->barcode())==5){ + int nqin(0),ngin(0),nqout(0),ngout(0),npartin(0),npartout(0),nphtout(0); + if(m_partOriVert!=0){ + npartin = m_partOriVert->nIncomingParticles(); + for(unsigned int ipIn=0;ipIn<m_partOriVert->nIncomingParticles();ipIn++){ + if(abs(m_partOriVert->incomingParticle(ipIn)->pdgId())<7) nqin++; + if(abs(m_partOriVert->incomingParticle(ipIn)->pdgId())==21) ngin++; + } + + npartout = m_partOriVert->nOutgoingParticles(); + for(unsigned int ipOut=0;ipOut<m_partOriVert->nOutgoingParticles();ipOut++){ + if(abs(m_partOriVert->outgoingParticle(ipOut)->pdgId())<7) nqout++; + if(abs(m_partOriVert->outgoingParticle(ipOut)->pdgId())==21) ngout++; + if(abs(m_partOriVert->outgoingParticle(ipOut)->pdgId())==22) nphtout++; + + } + } + + if(npartout==2&&npartin==2&& + ( ((nqin==2&&ngin==0)&&(nqout==0&&ngout==1&&nphtout==1)) || + ((nqin==2&&ngin==0)&&(nqout==0&&ngout==0&&nphtout==2)) || + ((nqin==1&&ngin==1)&&(nqout==1&&ngout==0&&nphtout==1)) || + ((nqin==0&&ngin==2)&&(nqout==0&&ngout==0&&nphtout==2)) || + ((nqin==0&&ngin==2)&&(nqout==0&&ngout==1&&nphtout==1)) + ) ) return PromptPhot; + } + + //-- to find initial and final state raiation and underline photons + //-- dijets and min bias + if(m_NumOfParents==1&&m_MotherStatus==3){ + + // const xAOD::TruthParticle* thePhotMoth = (*mcEventItr)->barcode_to_particle(m_MotherBarcode); + // const xAOD::TruthVertex* MothOriVert = thePhotMoth->prodVtx(); + if(m_MothOriVert!=0&&abs(m_MothOriVert->barcode())==5) return FSRPhot; + + for(unsigned int ipOut=0;ipOut<m_partOriVert->nOutgoingParticles();ipOut++){ + if(m_partOriVert->outgoingParticle(ipOut)->status()!=3|| + m_MotherPDG!=m_partOriVert->outgoingParticle(ipOut)->pdgId()) continue; + const xAOD::TruthVertex* Vrtx=m_partOriVert->outgoingParticle(ipOut)->decayVtx(); + if(!Vrtx) continue; + if(abs(Vrtx->barcode())==5) foundISR=true; + } + + if( foundISR ) return ISRPhot; + else return UndrPhot; + + } + + //-- to find initial and final state raiation and underline photons + //-- SUSY + if(m_NumOfParents==1&&(abs(m_MotherPDG)<7||m_MotherPDG==21)){ + for(unsigned int ipOut=0;ipOut<m_partOriVert->nOutgoingParticles();ipOut++){ + if(m_MotherPDG!=m_partOriVert->outgoingParticle(ipOut)->pdgId()) continue; + const xAOD::TruthVertex* Vrtx = m_partOriVert->outgoingParticle(ipOut)->decayVtx(); + if(!Vrtx) continue; + if(Vrtx->nOutgoingParticles()!=1&&Vrtx->nIncomingParticles()==1) continue; + if(Vrtx->outgoingParticle(0)->pdgId()==91) foundISR=true; + } + if( foundISR ) return ISRPhot; + else return UndrPhot; + + } + + //-- to find final state radiation + //-- Exotics + if(m_NumOfParents==1&&abs(m_MotherPDG)==11&&m_MotherStatus==2&&m_MothOriVert!=0&&m_MothOriVert->nIncomingParticles()!=0){ + const xAOD::TruthParticle* itrP =m_MothOriVert->incomingParticle(0); + if(m_MothOriVert->nIncomingParticles()==1&&abs(itrP->pdgId())==11&&itrP->prodVtx()!=0&& + abs(itrP->prodVtx()->barcode())==5&&itrP->status()==3) return FSRPhot; + } + + + // FSR from Photos + //-- Exotics- CompHep + if(m_NumOfParents==2&&((abs(m_MotherPDG)==11&&NumOfEl==1&&NumOfPos==1)|| + (abs(m_MotherPDG)==13&&NumOfMu==2)||(abs(m_MotherPDG)==15&&NumOfTau==2))) { + int pdg1=m_partOriVert->incomingParticle(0)->pdgId(); + int pdg2=m_partOriVert->incomingParticle(1)->pdgId(); + if (abs(pdg1)==abs(pdg2)) return FSRPhot; + } + + + if(m_NumOfParents==2&&NumOfLep==1&&NumOfNeut==1&&(abs(m_MotherPDG)==11||abs(m_MotherPDG)==12)) return FSRPhot; + + + + + //-- Exotics - CompHep + if (abs(m_MotherPDG)==11&& m_NumOfParents == 1 && m_NumOfDaug == 2 && (NumOfEl==1||NumOfPos==1)&&NumOfPht==1&& + DaugBarcode%1000000!=m_MotherBarcode%1000000&&DaugBarcode<20000&&m_MotherBarcode<20000 ) return FSRPhot; + + + // FSR from Photos + if ( abs(m_MotherPDG)==23&&( (NumOfEl+NumOfPos==2 || NumOfEl+NumOfPos==4 )|| + (NumOfMu==2||NumOfMu==4) || + (NumOfTau==2||NumOfTau==4)) &&NumOfPht>0) + return FSRPhot; + + if( abs(m_MotherPDG)==9900024&&NumOfPht>0) return FSRPhot; + + if( abs(m_MotherPDG)==9900012&&NumOfPht>0) return FSRPhot; + if( abs(m_MotherPDG)==9900014&&NumOfPht>0) return FSRPhot; + if( abs(m_MotherPDG)==9900016&&NumOfPht>0) return FSRPhot; + + if(m_NumOfParents==2&&NumOfLQ==1) return FSRPhot; + + + //--- other process + + + if ( abs(m_MotherPDG)==23) return ZBoson; + + + if ( abs(m_MotherPDG)==24 ) { + + if(NumOfLep==1&&NumOfNeut==1&&m_NumOfDaug==NumOfLep+NumOfNeut+NumOfPht) return FSRPhot; + + if(m_MothOriVert!=0&&m_MothOriVert->nIncomingParticles()!=0){ + const xAOD::TruthVertex* prodVert = m_MothOriVert; + const xAOD::TruthParticle* itrP; + do { + itrP =prodVert->incomingParticle(0); + prodVert= itrP->prodVtx(); + } while(abs(itrP->pdgId())==24&&prodVert!=0); + + if(prodVert&&prodVert->nIncomingParticles()==1&&abs(itrP->pdgId())==15) return TauLep; + else if(prodVert&&prodVert->nIncomingParticles()==1&&abs(itrP->pdgId())==13) return Mu; + else if(prodVert&&prodVert->nIncomingParticles()==1&&abs(itrP->pdgId())==9900012) return NuREle; + else if(prodVert&&prodVert->nIncomingParticles()==1&&abs(itrP->pdgId())==9900014) return NuRMu; + else if(prodVert&&prodVert->nIncomingParticles()==1&&abs(itrP->pdgId())==9900016) return NuRTau; + + } else return WBoson; + } + + //MadGraphPythia ZWW*->lllnulnu + if(m_NumOfParents==1&&m_NumOfDaug>4&&(abs(m_MotherPDG)<7||m_MotherPDG==21)){ + bool isZboson=false; + bool isWboson=false; + bool skipnext=false; + //cout<<"check electrons "<<m_partOriVert->nOutgoingParticles()<<endl; + //int iter=0; + for(unsigned int ipOut=0;ipOut<m_partOriVert->nOutgoingParticles()-1;ipOut++){ + if(skipnext) {skipnext=false; continue;} + const xAOD::TruthParticle* theDaug=m_partOriVert->outgoingParticle(ipOut); + const xAOD::TruthParticle* theNextDaug=m_partOriVert->outgoingParticle(ipOut+1); + //cout<<"not skipped theDaug "<<theDaug<<" theNextDaug "<<theNextDaug<<endl; + + if(abs(theDaug->pdgId())==15&&abs(theNextDaug->pdgId())==15 ){ + //Zboson + //cout<<"Zboson "<<thePriPart<<" "<<theDaug<<" "<<theNextDaug<<endl; + if(thePriPart==theDaug||thePriPart==theNextDaug) { isZboson=true; break;} + skipnext=true; + } else if( abs(theDaug->pdgId())==15&&abs(theNextDaug->pdgId())==16) { + //WBoson + //cout<<"Wboson "<<thePriPart<<" "<<theDaug<<" "<<theNextDaug<<endl; + if(thePriPart==theDaug||thePriPart==theNextDaug) { isWboson=true; break;} + skipnext=true; + } + //cout<<"here "<<endl; + } + //cout<<"=============== end of cycle isWboson "<<isWboson<<" isZboson "<<isZboson<<endl; + if(isWboson) return WBoson; + if(isZboson) return ZBoson; + } + + //--Sherpa ZZ,ZW+FSR + if(m_NumOfParents==4&&(m_NumOfDaug-NumOfPht)==4&&(NumOfLep+NumOfNeut==4)) { + int pdg1=m_partOriVert->incomingParticle(0)->pdgId(); + int pdg2=m_partOriVert->incomingParticle(1)->pdgId(); + int pdg3=m_partOriVert->incomingParticle(2)->pdgId(); + int pdg4=m_partOriVert->incomingParticle(3)->pdgId(); + if(abs(pdg1)<17&&abs(pdg1)>10&&abs(pdg2)<17&&abs(pdg2)>10&&abs(pdg3)<17&&abs(pdg3)>10&& + abs(pdg4)<17&&abs(pdg4)>10 ) return FSRPhot; + } + + + if ( abs(m_MotherPDG)==25 ) return Higgs; + + if ( abs(m_MotherPDG)==111 ) return PiZero; + + if( abs(m_MotherPDG)==35|| + abs(m_MotherPDG)==36|| + abs(m_MotherPDG)==37) return HiggsMSSM; + + if( abs(m_MotherPDG)==32|| + abs(m_MotherPDG)==33|| + abs(m_MotherPDG)==34) return HeavyBoson; + + if( abs(m_MotherPDG)<2000040&& + abs(m_MotherPDG)>1000001) return SUSY; + + + + ParticleType pType = defTypeOfHadron(m_MotherPDG); + if( (pType==BBbarMesonPart || pType==CCbarMesonPart ) + && m_MothOriVert!=0&&isHardScatVrtx(m_MothOriVert)) m_isPrompt=true; + return convHadronTypeToOrig(pType); + + + +} +//----------------------------------------------------------------------------------------- +const xAOD::TruthParticle* +MCTruthClassifier::egammaClusMatch(const xAOD::CaloCluster* clus, bool isFwrdEle){ + //----------------------------------------------------------------------------------------- + + ATH_MSG_DEBUG( "Executing egammaClusMatch " ); + + const xAOD::TruthParticle* theMatchPart=0; + + //retrieve collection and get a pointer + + const xAOD::TruthParticleContainer * m_xTruthParticleContainer; + StatusCode sc = evtStore()->retrieve(m_xTruthParticleContainer, m_xaodTruthParticleContainerName); + if (sc.isFailure()||!m_xTruthParticleContainer){ + ATH_MSG_WARNING( "No xAODTruthParticleContainer "<<m_xaodTruthParticleContainerName<<" found" ); + return theMatchPart; + } + ATH_MSG_DEBUG( "xAODTruthParticleContainer " << m_xaodTruthParticleContainerName<<" successfully retrieved " ); + + const xAOD::TruthParticle* thePhoton(0); + const xAOD::TruthParticle* theLeadingPartInCone(0); + const xAOD::TruthParticle* theBestPartOutCone(0); + const xAOD::TruthParticle* theBestPartdR(0); + double LeadingPhtPT(0),LeadingPartPT(0); + double LeadingPhtdR(999.),LeadingPartdR(999.),BestPartdR(999.); + + for(const auto thePart : *m_xTruthParticleContainer){ + + // loop over the stable particle + if(thePart->status()!=1) continue; + // excluding G4 particle + if(thePart->barcode()>=200000) continue; + long iParticlePDG = thePart->pdgId(); + // excluding neutrino + if(abs(iParticlePDG)==12||abs(iParticlePDG)==14||abs(iParticlePDG)==16) continue; + + + double pt = thePart->pt()/GeV; + double q = partCharge(thePart); + // exclude charged particles with pT<1 GeV + if(q!=0&&pt<m_pTChargePartCut) continue; + if(q==0&&pt<m_pTNeutralPartCut) continue; + + // eleptical cone for extrapolations m_partExtrConePhi X m_partExtrConeEta + if(!isFwrdEle&&m_ROICone&& pow((detPhi(clus->phiBE(2),thePart->phi())/m_partExtrConePhi),2)+ + pow((detEta(clus->etaBE(2),thePart->eta())/m_partExtrConeEta),2)>1.0 ) continue; + + //If we are looking a frwd electron and the eta of the truth particle is less than 2.3 continue + //Forward electrons should start after 2.47 . + if(isFwrdEle && (fabs(thePart->eta())<2.3) ) continue; + + double dR(-999.); + bool isNCone=false; + bool isExt = genPartToCalo(clus, thePart,isFwrdEle, dR, isNCone); + if(!isExt) continue; + + m_egPartPtr.push_back(thePart); + m_egPartdR.push_back(dR); + + theMatchPart = barcode_to_particle(m_xTruthParticleContainer,thePart->barcode()%1000000); + m_egPartClas.push_back(particleTruthClassifier(theMatchPart)); + + // the leading photon inside narrow eleptical cone m_partExtrConePhi X m_partExtrConeEta + if(!isFwrdEle&&iParticlePDG==22&&isNCone&&pt>LeadingPhtPT) { thePhoton = thePart; LeadingPhtPT=pt; LeadingPhtdR=dR;} + // leading particle (excluding photon) inside narrow eleptic cone m_partExtrConePhi X m_partExtrConeEta + if(!isFwrdEle&&iParticlePDG!=22&&isNCone&&pt>LeadingPartPT) { theLeadingPartInCone = thePart; LeadingPartPT = pt; LeadingPartdR = dR;}; + // the best dR matched particle outside narrow eleptic cone m_partExtrConePhi X m_partExtrConeEta + if(!isFwrdEle&&!isNCone&&dR<BestPartdR) { theBestPartOutCone = thePart; BestPartdR = dR; }; + // for forward electrons + if(isFwrdEle&&dR<BestPartdR) { theBestPartdR = thePart; BestPartdR = dR; }; + + } // end cycle for Gen particle + + // std::cout<<thePhoton<<" "<<theLeadingPartInCone<<" "<<theBestPartOutCone<<std::endl; + + if(thePhoton!=0) { + theMatchPart = barcode_to_particle(m_xTruthParticleContainer,thePhoton->barcode()%1000000); m_deltaRMatch=LeadingPhtdR; + } else if(theLeadingPartInCone!=0) { + theMatchPart = barcode_to_particle(m_xTruthParticleContainer,theLeadingPartInCone->barcode()%1000000); m_deltaRMatch=LeadingPartdR; + } else if(theBestPartOutCone!=0) { + theMatchPart = barcode_to_particle(m_xTruthParticleContainer,theBestPartOutCone->barcode()%1000000); m_deltaRMatch=BestPartdR; + } else if(isFwrdEle&&theBestPartdR!=0) { + theMatchPart = barcode_to_particle(m_xTruthParticleContainer,theBestPartdR->barcode()%1000000); m_deltaRMatch=BestPartdR; + } else theMatchPart = 0; + + + if(isFwrdEle||theMatchPart!=0||!m_inclG4part) return theMatchPart; + + // additional loop over G4 particles for unmatched egamma photons + // requested by Photon's group people + + for(const auto thePart : *m_xTruthParticleContainer){ + // loop over the stable particle + if(thePart->status()!=1) continue; + // only G4 particle including None Primary with barcode > 10^6 + if(thePart->barcode()<=200000) continue; + long iParticlePDG = thePart->pdgId(); + // exclude neutrino + if(abs(iParticlePDG)==12||abs(iParticlePDG)==14||abs(iParticlePDG)==16) continue; + // exclude particles interacting into the detector volume + if(thePart->decayVtx()!=0) continue; + + + if( pow((detPhi(clus->phiBE(2),thePart->phi())/m_partExtrConePhi),2)+ + pow((detEta(clus->etaBE(2),thePart->eta())/m_partExtrConeEta),2)>1.0 ) continue; + + + double pt = thePart->pt()/GeV; + double q = partCharge(thePart); + // exclude charged particles with pT<1 GeV + if(q!=0&&pt<m_pTChargePartCut ) continue; + if(q==0&&pt<m_pTNeutralPartCut) continue; + + double dR(-999.); + bool isNCone=false; + bool isExt = genPartToCalo(clus, thePart, false , dR, isNCone); + if(!isExt) continue; + + m_egPartPtr.push_back(thePart); + m_egPartdR.push_back(dR); + + theMatchPart = barcode_to_particle(m_xTruthParticleContainer,thePart->barcode()%1000000); + m_egPartClas.push_back(particleTruthClassifier(theMatchPart)); + + + // the leading photon inside narrow eleptical cone m_phtClasConePhi X m_phtClasConeEta + if(iParticlePDG==22&&isNCone&&pt>LeadingPhtPT) { thePhoton = thePart; LeadingPhtPT=pt; LeadingPhtdR=dR;} + // leading particle (excluding photon) inside narrow eleptic cone m_phtClasConePhi X m_phtClasConeEta + if(iParticlePDG!=22&&isNCone&&pt>LeadingPartPT) { theLeadingPartInCone = thePart; LeadingPartPT = pt; LeadingPartdR = dR;}; + // the best dR matched particle outside narrow eleptic cone cone m_phtClasConePhi X m_phtClasConeEta + if(!isNCone&&dR<BestPartdR) { theBestPartOutCone = thePart; BestPartdR = dR; }; + + } // end cycle for G4 particle + + if( thePhoton!=0){ + theMatchPart = barcode_to_particle(m_xTruthParticleContainer,thePhoton->barcode()%1000000); m_deltaRMatch=LeadingPhtdR; + } else if( theLeadingPartInCone!=0) { + theMatchPart = barcode_to_particle(m_xTruthParticleContainer,theLeadingPartInCone->barcode()%1000000); m_deltaRMatch=LeadingPartdR; + } else if( theBestPartOutCone!=0) { + theMatchPart = barcode_to_particle(m_xTruthParticleContainer,theBestPartOutCone->barcode()%1000000); m_deltaRMatch=BestPartdR; + } else theMatchPart = 0; + + + ATH_MSG_DEBUG( "succeeded egammaClusMatch "); + return theMatchPart; +} +//-------------------------------------------------------------- +bool MCTruthClassifier::genPartToCalo(const xAOD::CaloCluster* clus, + const xAOD::TruthParticle* thePart, + bool isFwrdEle, + double& dRmatch, + bool & isNarrowCone) { + //-------------------------------------------------------------- + dRmatch = -999.; + isNarrowCone = false; + + if (!m_extrapolateToCalo){ + ATH_MSG_WARNING( "No extrapolation tool available. Returning false." ); + return false; + } + + if ( thePart == 0 ) return false ; + const xAOD::TruthVertex* pvtx = thePart->prodVtx(); + if ( pvtx == 0 ) return false ; + + // define calo sample + CaloCell_ID::CaloSample sample= CaloCell_ID::EMB2; + + if ( (clus->inBarrel() && !clus->inEndcap()) || + (clus->inBarrel() && clus->inEndcap() && + clus->eSample(CaloSampling::EMB2) >= clus->eSample(CaloSampling::EME2) ) ) { + // Barrel + sample = CaloCell_ID::EMB2; + + } else if( ( !clus->inBarrel() && clus->inEndcap() && !isFwrdEle) || + ( clus->inBarrel() && clus->inEndcap() && + clus->eSample(CaloSampling::EME2) > clus->eSample(CaloSampling::EMB2) ) ) { + // End-cap + sample = CaloCell_ID::EME2; + } else if( isFwrdEle && clus->inEndcap()) { + // FCAL + sample=CaloCell_ID::FCAL2; + + } else return false ; + + + double etaCalo= 0; + double phiCalo= 0; + double offset = 0.; + + // define particle perigee: + Amg::Vector3D pos( pvtx->x() , pvtx->y() , pvtx->z() ) ; + Amg::Vector3D mom( thePart->px() , thePart->py() , thePart->pz() ) ; + + if(!isFwrdEle){ + //if Photon use intersection + + Trk::SurfaceIntersection result = m_extrapolateToCalo->getIntersectionInCalo(pos,mom, sample); + if ( !result.valid ) return false ; + etaCalo = result.intersection.eta(); + phiCalo = result.intersection.phi() ; + + } else{ + //For Frwd use the extrapolation + Trk::Perigee perigee(pos,mom, partCharge(thePart),pos); + const Trk::TrackParameters* result = m_extrapolateToCalo->extrapolate(perigee, sample, offset, Trk::nonInteracting, Trk::alongMomentum); + if ( result == 0 ) return false ; + etaCalo = result->position().eta() ; + phiCalo = result->position().phi() ; + // added by request of Thomas Koffas to stop memory leak ?! + delete result; + } + + double phiClus = clus->phiBE(2); + double etaClus = clus->etaBE(2); + + //--FixMe + if(isFwrdEle||(etaClus==0.&&phiClus==0.)) { + phiClus = clus->phi(); + etaClus = clus->eta(); + } + + + double dPhi = detPhi(phiCalo,phiClus); + double dEta = detEta(etaCalo,etaClus); + dRmatch = rCone(dPhi,dEta); + + if((!isFwrdEle&&dRmatch>m_phtdRtoTrCut)|| + (isFwrdEle&&dRmatch>m_fwrdEledRtoTrCut)) return false ; + + if(!isFwrdEle&&pow(dPhi/m_phtClasConePhi,2)+pow(dEta/m_phtClasConeEta,2)<=1.0) isNarrowCone=true; + + return true; +} + +//--------------------------------------------------------------------------------- +float MCTruthClassifier::detPhi(float x, float y) +//--------------------------------------------------------------------------------- +{ + float det; + det=x-y; + if(det > M_PI) det=det-2.*M_PI; + if(det < - M_PI) det=det+2.*M_PI; + return fabs(det); +} +//--------------------------------------------------------------------------------- +ParticleOrigin MCTruthClassifier::convHadronTypeToOrig(ParticleType pType){ + //--------------------------------------------------------------------------------- + if(pType==BBbarMesonPart&& + abs(m_MotherPDG==443)) return JPsi; + else if(pType==BBbarMesonPart) return BBbarMeson; + else if(pType==BottomMesonPart) return BottomMeson; + else if(pType==BottomBaryonPart) return BottomBaryon; + else if(pType==CCbarMesonPart) return CCbarMeson; + else if(pType==CharmedMesonPart) return CharmedMeson; + else if(pType==CharmedBaryonPart) return CharmedBaryon; + else if(pType==StrangeBaryonPart) return StrangeBaryon; + else if(pType==StrangeMesonPart) return StrangeMeson; + else if(pType==LightBaryonPart) return LightBaryon; + else if(pType==LightMesonPart) return LightMeson; + else return NonDefined; +} +//--------------------------------------------------------------------------------- +ParticleOrigin MCTruthClassifier::defHadronType(long pdg){ + //--------------------------------------------------------------------------------- + + if ( abs(pdg) == 443 ) return JPsi; + + int q1=(abs(pdg)/1000)%10; + int q2=(abs(pdg)/100)%10; + int q3=(abs(pdg)/10)%10; + + // di quark + // if( q3 == 0 && q2 >=q3 ) cout<<"di quark"<<endl; + + if( q1 == 0 && q2 == 5 && q3 == 5 ) return BBbarMeson; + else if( q1 == 0 && q3<5 && q3>0 && q2 == 5 ) return BottomMeson; + else if( q1 == 0 && q3 == 4 && q2 == 4 ) return CCbarMeson; + else if(q1==0&&q3<4&&q3>0&&q2==4) return CharmedMeson; + else if( q1 == 5 ) return BottomBaryon; + else if( q1 == 4 ) return CharmedBaryon; + else if( q1 == 3 ) return StrangeBaryon; + else if( q1 == 2 || q1 == 1 ) return LightBaryon; + else if((q1==0&&q2==3&&q3<3&&q3>0)||abs(pdg)==130) + return StrangeMeson; + else if( (q1==0&&(q3==1||q3==2) && (q2==1||q2==2)) || (q1==0&&q3==3&&q2==3)) + return LightMeson; + else return NonDefined; + +} + +//--------------------------------------------------------------------------------- +ParticleType MCTruthClassifier::defTypeOfHadron(long pdg){ + //--------------------------------------------------------------------------------- + + int q1=(abs(pdg)/1000)%10; + int q2=(abs(pdg)/100)%10; + int q3=(abs(pdg)/10)%10; + + // di quark + // if( q3 == 0 && q2 >=q3 ) cout<<"di quark"<<endl; + + if( q1 == 0 && q2 == 5 && q3 == 5 ) return BBbarMesonPart; + else if( q1 == 0 && q3<5 && q3>0 && q2 == 5 ) return BottomMesonPart; + else if( q1 == 0 && q3 == 4 && q2 == 4 ) return CCbarMesonPart; + else if(q1==0&&q3<4&&q3>0&&q2==4) return CharmedMesonPart; + else if( q1 == 5 ) return BottomBaryonPart; + else if( q1 == 4 ) return CharmedBaryonPart; + else if( q1 == 3 ) return StrangeBaryonPart; + else if( q1 == 2 || q1 == 1 ) return LightBaryonPart; + else if((q1==0&&q2==3&&q3<3&&q3>0)||abs(pdg)==130) + return StrangeMesonPart; + else if( (q1==0&&(q3==1||q3==2) && (q2==1||q2==2)) || (q1==0&&q3==3&&q2==3)) + return LightMesonPart; + else return Unknown; + +} + +//------------------------------------------------------------------------------- +bool MCTruthClassifier::isHardScatVrtx(const xAOD::TruthVertex* pVert){ + //------------------------------------------------------------------------------- + + if(pVert==0) return false; + + const xAOD::TruthVertex* pV = pVert; + int numOfPartIn(0),pdg(0),NumOfParton(0); + + do { + pVert = pV; + numOfPartIn = pVert->nIncomingParticles(); + pdg = pVert->incomingParticle(0)->pdgId(); + pV = pVert->incomingParticle(0)->prodVtx(); + } while (numOfPartIn==1&&(abs(pdg)<81||abs(pdg)>100)&&pV!=0); + + if(numOfPartIn==2) { + for(unsigned int ipIn=0;ipIn<pVert->nIncomingParticles();ipIn++){ + if(abs(pVert->incomingParticle(ipIn)->pdgId())<7|| + pVert->incomingParticle(ipIn)->pdgId()==21) NumOfParton++; + } + if(NumOfParton==2) return true; + } + + return false; +} + +//--------------------------------------------------------------------------------- +bool MCTruthClassifier::isHadron(const xAOD::TruthParticle* thePart){ + //--------------------------------------------------------------------------------- + + + bool isPartHadron = false; + if(thePart!=0) { + long pdg=thePart->pdgId(); + ParticleType pType = defTypeOfHadron(pdg); + // ParticleOrigin partOrig=convHadronTypeToOrig(pType); + //if(partOrig!=NonDefined) isPartHadron = true; + if(pType!=Unknown) isPartHadron = true; + //--exclude protons from beam + if(pdg==2212&&thePart->status()==3) isPartHadron=false; + } + return isPartHadron; +} + +//--------------------------------------------------------------------------------- +const xAOD::TruthParticle* MCTruthClassifier::getMother(const xAOD::TruthParticle* thePart){ + //--------------------------------------------------------------------------------- + ATH_MSG_DEBUG( "executing getMother" ); + + const xAOD::TruthVertex* partOriVert = thePart->prodVtx(); + + long partPDG = thePart->pdgId(); + int partBarcode = thePart->barcode()%1000000; + long MotherPDG(0); + + const xAOD::TruthVertex* MothOriVert(0); + const xAOD::TruthParticle* theMoth(0); + + if(!partOriVert) return theMoth; + + int itr=0; + do { + if(itr!=0) partOriVert = MothOriVert; + for(unsigned int ipIn=0;ipIn<partOriVert->nIncomingParticles();ipIn++){ + theMoth=partOriVert->incomingParticle(ipIn); + MotherPDG = theMoth->pdgId(); + MothOriVert = theMoth->prodVtx(); + if(MotherPDG==partPDG) break; + } + itr++; + if(itr>100) { ATH_MSG_WARNING( "getMother:: infinite while" ); break;} + } while (MothOriVert!=0&&MotherPDG==partPDG&&partBarcode<200000); + + + ATH_MSG_DEBUG( "succeded getMother" ); + return theMoth; +} + +//--------------------------------------------------------------------------------- +const xAOD::TruthVertex* MCTruthClassifier::findEndVert(const xAOD::TruthParticle* thePart){ + //--------------------------------------------------------------------------------- + const xAOD::TruthVertex* EndVert = thePart->decayVtx(); + const xAOD::TruthVertex* pVert(0); + if(EndVert!=0){ + do { + bool samePart=false; + pVert=0; + for(unsigned int ipOut=0;ipOut<EndVert->nOutgoingParticles();ipOut++){ + const xAOD::TruthParticle * itrDaug=EndVert->outgoingParticle(ipOut); + if(( (itrDaug->barcode()%1000000==thePart->barcode()%1000000)|| + // brem on generator level for tau + (EndVert->nOutgoingParticles()==1&&EndVert->nIncomingParticles()==1&& + itrDaug->barcode()<200000&&thePart->barcode()<200000) + ) && + itrDaug->pdgId() == thePart->pdgId()) {samePart=true; pVert=itrDaug ->decayVtx();} + } // cycle itrDaug + if(samePart) EndVert=pVert; + } while (pVert!=0); + + } // EndVert + + return EndVert; +} +//--------------------------------------------------------------------------------- +ParticleOutCome MCTruthClassifier::defOutComeOfElectron(const xAOD::TruthParticle* thePart){ + //--------------------------------------------------------------------------------- + + ParticleOutCome PartOutCome=UnknownOutCome; + + const xAOD::TruthVertex* EndVert = findEndVert(thePart); + + if(EndVert==0) return NonInteract; + + int NumOfElecDaug(0),ElecOutNumOfNucFr(0),ElecOutNumOfElec(0),NumOfHadr(0); + long EndDaugType(0); + NumOfElecDaug=EndVert->nOutgoingParticles(); + for(unsigned int ipOut=0;ipOut<EndVert->nOutgoingParticles();ipOut++){ + EndDaugType = EndVert->outgoingParticle(ipOut)->pdgId(); + if(abs(EndDaugType)==11) ElecOutNumOfElec++; + if(isHadron(EndVert->outgoingParticle(ipOut))) NumOfHadr++; + if(EndDaugType > 1000000000||EndDaugType==0||abs(EndDaugType) == 2212||abs(EndDaugType) == 2112) ElecOutNumOfNucFr++; + } // cycle itrDaug + + if(ElecOutNumOfNucFr!=0||NumOfHadr!=0) PartOutCome = NuclInteraction; + if(ElecOutNumOfElec==1&&NumOfElecDaug==1) PartOutCome = ElectrMagInter; + + return PartOutCome; +} +//--------------------------------------------------------------------------------- +ParticleOutCome MCTruthClassifier::defOutComeOfMuon(const xAOD::TruthParticle* thePart){ + //--------------------------------------------------------------------------------- + + ParticleOutCome PartOutCome=UnknownOutCome; + + const xAOD::TruthVertex* EndVert = findEndVert(thePart); + + if(EndVert==0) return NonInteract; + int NumOfMuDaug(0),MuOutNumOfNucFr(0),NumOfHadr(0); + int NumOfEleNeutr(0),NumOfMuonNeutr(0),NumOfElec(0); + long EndDaugType(0); + + NumOfMuDaug=EndVert->nOutgoingParticles(); + for(unsigned int ipOut=0;ipOut<EndVert->nOutgoingParticles();ipOut++){ + EndDaugType = EndVert->outgoingParticle(ipOut)->pdgId(); + if(abs(EndDaugType)==11) NumOfElec++; + if(abs(EndDaugType)==12) NumOfEleNeutr++; + if(abs(EndDaugType)==14) NumOfMuonNeutr++; + if(isHadron(EndVert->outgoingParticle(ipOut))) NumOfHadr++; + if(EndDaugType > 1000000000||EndDaugType==0||abs(EndDaugType) == 2212||abs(EndDaugType) == 2112) MuOutNumOfNucFr++; + } // cycle itrDaug + + if(MuOutNumOfNucFr!=0||NumOfHadr!=0) PartOutCome = NuclInteraction; + if(NumOfMuDaug==3&&NumOfElec==1&&NumOfEleNeutr==1&&NumOfMuonNeutr==1) PartOutCome = DecaytoElectron; + + return PartOutCome; +} +//--------------------------------------------------------------------------------- +ParticleOutCome MCTruthClassifier::defOutComeOfTau(const xAOD::TruthParticle* thePart){ + //--------------------------------------------------------------------------------- + + ATH_MSG_DEBUG( "Executing defOutComeOfTau" ); + + ParticleOutCome PartOutCome=UnknownOutCome; + + const xAOD::TruthVertex* EndVert = findEndVert(thePart); + + if(EndVert==0) return NonInteract; + int NumOfTauDaug(0),NumOfNucFr(0); + int NumOfElec(0),NumOfElecNeut(0),NumOfTauNeut(0); + int NumOfMuon(0),NumOfMuonNeut(0),NumOfPhot(0),NumOfPi(0),NumOfKaon(0); + + NumOfTauDaug=EndVert->nOutgoingParticles(); + + m_tauFinalStatePart = findFinalStatePart(EndVert); + + for(int i=0;i<(int) m_tauFinalStatePart.size();i++){ + long pdg=m_tauFinalStatePart[i]->pdgId(); + if(abs(pdg)==11) NumOfElec++; + else if(abs(pdg)==13) NumOfMuon++; + else if(abs(pdg)==12) NumOfElecNeut++; + else if(abs(pdg)==14) NumOfMuonNeut++; + else if(abs(pdg)==16) NumOfTauNeut++; + else if(pdg==22) NumOfPhot++; + else if(abs(pdg)==211) NumOfPi++; + else if(abs(pdg)==321) NumOfKaon++; + else if(pdg > 1000000000||pdg==0) NumOfNucFr++; + } + + + if(NumOfNucFr!=0) PartOutCome = NuclInteraction; + if((NumOfTauDaug==3&&NumOfElec==1&&NumOfElecNeut==1)|| + (NumOfTauDaug==(3+NumOfPhot)&&NumOfElecNeut==1)) PartOutCome = DecaytoElectron; + if((NumOfTauDaug== 3&&NumOfMuon==1&&NumOfMuonNeut==1)|| + (NumOfTauDaug==(3+NumOfPhot)&&NumOfMuonNeut==1)) PartOutCome = DecaytoMuon; + + if(NumOfPi==1||NumOfKaon==1) PartOutCome = OneProng; + if(NumOfPi+NumOfKaon==3) PartOutCome = ThreeProng; + if(NumOfPi+NumOfKaon==5) PartOutCome = FiveProng; + + + ATH_MSG_DEBUG( "defOutComeOfTau succeeded" ); + + return PartOutCome; + +} +//--------------------------------------------------------------------------------- +std::vector<const xAOD::TruthParticle*> +MCTruthClassifier::findFinalStatePart(const xAOD::TruthVertex* EndVert){ + //--------------------------------------------------------------------------------- + + + //long EndDaugType(0); + std::vector<const xAOD::TruthParticle*> finalStatePart; + + if(EndVert==0) return finalStatePart ; + + for(unsigned int ipOut=0;ipOut<EndVert->nOutgoingParticles();ipOut++){ + + const xAOD::TruthParticle* thePart=EndVert->outgoingParticle(ipOut); + + finalStatePart.push_back(thePart); + if(thePart->status()!=1) { + + const xAOD::TruthVertex* pVert = findEndVert(thePart); + std::vector<const xAOD::TruthParticle*> vecPart; + if(pVert!=0) { + vecPart = findFinalStatePart(pVert); + if(vecPart.size()!=0) for(int i=0;i<(int)vecPart.size();i++) finalStatePart.push_back(vecPart[i]); + } + } + + } // cycle itrDaug + + return finalStatePart; +} +//--------------------------------------------------------------------------------- +ParticleOutCome MCTruthClassifier::defOutComeOfPhoton(const xAOD::TruthParticle* thePart){ + //--------------------------------------------------------------------------------- + + ParticleOutCome PartOutCome=UnknownOutCome; + const xAOD::TruthVertex* EndVert = findEndVert(thePart); + if(EndVert==0) return UnConverted; + + int PhtOutNumOfNucFr(0),PhtOutNumOfEl(0),PhtOutNumOfPos(0); + int NumOfPhtDaug(0),PhtOutNumOfHadr(0); + // int PhtOutNumOfPi(0); + long EndDaugType(0); + + NumOfPhtDaug=EndVert->nOutgoingParticles(); + for(unsigned int ipOut=0;ipOut<EndVert->nOutgoingParticles();ipOut++){ + EndDaugType = EndVert->outgoingParticle(ipOut)->pdgId(); + if(EndDaugType > 1000000000||EndDaugType==0||abs(EndDaugType) == 2212||abs(EndDaugType) == 2112) PhtOutNumOfNucFr++; + if(EndDaugType == 11) PhtOutNumOfEl++; + if(EndDaugType ==-11) PhtOutNumOfPos++; + // if(abs(EndDaugType)==211||EndDaugType==111) PhtOutNumOfPi++; + if(isHadron( EndVert->outgoingParticle(ipOut))) PhtOutNumOfHadr++; + } // cycle itrDaug + + if(PhtOutNumOfEl==1&&PhtOutNumOfPos==1&&NumOfPhtDaug==2) PartOutCome = Converted; + if((NumOfPhtDaug>1&&PhtOutNumOfNucFr!=0)||PhtOutNumOfHadr>0 ) PartOutCome = NuclInteraction; + + return PartOutCome; + +} +//--------------------------------------------------------------------------------- +std::pair<ParticleType,ParticleOrigin> +MCTruthClassifier::checkOrigOfBkgElec(const xAOD::TruthParticle* theEle){ + //--------------------------------------------------------------------------------- + + ATH_MSG_DEBUG( "executing CheckOrigOfBkgElec " << theEle ); + + m_BkgElecMother = 0; + + std::pair<ParticleType,ParticleOrigin> part; + part.first = Unknown; + part.second = NonDefined; + + if(theEle==0) return part; + + const xAOD::TruthParticleContainer * m_xTruthParticleContainer; + StatusCode sc = evtStore()->retrieve(m_xTruthParticleContainer, m_xaodTruthParticleContainerName); + if (sc.isFailure()||!m_xTruthParticleContainer){ + ATH_MSG_WARNING( "No xAODTruthParticleContainer "<<m_xaodTruthParticleContainerName<<" found" ); + return part; + } + ATH_MSG_DEBUG( "xAODTruthParticleContainer " << m_xaodTruthParticleContainerName<<" successfully retrieved " ); + + + part=particleTruthClassifier(theEle); + + if(part.first!=BkgElectron||part.second!=PhotonConv) return part; + + const xAOD::TruthParticle* thePart(0); + + + + if(abs(m_PhotonMotherPDG)==11||abs(m_PhotonMotherPDG)==13|| abs(m_PhotonMotherPDG)==15||isHadron(m_PhotonMother)){ + do { + thePart = barcode_to_particle(m_xTruthParticleContainer,m_PhotonMotherBarcode%1000000); + if(thePart==0) break; + part.first=Unknown; part.second=NonDefined; + part=particleTruthClassifier(thePart); + } while (part.first == BkgElectron&& part.second==PhotonConv&& + (abs(m_PhotonMotherPDG)==11||abs(m_PhotonMotherPDG)==13|| + abs(m_PhotonMotherPDG)==15||isHadron(m_PhotonMother))); + + + if(part.first == BkgElectron&& part.second==PhotonConv) { + // in case of photon from gen particle classify photon + //part=particleTruthClassifier(m_Mother); + thePart = barcode_to_particle(m_xTruthParticleContainer,m_MotherBarcode%1000000); + if(thePart!=0) part=particleTruthClassifier(thePart); + + } else if(part.first == GenParticle&&isHadron(thePart)){ + // to fix Alpgen hadrons with status code !=1 (>100) + part.first=Hadron; part.second=NonDefined; + } + + } else { + // in case of photon from gen particle classify photon + thePart = barcode_to_particle(m_xTruthParticleContainer,m_MotherBarcode%1000000); + if(thePart!=0) part=particleTruthClassifier(thePart); + } + + m_BkgElecMother = thePart; + return part; + +} +//------------------------------------------------------------------------ +double MCTruthClassifier::partCharge(const xAOD::TruthParticle* thePart){ + //------------------------------------------------------------------------ + if ( thePart == 0 ) return 0. ; + + const HepPDT::ParticleData * pData=m_particleTable->particle(HepPDT::ParticleID(abs(thePart->pdgId()))); + double pCharge=0.; + if(pData) pCharge=pData->charge(); + if(pCharge!=0&&thePart->pdgId()/abs(thePart->pdgId())<0) pCharge=-pCharge; + return pCharge; + +} + +//------------------------------------------------------------------------ +const xAOD::TruthParticle* MCTruthClassifier:: +barcode_to_particle(const xAOD::TruthParticleContainer* m_TruthTES, + int bc){ + //------------------------------------------------------------------------ + // temporary solution? + const xAOD::TruthParticle* ptrPart=NULL; + + for(const auto truthParticle : *m_TruthTES){ + if(truthParticle->barcode()==bc) {ptrPart=truthParticle; break;} + } + + return ptrPart; +} diff --git a/PhysicsAnalysis/MCTruthClassifier/src/components/MCTruthClassifier_entries.cxx b/PhysicsAnalysis/MCTruthClassifier/src/components/MCTruthClassifier_entries.cxx new file mode 100755 index 0000000000000000000000000000000000000000..920dac54190e3d682085d0fd59fa948f0a823358 --- /dev/null +++ b/PhysicsAnalysis/MCTruthClassifier/src/components/MCTruthClassifier_entries.cxx @@ -0,0 +1,8 @@ +#include "MCTruthClassifier/MCTruthClassifier.h" +#include "GaudiKernel/DeclareFactoryEntries.h" + +DECLARE_TOOL_FACTORY ( MCTruthClassifier ) +DECLARE_FACTORY_ENTRIES(MCTruthClassifier) { + DECLARE_TOOL ( MCTruthClassifier ) +} + diff --git a/PhysicsAnalysis/MCTruthClassifier/src/components/MCTruthClassifier_load.cxx b/PhysicsAnalysis/MCTruthClassifier/src/components/MCTruthClassifier_load.cxx new file mode 100755 index 0000000000000000000000000000000000000000..7dddcfbf0badd114ce2b38cab8d9333713ec73ca --- /dev/null +++ b/PhysicsAnalysis/MCTruthClassifier/src/components/MCTruthClassifier_load.cxx @@ -0,0 +1,3 @@ +#include "GaudiKernel/LoadFactoryEntries.h" + +LOAD_FACTORY_ENTRIES(MCTruthClassifier)