22 return StatusCode::SUCCESS;
30 for (
size_t i = 0;
i < matches.size(); ++
i ) {
31 if ( link.
key() == std::get<0>(matches[
i]).key() && link.
index() == std::get<0>(matches[
i]).index() )
35 matches.emplace_back( link, 0., 0. );
36 return matches.size() - 1;
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 ) {
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];
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.");
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);
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);
332 splitPartnerDecor( *recoVerticesToMatch[j] ).emplace_back(splitLink_jk);
335 foundSplits.push_back(j);
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;
413 ATH_MSG_DEBUG(
"Insufficient pt to reconstruct the particle");
435 if (std::abs(trkPart->eta()) < 2.5) {
436 ATH_MSG_DEBUG(
"Particle has a track that passes track selection.");
439 ATH_MSG_DEBUG(
"Particle has a track, but did not pass track selection.");
454 float matchProb = 0.0;
456 matchProb = trk_truthProbAcc(*trkPart);
458 ATH_MSG_DEBUG(
"truthMatchProbability not available on track");
466 if(trackPass( *trkPart )) {
467 ATH_MSG_DEBUG(
"Particle has a track that passes track selection.");
470 ATH_MSG_DEBUG(
"Particle has a track, but did not pass track selection.");
474 ATH_MSG_DEBUG(
"Track selection decoration not available, calling the track selected");
503 if(
std::find(truthVerticesToMatch.begin(), truthVerticesToMatch.end(), parentVertex) != truthVerticesToMatch.end()) {
550 ATH_MSG_WARNING(
"TrackTruthOriginTool not set, returning 0 for origin");
555 std::vector<const xAOD::TruthParticle*>&
set,
int counter)
const {
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");
589 if (isOutsideID_MuSA(prodPos) && isInsideMS_MuSA(decayPos) && (
particle->isCharged() ||
particle->isMuon())) {
594 if (isInsideID(prodPos) && isOutsideID(decayPos) &&
particle->isCharged()) {
601 if (!(
particle->isCharged()))
continue;
612 ATH_MSG_WARNING(
"TrackTruthOriginTool not set, returning false for isFrom");