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;
TLorentzVector FourMom_t
Definition of the 4-momentum type.
void setPy(float value)
Set the y component of the particle's momentum.
void setE(float value)
Set the energy of the particle.
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 setPx(float value)
Set the x component of the particle's momentum.