42 return StatusCode::FAILURE;
66 return StatusCode::SUCCESS;
75 return StatusCode::SUCCESS;
85 static const bool is_sherpa = [
this]() {
86 bool is_sherpa =
false;
94 if (
m_metaStore->retrieve(truthMetaData).isSuccess() && !truthMetaData->
empty()){
96 const std::string gens = truthMetaData->
at(0)->generators();
97 is_sherpa = (gens.find(
"sherpa")==std::string::npos &&
98 gens.find(
"Sherpa")==std::string::npos &&
99 gens.find(
"SHERPA")==std::string::npos) ? false :
true;
102 ATH_MSG_WARNING(
"Found xAODTruthMetaDataContainer empty! Configuring to be NOT Sherpa.");
104 ATH_MSG_INFO(
"From metadata configured: Sherpa? " << is_sherpa);
106 ATH_MSG_WARNING(
"Could not find metadata container in storegate; assuming NOT Sherpa");
113 if (!truthParticles.
isValid()) {
115 return StatusCode::FAILURE;
120 ATH_CHECK(newParticlesWriteHandle.
record(std::make_unique<xAOD::TruthParticleContainer>(),
121 std::make_unique<xAOD::TruthParticleAuxContainer>()));
125 unsigned int nParticles = truthParticles->size();
146 std::vector<int>
entries = m_parser->evaluateAsVector();
147 unsigned int nEntries =
entries.size();
149 if (nParticles != nEntries ) {
150 ATH_MSG_ERROR(
"Sizes incompatible! Are you sure your selection string used TruthParticles?");
151 return StatusCode::FAILURE;
160 bool SherpaW =
false;
161 bool SherpaZ =
false;
168 if ((SherpaW or SherpaZ) && is_sherpa){
175 if ((SherpaW || SherpaZ) && is_sherpa){
177 std::vector<const xAOD::TruthParticle*> status_nonPhysical;
178 for (
unsigned int i=0; i<nParticles; ++i) {
180 if (!truthParticles->at(i))
continue;
184 if (!
MC::isPhysical(truthParticles->at(i))) status_nonPhysical.push_back( truthParticles->at(i) );
187 if ((status_nonPhysical.size()==2 || status_nonPhysical.size()==4 || status_nonPhysical.size()==6) && (SherpaZ || SherpaW)){
189 int gens[3] = {0,0,0};
190 for (
size_t i=0;i<status_nonPhysical.size();++i){
191 if (status_nonPhysical[i]->absPdgId()<13) gens[0]++;
192 else if (status_nonPhysical[i]->absPdgId()<15) gens[1]++;
196 if (gens[0]>2 || gens[0]==1 || gens[1]>2 || gens[1]==1 || gens[2]>2 || gens[2]==1){
198 ATH_MSG_VERBOSE(
"Too many leptons of one generation. Cannot make bosons. Give up");
199 return StatusCode::SUCCESS;
201 std::vector<const xAOD::TruthParticle*> boson;
202 for (
size_t i=0;i<status_nonPhysical.size();++i){
203 if (status_nonPhysical[i]->absPdgId()<13) boson.push_back(status_nonPhysical[i]);
204 else if (gens[0]==0 && status_nonPhysical[i]->absPdgId()<15) boson.push_back(status_nonPhysical[i]);
205 else if (gens[0]==0 && gens[1]==0) boson.push_back(status_nonPhysical[i]);
206 if (boson.size()==2){
210 if (boson[0]->pdgId()==-boson[1]->pdgId()) pdg_id=23;
211 else if (std::abs(boson[0]->pdgId()+boson[1]->pdgId())!=1){
213 ATH_MSG_WARNING(
"Do not know how to interpret as a boson: " << boson[0]->pdgId() <<
" " << boson[1]->pdgId());
216 pdg_id=24*(boson[0]->pdgId()+boson[1]->pdgId());
218 if ( (SherpaW &&
MC::isW(pdg_id)) ||
219 (SherpaZ &&
MC::isZ(pdg_id)) ){
222 newParticlesWriteHandle->push_back( xTruthParticle );
224 if (boson[0]->hasProdVtx()) {
225 if ((boson[0]->prodVtx()->nIncomingParticles() > 0) && (boson[0]->prodVtx()->incomingParticle(0)!=
nullptr)) {
226 motherIDDecorator(*xTruthParticle) = boson[0]->prodVtx()->incomingParticle(0)->pdgId();
227 }
else {motherIDDecorator(*xTruthParticle) = 0;}
228 }
else {motherIDDecorator(*xTruthParticle) = 0;}
229 if (boson[0]->hasDecayVtx()) {
230 if ((boson[0]->decayVtx()->nOutgoingParticles() > 0) && (boson[0]->decayVtx()->outgoingParticle(0)!=
nullptr)) {
231 daughterIDDecorator(*xTruthParticle) = boson[0]->decayVtx()->outgoingParticle(0)->pdgId();
232 }
else {daughterIDDecorator(*xTruthParticle) = 0;}
233 }
else {daughterIDDecorator(*xTruthParticle) = 0;}
242 xTruthParticle->
setM(new_mom.M());
243 xTruthParticle->
setPx(new_mom.Px());
244 xTruthParticle->
setPy(new_mom.Py());
245 xTruthParticle->
setPz(new_mom.Pz());
246 xTruthParticle->
setE(new_mom.E());
251 if (gens[0]==0 && gens[1]==0) gens[2]=0;
252 else if (gens[0]==0) gens[1]=0;
257 if (status_nonPhysical.size()==1 || status_nonPhysical.size()==3 || status_nonPhysical.size()==5 || status_nonPhysical.size()>6){
258 ATH_MSG_WARNING(status_nonPhysical.size() <<
" leptons found in the Sherpa event record. Not sure how to deal with this.");
260 return StatusCode::SUCCESS;
262 for (
unsigned int i=0; i<nParticles; ++i) {
269 bool same_as_mother =
false;
270 bool same_as_daughter =
false;
274 same_as_mother =
true;
281 same_as_daughter =
true;
285 if (same_as_mother && same_as_daughter){
291 newParticlesWriteHandle->push_back( xTruthParticle );
296 }
else {motherIDDecorator(*xTruthParticle) = 0;}
297 }
else {motherIDDecorator(*xTruthParticle) = 0;}
301 }
else {daughterIDDecorator(*xTruthParticle) = 0;}
302 }
else {daughterIDDecorator(*xTruthParticle) = 0;}
305 *xTruthParticle=*theParticle;
307 typeDecorator(*xTruthParticle) =
308 typeReadDecor(*theParticle);
310 originDecorator(*xTruthParticle) =
311 originReadDecor(*theParticle);
313 outcomeDecorator(*xTruthParticle) =
314 outcomeReadDecor(*theParticle);
316 classificationDecorator(*xTruthParticle) =
317 classificationReadDecor(*theParticle);
321 hadronOriginDecorator(*xTruthParticle) =
322 TopHadronOriginFlagAcc.
withDefault (*theParticle, 0);
333 return StatusCode::SUCCESS;
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
Helper class to provide constant type-safe access to aux data.
ATLAS-specific HepMC functions.
Handle class for adding a decoration to an object.
const T * at(size_type n) const
Access an element, as an rvalue.
bool empty() const noexcept
Returns true if the collection is empty.
ServiceHandle< StoreGateSvc > m_metaStore
Handle on the metadata store for init.
SG::ReadHandleKey< xAOD::TruthParticleContainer > m_particlesKey
virtual StatusCode finalize() override final
Gaudi::Property< bool > m_do_compress
SG::ReadDecorHandleKey< xAOD::TruthParticleContainer > m_originReadDecorKey
virtual StatusCode initialize() override final
std::atomic< unsigned int > m_ntotpart
SG::WriteDecorHandleKey< xAOD::TruthParticleContainer > m_typeDecoratorKey
virtual StatusCode addBranches(const EventContext &ctx) const override final
std::atomic< unsigned int > m_npasspart
SG::ReadDecorHandleKey< xAOD::TruthParticleContainer > m_outcomeReadDecorKey
SG::WriteDecorHandleKey< xAOD::TruthParticleContainer > m_linkDecoratorKey
SG::ReadDecorHandleKey< xAOD::TruthParticleContainer > m_classificationReadDecorKey
Gaudi::Property< std::string > m_partString
SG::WriteDecorHandleKey< xAOD::TruthParticleContainer > m_hadronOriginDecoratorKey
SG::WriteDecorHandleKey< xAOD::TruthParticleContainer > m_originDecoratorKey
SG::WriteDecorHandleKey< xAOD::TruthParticleContainer > m_daughterIDDecoratorKey
SG::WriteDecorHandleKey< xAOD::TruthParticleContainer > m_outcomeDecoratorKey
SG::WriteHandleKey< xAOD::TruthParticleContainer > m_outputParticlesKey
SG::WriteDecorHandleKey< xAOD::TruthParticleContainer > m_classificationDecoratorKey
SG::ReadDecorHandleKey< xAOD::TruthParticleContainer > m_typeReadDecorKey
Gaudi::Property< bool > m_do_sherpa
Gaudi::Property< bool > m_keep_navigation_info
SG::WriteDecorHandleKey< xAOD::TruthParticleContainer > m_motherIDDecoratorKey
ElementLink implementation for ROOT usage.
Helper class to provide constant type-safe access to aux data.
const_reference_type withDefault(const ELT &e, const T &deflt) const
Fetch the variable for one element, as a const reference, with a default.
Handle class for reading a decoration on an object.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Handle class for adding a decoration to an object.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
TLorentzVector FourMom_t
Definition of the 4-momentum type.
void setPy(float value)
Set the y component of the particle's momentum.
void setUid(int value)
Set unique ID.
void setM(float value)
Also store the mass.
void setE(float value)
Set the energy of the particle.
int pdgId() const
PDG ID code.
const TruthVertex_v1 * decayVtx() const
The decay vertex of this particle.
void setPz(float value)
Set the z component of the particle's momentum.
bool hasProdVtx() const
Check for a production vertex on this particle.
bool hasDecayVtx() const
Check for a decay vertex on this particle.
const TruthVertex_v1 * prodVtx() const
The production vertex of this particle.
void setStatus(int value)
Set status code.
void setPdgId(int pid)
Set PDG ID code.
void setPx(float value)
Set the x component of the particle's momentum.
const TruthParticle_v1 * outgoingParticle(size_t index) const
Get one of the outgoing particles.
const TruthParticle_v1 * incomingParticle(size_t index) const
Get one of the incoming particles.
size_t nOutgoingParticles() const
Get the number of outgoing particles.
size_t nIncomingParticles() const
Get the number of incoming particles.
constexpr int INVALID_PARTICLE_ID
bool isSMLepton(const T &p)
APID: the fourth generation leptons are not standard model leptons.
bool isPhysical(const T &p)
Identify if the particle is physical, i.e. is stable or decayed.
TruthMetaDataContainer_v1 TruthMetaDataContainer
Declare the latest version of the truth vertex container.
TruthParticle_v1 TruthParticle
Typedef to implementation.