51 std::vector<const xAOD::TruthVertex*> truthVerticesToMatch,
65 return StatusCode::FAILURE;
69 return StatusCode::FAILURE;
100 std::vector<VertexTruthMatchInfo> matchinfo;
103 size_t ntracks = trackParticles.size();
104 const std::vector<float> & trkWeights = weightAcc( *vtx );
117 trkMuSATrkParts.reserve(ntracks);
118 for (
const auto& trkLink : trackParticles) {
119 if (!trkLink.isValid())
continue;
123 if (trkMuSATrkLink.
isValid()) {
124 trkMuSATrkParts.push_back(trkMuSATrkLink);
129 ATH_MSG_WARNING(
"MuSATrk_MSTPLink decoration is not available on track particle");
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) {
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 );
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;
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;
622 std::vector<const xAOD::TruthParticle*>&
set,
int counter)
const {
628 if (!particle)
continue;
630 auto isInsideID = [](
const TVector3& v) {
return (v.Perp() < 300. && std::abs(v.z()) < 1500.); };
631 auto isOutsideID = [](
const TVector3& v) {
return (v.Perp() > 563. || std::abs(v.z()) > 2720.); };
632 auto isWithinMuSAWindow = [](
const TVector3& v) {
return (v.Perp() < 8000. && std::abs(v.z()) < 10000.); };
635 if (particle->hasDecayVtx()) {
637 TVector3 decayPos(particle->decayVtx()->x(), particle->decayVtx()->y(), particle->decayVtx()->z());
638 TVector3 prodPos(particle->prodVtx()->x(), particle->prodVtx()->y(), particle->prodVtx()->z());
640 const auto distance = (decayPos - prodPos).Mag();
643 ATH_MSG_WARNING(
"Vetoing particle that may be added recursively infinitely (potential loop in generator record");
648 if (distance < 10.0) {
652 if (isWithinMuSAWindow(decayPos) && (particle->isCharged() || particle->isMuon())) {
653 set.push_back(particle);
657 if (isInsideID(prodPos) && isOutsideID(decayPos) && particle->isCharged()) {
658 set.push_back(particle);
659 }
else if (particle->isElectron() || particle->isMuon()) {
660 set.push_back(particle);
664 if (!(particle->isCharged()))
continue;
669 TVector3 prodPos(prodVtx->
x(), prodVtx->
y(), prodVtx->
z());
670 if (isWithinMuSAWindow(prodPos)) {
671 set.push_back(particle);
675 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.