42 std::vector<const xAOD::TruthVertex*> truthVerticesToMatch,
73 std::vector<VertexTruthMatchInfo> matchinfo;
76 size_t ntracks = trackParticles.size();
77 const std::vector<float> & trkWeights = weightAcc( *vtx );
90 trkMuSATrkParts.reserve(ntracks);
91 for (
const auto& trkLink : trackParticles) {
92 if (!trkLink.isValid())
continue;
97 trkMuSATrkParts.push_back(trkMuSATrkLink);
102 ATH_MSG_WARNING(
"MuSATrk_MSTPLink decoration is not available on track particle");
109 ATH_MSG_WARNING(
"trackParticles or trackWeights not available, vertex is missing info");
112 if ( trkWeights.size() != ntracks ) {
113 ATH_MSG_WARNING(
"Vertex without same number of tracks and trackWeights, vertex is missing info");
117 ATH_MSG_DEBUG(
"Matching new vertex at (" << vtx->x() <<
", " << vtx->y() <<
", " << vtx->z() <<
")" <<
" with " << ntracks <<
" tracks, at index: " << vtx->index());
119 float totalWeight = 0.;
125 int combinedSMOrigin = 0;
128 for (
size_t t = 0; t < ntracks; ++t ) {
133 if (!trackParticles[t].
isValid()) {
139 if (t >= trkParts.size() || !trkParts[t].isValid()) {
140 ATH_MSG_DEBUG(
"Track " << t <<
" is invalid or out of bounds in trkParts!");
149 totalWeight += trkWeights[t];
157 }
catch (
const std::exception& e) {
164 ATH_MSG_DEBUG(
"The truth particle link decoration isn't available.");
175 prob = trk_truthProbAcc(trk);
183 const int ancestorVertexUniqueID =
checkProduction(truthPart, truthVerticesToMatch);
187 combinedSMOrigin |= smOrigin;
199 auto it = std::find_if(truthVerticesToMatch.begin(), truthVerticesToMatch.end(),
200 [&](
const auto& ele){ return HepMC::uniqueID(ele) == ancestorVertexUniqueID;} );
202 if (it == truthVerticesToMatch.end()) {
203 ATH_MSG_WARNING(
"Truth vertex with unique ID " << ancestorVertexUniqueID <<
" not found!");
208 size_t matchIdx = indexOfMatchInfo(matchinfo, elLink);
211 std::get<1>(matchinfo[matchIdx]) += 1.0;
213 std::get<1>(matchinfo[matchIdx]) += trkWeights[t];
215 std::get<2>(matchinfo[matchIdx]) += trk.
pt();
236 std::get<1>(link) /= totalWeight;
237 std::get<2>(link) /= totalPt;
240 float fakeScore = fakePt/totalPt;
241 float otherScore = otherPt/totalPt;
243 matchInfoDecor ( *vtx ) = matchinfo;
244 fakeScoreDecor ( *vtx ) = fakeScore;
245 otherScoreDecor( *vtx ) = otherScore;
249 smOriginDecor( *vtx ) = combinedSMOrigin;
257 std::vector<bool> assignedType( recoVerticesToMatch.size(),
false );
261 for (
size_t i = 0; i < recoVerticesToMatch.size(); ++i ) {
263 int recoVertexMatchType = 0;
265 if ( assignedType[i] ) {
270 std::vector<VertexTruthMatchInfo> & info = matchInfoDecor( *recoVerticesToMatch[i] );
271 float fakeScore = fakeScoreDecor( *recoVerticesToMatch[i] );
276 }
else if (info.size() == 1) {
278 ATH_MSG_DEBUG(
"One true decay vertices matched with sufficient weight. Vertex is matched.");
280 isMatched(**std::get<0>(info[0])) =
true;
283 ATH_MSG_DEBUG(
"One true decay vertices matched with insufficient weight. Vertex is other.");
286 }
else if (info.size() >= 2 ) {
287 ATH_MSG_DEBUG(
"Multiple true decay vertices matched. Vertex is merged.");
291 isMatched(**std::get<0>(link)) = true;
294 ATH_MSG_DEBUG(
"Vertex is neither fake nor LLP. Marking as OTHER.");
298 recoMatchTypeDecor(*recoVerticesToMatch[i]) = recoVertexMatchType;
303 std::vector<size_t> foundSplits;
304 for (
size_t j = i + 1; j < recoVerticesToMatch.size(); ++j ) {
305 std::vector<VertexTruthMatchInfo> & info2 = matchInfoDecor( *recoVerticesToMatch[j] );
310 if (!info2.empty() && std::get<0>(info2[0]).isValid() && std::get<0>(info[0]).key() == std::get<0>(info2[0]).key() && std::get<0>(info[0]).index() == std::get<0>(info2[0]).index() ) {
313 splitLink_ij.
setElement( recoVerticesToMatch[j] );
315 splitPartnerDecor( *recoVerticesToMatch[i] ).emplace_back(splitLink_ij);
318 splitLink_ji.
setElement( recoVerticesToMatch[i] );
320 splitPartnerDecor( *recoVerticesToMatch[j] ).emplace_back(splitLink_ji);
323 for (
auto k : foundSplits ) {
325 splitLink_kj.
setElement( recoVerticesToMatch[j] );
327 splitPartnerDecor( *recoVerticesToMatch[k] ).emplace_back(splitLink_kj);
330 splitLink_jk.
setElement( recoVerticesToMatch[k] );
332 splitPartnerDecor( *recoVerticesToMatch[j] ).emplace_back(splitLink_jk);
335 foundSplits.push_back(j);
338 isSplit(**std::get<0>(info[0])) =
true;
339 assignedType[j] =
true;
354 std::vector<const xAOD::TruthParticle*> reconstructibleParticles;
359 std::vector<int> particleInfo = {0,0,0};
360 std::vector<int> vertexInfo = {0,0,0};
362 for(
size_t n = 0; n < reconstructibleParticles.size(); n++){
369 for(
size_t h = 0;
h < particleInfo.size();
h++){
370 vertexInfo.at(
h) += particleInfo.at(
h);
375 int truthMatchType = 0;
376 if( vertexInfo.at(0) > 1 &&
377 ((
m_doMuSA && truthVtx->perp() < 8000 && std::abs(truthVtx->z()) < 10000) ||
378 (!
m_doMuSA && truthVtx->perp() < 320 && std::abs(truthVtx->z()) < 1500))){
379 ATH_MSG_DEBUG(
"Vertex is reconstructable and in " << (
m_doMuSA ?
"Muon Spectrometer" :
"Inner Det") <<
" region");
387 ATH_MSG_DEBUG(
"Vertex is has at least two tracks passing track selection: " << vertexInfo.at(2));
391 ATH_MSG_DEBUG(
"Vertex is matched to a reconstructed secVtx");
398 truthMatchTypeDecor(*truthVtx) = truthMatchType;
402 return StatusCode::SUCCESS;
555 std::vector<const xAOD::TruthParticle*>&
set,
int counter)
const {
561 if (!particle)
continue;
564 if (particle->hasDecayVtx()) {
566 TVector3 decayPos(particle->decayVtx()->x(), particle->decayVtx()->y(), particle->decayVtx()->z());
567 TVector3 prodPos(particle->prodVtx()->x(), particle->prodVtx()->y(), particle->prodVtx()->z());
570 auto isInsideID = [](TVector3& v) {
return (v.Perp() < 300. && std::abs(v.z()) < 1500.); };
571 auto isOutsideID = [](TVector3& v) {
return (v.Perp() > 563. || std::abs(v.z()) > 2720.); };
574 auto isOutsideID_MuSA = [](TVector3& v) {
return (v.Perp() > 563. || std::abs(v.z()) > 2720.); };
575 auto isInsideMS_MuSA = [](TVector3& v) {
return (v.Perp() < 8000. && std::abs(v.z()) < 10000.); };
577 const auto distance = (decayPos - prodPos).Mag();
580 ATH_MSG_WARNING(
"Vetoing particle that may be added recursively infinitely (potential loop in generator record");
585 if (distance < 10.0) {
589 if (isOutsideID_MuSA(prodPos) && isInsideMS_MuSA(decayPos) && (particle->isCharged() || particle->isMuon())) {
590 set.push_back(particle);
594 if (isInsideID(prodPos) && isOutsideID(decayPos) && particle->isCharged()) {
595 set.push_back(particle);
596 }
else if (particle->isElectron() || particle->isMuon()) {
597 set.push_back(particle);
601 if (!(particle->isCharged()))
continue;
603 set.push_back(particle);
virtual double pt() const override final
The transverse momentum ( ) of the particle.
const TruthParticle_v1 * parent(size_t i) const
Retrieve the i-th mother (TruthParticle) of this TruthParticle.
virtual double pt() const override final
The transverse momentum ( ) of the particle.