51 std::vector<const xAOD::TruthVertex*> truthVerticesToMatch,
65 return StatusCode::FAILURE;
69 return StatusCode::FAILURE;
75 static const xAOD::Vertex::Decorator<std::vector<VertexTruthMatchInfo> > matchInfoDecor(
"truthVertexMatchingInfos");
76 static const xAOD::Vertex::Decorator<int> recoMatchTypeDecor(
"vertexMatchType");
77 static const xAOD::Vertex::Decorator<std::vector<ElementLink<xAOD::VertexContainer> > > splitPartnerDecor(
"splitPartners");
79 static const xAOD::Vertex::Decorator<int> smOriginDecor(
"vertexMatchOriginType");
81 const xAOD::Vertex::Decorator<float> fakeScoreDecor(
"fakeScore");
82 const xAOD::Vertex::Decorator<float> otherScoreDecor(
"otherScore");
86 xAOD::Vertex::ConstAccessor<xAOD::Vertex::TrackParticleLinks_t> trkAcc(
"trackParticleLinks");
87 xAOD::Vertex::ConstAccessor<std::vector<float> > weightAcc(
"trackWeights");
88 xAOD::TrackParticle::ConstAccessor<ElementLink<xAOD::TruthParticleContainer> > trk_truthPartAcc(
"truthParticleLink");
89 xAOD::TrackParticle::ConstAccessor<float> trk_truthProbAcc(
"truthMatchProbability");
100 std::vector<VertexTruthMatchInfo> matchinfo;
103 size_t ntracks = trackParticles.size();
104 const std::vector<float> & trkWeights = weightAcc( *vtx );
115 const SG::AuxElement::Accessor<ElementLink<xAOD::TrackParticleContainer>> acc_MSTPLink(
"MuSATrk_MSTPLink");
117 trkMuSATrkParts.reserve(ntracks);
118 for (
const auto& trkLink : trackParticles) {
119 if (!trkLink.isValid())
continue;
121 if (acc_MSTPLink.isAvailable(trackParticle)) {
123 if (trkMuSATrkLink.
isValid()) {
124 trkMuSATrkParts.push_back(trkMuSATrkLink);
129 ATH_MSG_WARNING(
"MuSATrk_MSTPLink decoration is not available on track particle");
135 if ((!trkAcc.isAvailable(*vtx) || !weightAcc.isAvailable(*vtx)) && !
m_doMuSA) {
136 ATH_MSG_WARNING(
"trackParticles or trackWeights not available, vertex is missing info");
139 if ( trkWeights.size() != ntracks ) {
140 ATH_MSG_WARNING(
"Vertex without same number of tracks and trackWeights, vertex is missing info");
144 ATH_MSG_DEBUG(
"Matching new vertex at (" << vtx->x() <<
", " << vtx->y() <<
", " << vtx->z() <<
")" <<
" with " << ntracks <<
" tracks, at index: " << vtx->index());
146 float totalWeight = 0.;
152 int combinedSMOrigin = 0;
155 for (
size_t t = 0; t < ntracks; ++t ) {
160 if (!trackParticles[t].
isValid()) {
166 if (t >= trkParts.size() || !trkParts[t].isValid()) {
167 ATH_MSG_DEBUG(
"Track " << t <<
" is invalid or out of bounds in trkParts!");
176 totalWeight += trkWeights[t];
184 }
catch (
const std::exception& e) {
190 if (!trk_truthPartAcc.isAvailable(trk)) {
191 ATH_MSG_DEBUG(
"The truth particle link decoration isn't available.");
202 prob = trk_truthProbAcc(trk);
210 const int ancestorVertexUniqueID =
checkProduction(truthPart, truthVerticesToMatch);
214 combinedSMOrigin |= smOrigin;
226 auto it = std::find_if(truthVerticesToMatch.begin(), truthVerticesToMatch.end(),
227 [&](
const auto& ele){ return HepMC::uniqueID(ele) == ancestorVertexUniqueID;} );
229 if (it == truthVerticesToMatch.end()) {
230 ATH_MSG_WARNING(
"Truth vertex with unique ID " << ancestorVertexUniqueID <<
" not found!");
235 size_t matchIdx = indexOfMatchInfo(matchinfo, elLink);
238 std::get<1>(matchinfo[matchIdx]) += 1.0;
240 std::get<1>(matchinfo[matchIdx]) += trkWeights[t];
242 std::get<2>(matchinfo[matchIdx]) += trk.
pt();
263 std::get<1>(link) /= totalWeight;
264 std::get<2>(link) /= totalPt;
267 float fakeScore = fakePt/totalPt;
268 float otherScore = otherPt/totalPt;
270 matchInfoDecor ( *vtx ) = matchinfo;
271 fakeScoreDecor ( *vtx ) = fakeScore;
272 otherScoreDecor( *vtx ) = otherScore;
276 smOriginDecor( *vtx ) = combinedSMOrigin;
284 std::vector<bool> assignedType( recoVerticesToMatch.size(),
false );
285 static const xAOD::TruthVertex::Decorator<bool>
isMatched(
"matchedToRecoVertex");
286 static const xAOD::TruthVertex::Decorator<bool>
isSplit(
"vertexSplit");
288 for (
size_t i = 0; i < recoVerticesToMatch.size(); ++i ) {
290 int recoVertexMatchType = 0;
292 if ( assignedType[i] ) {
297 std::vector<VertexTruthMatchInfo> & info = matchInfoDecor( *recoVerticesToMatch[i] );
298 float fakeScore = fakeScoreDecor( *recoVerticesToMatch[i] );
303 }
else if (info.size() == 1) {
305 ATH_MSG_DEBUG(
"One true decay vertices matched with sufficient weight. Vertex is matched.");
307 isMatched(**std::get<0>(info[0])) =
true;
310 ATH_MSG_DEBUG(
"One true decay vertices matched with insufficient weight. Vertex is other.");
313 }
else if (info.size() >= 2 ) {
314 ATH_MSG_DEBUG(
"Multiple true decay vertices matched. Vertex is merged.");
318 isMatched(**std::get<0>(link)) = true;
321 ATH_MSG_DEBUG(
"Vertex is neither fake nor LLP. Marking as OTHER.");
325 recoMatchTypeDecor(*recoVerticesToMatch[i]) = recoVertexMatchType;
330 std::vector<size_t> foundSplits;
331 for (
size_t j = i + 1; j < recoVerticesToMatch.size(); ++j ) {
332 std::vector<VertexTruthMatchInfo> & info2 = matchInfoDecor( *recoVerticesToMatch[j] );
337 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() ) {
340 splitLink_ij.
setElement( recoVerticesToMatch[j] );
342 splitPartnerDecor( *recoVerticesToMatch[i] ).emplace_back(splitLink_ij);
345 splitLink_ji.
setElement( recoVerticesToMatch[i] );
347 splitPartnerDecor( *recoVerticesToMatch[j] ).emplace_back(splitLink_ji);
350 for (
auto k : foundSplits ) {
352 splitLink_kj.
setElement( recoVerticesToMatch[j] );
354 splitPartnerDecor( *recoVerticesToMatch[k] ).emplace_back(splitLink_kj);
357 splitLink_jk.
setElement( recoVerticesToMatch[k] );
359 splitPartnerDecor( *recoVerticesToMatch[j] ).emplace_back(splitLink_jk);
362 foundSplits.push_back(j);
365 isSplit(**std::get<0>(info[0])) =
true;
366 assignedType[j] =
true;
377 static const xAOD::TruthVertex::Decorator<int> truthMatchTypeDecor(
"truthVertexMatchType");
381 std::vector<const xAOD::TruthParticle*> reconstructibleParticles;
386 std::vector<int> particleInfo = {0,0,0};
387 std::vector<int> vertexInfo = {0,0,0};
389 for(
size_t n = 0; n < reconstructibleParticles.size(); n++){
396 for(
size_t h = 0;
h < particleInfo.size();
h++){
397 vertexInfo.at(
h) += particleInfo.at(
h);
402 int truthMatchType = 0;
403 if( vertexInfo.at(0) > 1 &&
404 ((
m_doMuSA && (truthVtx->perp() < 8000 && std::abs(truthVtx->z()) < 10000)) ||
405 (!
m_doMuSA && truthVtx->perp() < 320 && std::abs(truthVtx->z()) < 1500))){
406 ATH_MSG_DEBUG(
"Vertex is reconstructable and in " << (
m_doMuSA ?
"Muon Spectrometer" :
"Inner Det") <<
" region");
414 ATH_MSG_DEBUG(
"Vertex is has at least two tracks passing track selection: " << vertexInfo.at(2));
418 ATH_MSG_DEBUG(
"Vertex is matched to a reconstructed secVtx");
425 truthMatchTypeDecor(*truthVtx) = truthMatchType;
429 return StatusCode::SUCCESS;