35 , m_metaStore(
"MetaDataStore",
n )
37 declareInterface<DerivationFramework::IAugmentationTool>(
this);
51 ATH_MSG_INFO(
"Using " << m_particlesKey.key() <<
" as the input truth container key");
54 ATH_CHECK(m_outputParticlesKey.initialize());
55 ATH_MSG_INFO(
"New truth particles container key: " << m_outputParticlesKey.key() );
57 if (m_partString.empty()) {
59 return StatusCode::FAILURE;
60 }
else {
ATH_MSG_INFO(
"Truth particle selection string: " << m_partString );}
63 if (!m_partString.empty()) {
64 ATH_CHECK( initializeParser(m_partString) );
68 ATH_CHECK(m_originReadDecorKey.initialize());
69 ATH_CHECK(m_typeReadDecorKey.initialize());
70 ATH_CHECK(m_outcomeReadDecorKey.initialize());
71 ATH_CHECK(m_classificationReadDecorKey.initialize());
74 ATH_CHECK(m_linkDecoratorKey.initialize());
75 ATH_CHECK(m_originDecoratorKey.initialize());
76 ATH_CHECK(m_typeDecoratorKey.initialize());
77 ATH_CHECK(m_outcomeDecoratorKey.initialize());
78 ATH_CHECK(m_classificationDecoratorKey.initialize());
79 ATH_CHECK(m_motherIDDecoratorKey.initialize());
80 ATH_CHECK(m_daughterIDDecoratorKey.initialize());
81 ATH_CHECK(m_hadronOriginDecoratorKey.initialize());
83 return StatusCode::SUCCESS;
90 ATH_MSG_INFO(
"Processed "<< m_ntotpart <<
" truth particles, "<< m_npasspart <<
" were retained ");
92 return StatusCode::SUCCESS;
99 const EventContext& ctx = Gaudi::Hive::currentContext();
103 static const bool is_sherpa = [
this]() {
104 bool is_sherpa =
false;
112 if (m_metaStore->retrieve(truthMetaData).isSuccess() && !truthMetaData->
empty()){
114 const std::string gens = truthMetaData->
at(0)->generators();
115 is_sherpa = (gens.find(
"sherpa")==std::string::npos &&
116 gens.find(
"Sherpa")==std::string::npos &&
117 gens.find(
"SHERPA")==std::string::npos) ?
false :
true;
120 ATH_MSG_WARNING(
"Found xAODTruthMetaDataContainer empty! Configuring to be NOT Sherpa.");
122 ATH_MSG_INFO(
"From metadata configured: Sherpa? " << is_sherpa);
124 ATH_MSG_WARNING(
"Could not find metadata container in storegate; assuming NOT Sherpa");
131 if (!truthParticles.
isValid()) {
132 ATH_MSG_ERROR(
"Couldn't retrieve TruthParticle collection with name " << m_particlesKey);
133 return StatusCode::FAILURE;
138 ATH_CHECK(newParticlesWriteHandle.
record(std::make_unique<xAOD::TruthParticleContainer>(),
139 std::make_unique<xAOD::TruthParticleAuxContainer>()));
140 ATH_MSG_DEBUG(
"Recorded new TruthParticleContainer with key: " << (m_outputParticlesKey.key()));
143 unsigned int nParticles = truthParticles->
size();
144 m_ntotpart += nParticles;
163 if (!m_partString.empty()) {
164 std::vector<int>
entries = m_parser->evaluateAsVector();
168 ATH_MSG_ERROR(
"Sizes incompatible! Are you sure your selection string used TruthParticles?");
169 return StatusCode::FAILURE;
178 bool SherpaW =
false;
179 bool SherpaZ =
false;
180 if (m_partString.value().find(
"24") != std::string::npos && m_do_sherpa && is_sherpa) {
183 if (m_partString.value().find(
"23") != std::string::npos && m_do_sherpa && is_sherpa) {
186 if ((SherpaW or SherpaZ) && is_sherpa){
193 if ((SherpaW || SherpaZ) && is_sherpa){
195 std::vector<const xAOD::TruthParticle*> status_nonPhysical;
196 for (
unsigned int i=0;
i<nParticles; ++
i) {
198 if (!truthParticles->
at(
i))
continue;
202 if (!
MC::isPhysical(truthParticles->
at(
i))) status_nonPhysical.push_back( truthParticles->
at(
i) );
205 if ((status_nonPhysical.size()==2 || status_nonPhysical.size()==4 || status_nonPhysical.size()==6) && (SherpaZ || SherpaW)){
207 int gens[3] = {0,0,0};
208 for (
size_t i=0;
i<status_nonPhysical.size();++
i){
209 if (status_nonPhysical[
i]->absPdgId()<13) gens[0]++;
210 else if (status_nonPhysical[
i]->absPdgId()<15) gens[1]++;
214 if (gens[0]>2 || gens[0]==1 || gens[1]>2 || gens[1]==1 || gens[2]>2 || gens[2]==1){
216 ATH_MSG_VERBOSE(
"Too many leptons of one generation. Cannot make bosons. Give up");
217 return StatusCode::SUCCESS;
219 std::vector<const xAOD::TruthParticle*> boson;
220 for (
size_t i=0;
i<status_nonPhysical.size();++
i){
221 if (status_nonPhysical[
i]->absPdgId()<13) boson.push_back(status_nonPhysical[
i]);
222 else if (gens[0]==0 && status_nonPhysical[
i]->absPdgId()<15) boson.push_back(status_nonPhysical[
i]);
223 else if (gens[0]==0 && gens[1]==0) boson.push_back(status_nonPhysical[
i]);
224 if (boson.size()==2){
228 if (boson[0]->pdgId()==-boson[1]->pdgId()) pdg_id=23;
229 else if (std::abs(boson[0]->pdgId()+boson[1]->pdgId())!=1){
231 ATH_MSG_WARNING(
"Do not know how to interpret as a boson: " << boson[0]->pdgId() <<
" " << boson[1]->pdgId());
234 pdg_id=24*(boson[0]->pdgId()+boson[1]->pdgId());
236 if ( (SherpaW && std::abs(pdg_id)==24) ||
237 (SherpaZ && pdg_id==23) ){
240 newParticlesWriteHandle->
push_back( xTruthParticle );
241 if (m_keep_navigation_info){
242 if (boson[0]->hasProdVtx()) {
243 if ((boson[0]->prodVtx()->nIncomingParticles() > 0) && (boson[0]->prodVtx()->incomingParticle(0)!=
nullptr)) {
244 motherIDDecorator(*xTruthParticle) = boson[0]->prodVtx()->incomingParticle(0)->pdgId();
245 }
else {motherIDDecorator(*xTruthParticle) = 0;}
246 }
else {motherIDDecorator(*xTruthParticle) = 0;}
247 if (boson[0]->hasDecayVtx()) {
248 if ((boson[0]->decayVtx()->nOutgoingParticles() > 0) && (boson[0]->decayVtx()->outgoingParticle(0)!=
nullptr)) {
249 daughterIDDecorator(*xTruthParticle) = boson[0]->decayVtx()->outgoingParticle(0)->pdgId();
250 }
else {daughterIDDecorator(*xTruthParticle) = 0;}
251 }
else {daughterIDDecorator(*xTruthParticle) = 0;}
260 xTruthParticle->
setM(new_mom.M());
261 xTruthParticle->
setPx(new_mom.Px());
262 xTruthParticle->
setPy(new_mom.Py());
263 xTruthParticle->
setPz(new_mom.Pz());
264 xTruthParticle->
setE(new_mom.E());
269 if (gens[0]==0 && gens[1]==0) gens[2]=0;
270 else if (gens[0]==0) gens[1]=0;
275 if (status_nonPhysical.size()==1 || status_nonPhysical.size()==3 || status_nonPhysical.size()==5 || status_nonPhysical.size()>6){
276 ATH_MSG_WARNING(status_nonPhysical.size() <<
" leptons found in the Sherpa event record. Not sure how to deal with this.");
278 return StatusCode::SUCCESS;
280 for (
unsigned int i=0;
i<nParticles; ++
i) {
287 bool same_as_mother =
false;
288 bool same_as_daughter =
false;
292 same_as_mother =
true;
299 same_as_daughter =
true;
303 if (same_as_mother && same_as_daughter){
309 newParticlesWriteHandle->
push_back( xTruthParticle );
310 if (m_keep_navigation_info){
314 }
else {motherIDDecorator(*xTruthParticle) = 0;}
315 }
else {motherIDDecorator(*xTruthParticle) = 0;}
319 }
else {daughterIDDecorator(*xTruthParticle) = 0;}
320 }
else {daughterIDDecorator(*xTruthParticle) = 0;}
323 *xTruthParticle=*theParticle;
325 typeDecorator(*xTruthParticle) =
328 originDecorator(*xTruthParticle) =
331 outcomeDecorator(*xTruthParticle) =
334 classificationDecorator(*xTruthParticle) =
335 classificationReadDecor.
withDefault(*theParticle, 0);
337 if (m_outputParticlesKey.key()==
"TruthHFHadrons"){
339 hadronOriginDecorator(*xTruthParticle) =
340 TopHadronOriginFlagAcc.
withDefault (*theParticle, 0);
343 if(m_keep_navigation_info) linkDecorator(*xTruthParticle) = eltp;
348 for (
unsigned int i=0;
i<nParticles; ++
i)
if (
entries[
i]) ++m_npasspart;
351 return StatusCode::SUCCESS;