10 #include "GaudiKernel/SystemOfUnits.h"
50 float result(std::numeric_limits<float>::quiet_NaN());
53 if (truthMatchProbabilityAcc.isAvailable(trackParticle)) {
54 result = truthMatchProbabilityAcc(trackParticle);
61 safelyGetEta(
const T& pTrk,
const float safePtThreshold = 0.1) {
62 return (pTrk->pt() > safePtThreshold) ? (pTrk->eta()) : std::nan(
"");
69 return not ((
value < minVal)or(
value > maxVal));
75 return not (std::abs(
value) > absoluteMax);
90 return nf ?
i :
i - 1;
95 const float x(vtx->
x()),
y(vtx->
y()),
z(vtx->
z());
96 const float vrtR2 = (
x *
x +
y *
y);
98 return inRange(
z, 500.
f) and not (vrtR2 > 1);
101 const std::vector<float> ETA_PARTITIONS = {
102 2.7, 3.5, std::numeric_limits<float>::infinity()
109 const IInterface*
parent) :
134 (
nullptr,
static_cast<std::string
>(
m_dirName) +
static_cast<std::string
>(
m_folder),
147 std::vector<std::string> required_float_track_decorations {
"d0",
"hitResiduals_residualLocX",
"d0err"};
148 std::vector<std::string> required_int_track_decorations {};
149 std::vector<std::string> required_float_truth_decorations {
"d0"};
150 std::vector<std::string> required_int_truth_decorations {};
151 std::vector<std::string> required_int_jet_decorations {
"HadronConeExclTruthLabelID"};
153 std::string empty_prefix;
167 return StatusCode::SUCCESS;
305 const EventContext& ctx = Gaudi::Hive::currentContext();
309 if (not trackHandle.
isValid()) {
311 return StatusCode::FAILURE;
322 ATH_MSG_WARNING(
"Shouldn't happen - EventInfo is buggy, setting mu to 0");
330 return StatusCode::SUCCESS;
334 std::vector<const xAOD::TruthParticle*> truthParticlesVec =
getTruthParticles(ctx);
342 unsigned int truthMu = 0;
345 truthMu =
static_cast<int>( truthPileupEventContainer->
size() );
350 float puEvents = truthMu>0 ? truthMu : actualMu;
354 float beamSpotWeight = 1;
357 ATH_MSG_DEBUG(
"Getting number of pu interactings per event");
365 ATH_MSG_DEBUG(
"beamSpotWeight is equal to " << beamSpotWeight);
369 if(readDecorHandle.
isAvailable()) prwWeight = readDecorHandle(*pie);
370 ATH_MSG_DEBUG(
"Applying pileup weight equal to " << prwWeight);
371 beamSpotWeight *= prwWeight;
375 ATH_MSG_DEBUG(
"Number of vertices retrieved for this event " << vertices->
size());
381 ATH_MSG_DEBUG(
"Failed to find a hard scatter vertex in this event.");
387 std::pair<std::vector<const xAOD::TruthVertex*>, std::vector<const xAOD::TruthVertex*>> truthVertices =
getTruthVertices(ctx);
388 std::vector<const xAOD::TruthVertex*> truthHSVertices = truthVertices.first;
389 std::vector<const xAOD::TruthVertex*> truthPUVertices = truthVertices.second;
396 m_monPlots->fill(*vertices, primaryvertex, truthHSVertices, truthPUVertices, actualMu, beamSpotWeight);
400 m_monPlots->fill(*vertices, truthMu, actualMu, beamSpotWeight);
417 const auto& stdVertexContainer = truthVrt->
stdcont();
419 auto findVtx = std::find_if(stdVertexContainer.rbegin(), stdVertexContainer.rend(), acceptTruthVertex);
420 truthVertex = (findVtx == stdVertexContainer.rend()) ?
nullptr : *findVtx;
424 if (not truthVertex)
ATH_MSG_INFO (
"Truth vertex did not pass cuts");
429 unsigned int nSelectedTruthTracks(0), nSelectedRecoTracks(0), nSelectedMatchedTracks(0), nAssociatedTruth(0), nMissingAssociatedTruth(0), nTruths(0);
438 std::map<const xAOD::TruthParticle*, std::vector<const xAOD::TrackParticle*>> cacheTruthMatching {};
440 std::vector<const xAOD::TrackParticle*> selectedTracks {};
441 selectedTracks.reserve(tracks->
size());
442 unsigned int nTrackTOT = 0;
443 unsigned int nTrackCentral = 0;
444 unsigned int nTrackPt1GeV = 0;
445 for (
const auto *
const thisTrack: *tracks) {
451 selectedTracks.push_back(thisTrack);
453 nSelectedRecoTracks++;
459 if (std::abs(thisTrack->eta()) < 2.5)
467 if (associatedTruth) {
478 nSelectedMatchedTracks++;
479 bool truthIsFromB =
false;
483 m_monPlots->fill(*thisTrack, *associatedTruth, truthIsFromB, puEvents, beamSpotWeight);
487 const bool isAssociatedTruth = associatedTruth !=
nullptr;
490 if(!isAssociatedTruth) nMissingAssociatedTruth++;
491 m_monPlots->fillFakeRate(*thisTrack,
isFake, isAssociatedTruth, puEvents, beamSpotWeight);
497 if (isAssociatedTruth) {
502 auto cachedAssoc = cacheTruthMatching.find(associatedTruth);
504 if (cachedAssoc == cacheTruthMatching.end()) {
506 cacheTruthMatching[associatedTruth] = {thisTrack};
510 cachedAssoc->second.push_back(thisTrack);
515 m_monPlots->fillNtuple(*thisTrack, primaryvertex);
523 for (
auto& cachedAssoc: cacheTruthMatching) {
530 std::sort(cachedAssoc.second.begin(), cachedAssoc.second.end(),
536 for (
int itrack = 0; itrack < (
int) cachedAssoc.second.size(); itrack++) {
540 m_monPlots->fillNtuple(*thisTrack, *thisTruth, primaryvertex, itrack);
546 m_monPlots->fill(nTrackTOT, nTrackCentral, nTrackPt1GeV, truthMu, actualMu,
nVertices, beamSpotWeight);
551 std::lock_guard<std::mutex> lock(
m_mutex);
552 m_truthCutFlow.merge(std::move(tmp_truth_cutflow));
558 for (
int itruth = 0; itruth < (
int) truthParticlesVec.size(); itruth++) {
565 ++nSelectedTruthTracks;
566 bool isEfficient(
false);
570 auto cachedAssoc = cacheTruthMatching.find(thisTruth);
572 if (cachedAssoc == cacheTruthMatching.end()) {
574 cacheTruthMatching[thisTruth] = {};
576 m_monPlots->fillDuplicate(*thisTruth, cacheTruthMatching[thisTruth], beamSpotWeight);
583 for (
const auto& thisTrack: selectedTracks) {
585 if (associatedTruth && associatedTruth == thisTruth) {
589 matchedTrack = thisTrack;
595 ATH_MSG_ERROR(
"An error occurred: Truth particle for tracking efficiency calculation is a nullptr");
597 else if (isEfficient && !matchedTrack){
598 ATH_MSG_ERROR(
"Something went wrong - we log a truth particle as reconstructed, but the reco track is a nullptr! Bailing out... ");
601 ATH_MSG_DEBUG(
"Filling efficiency plots info monitoring plots");
602 m_monPlots->fillEfficiency(*thisTruth, matchedTrack, isEfficient, truthMu, actualMu, beamSpotWeight);
604 ATH_MSG_DEBUG(
"Filling technical efficiency plots info monitoring plots");
608 m_monPlots->fillTechnicalEfficiency(*thisTruth, isEfficient,
609 truthMu, actualMu, beamSpotWeight);
612 ATH_MSG_DEBUG(
"Cannot fill technical efficiency. Missing si hit information for truth particle.");
630 if (nSelectedRecoTracks == nMissingAssociatedTruth) {
635 ATH_MSG_DEBUG(nAssociatedTruth <<
" tracks out of " << tracks->size() <<
" had associated truth.");
654 return StatusCode::SUCCESS;
680 ATH_MSG_DEBUG(
"Selected by pileup switch decoration requested from a truth particle but not available");
687 for (
const auto& thisTruth: truthParticles) {
701 std::vector<EfficiencyData> effs =
m_monPlots->retrieveBookedEfficiencies();
702 for (
auto&
eff : effs) {
715 return StatusCode::SUCCESS;
740 return StatusCode::SUCCESS;
743 const std::vector<const xAOD::TruthParticle*>
746 std::vector<const xAOD::TruthParticle*> tempVec {};
753 if (not truthParticleContainer.
isValid()) {
756 tempVec.insert(tempVec.begin(), truthParticleContainer->
begin(), truthParticleContainer->
end());
766 const auto&
links =
event->truthParticleLinks();
767 tempVec.reserve(
event->nTruthParticles());
768 for (
const auto& link :
links) {
770 tempVec.push_back(*link);
779 if (truthPileupEventContainer.
isValid()) {
780 const unsigned int nPileup = truthPileupEventContainer->
size();
781 tempVec.reserve(nPileup * 200);
782 for (
unsigned int i(0);
i != nPileup; ++
i) {
783 const auto *eventPileup = truthPileupEventContainer->
at(
i);
785 int ntruth = eventPileup->nTruthParticles();
786 ATH_MSG_VERBOSE(
"Adding " << ntruth <<
" truth particles from TruthPileupEvents container");
787 const auto&
links = eventPileup->truthParticleLinks();
788 for (
const auto& link :
links) {
790 tempVec.push_back(*link);
805 std::pair<const std::vector<const xAOD::TruthVertex*>,
const std::vector<const xAOD::TruthVertex*>>
808 std::vector<const xAOD::TruthVertex*> truthHSVertices = {};
809 truthHSVertices.reserve(5);
810 std::vector<const xAOD::TruthVertex*> truthPUVertices = {};
811 truthPUVertices.reserve(100);
834 if (truthEventContainer.
isValid()) {
835 for (
const auto *
const evt : *truthEventContainer) {
836 truthVtx =
evt->signalProcessVertex();
838 truthHSVertices.push_back(truthVtx);
852 if (truthPileupEventContainer.
isValid()) {
853 for (
const auto *
const evt : *truthPileupEventContainer) {
858 size_t i_vtx = 0;
size_t n_vtx =
evt->nTruthVertices();
859 while(!truthVtx && i_vtx<n_vtx){
860 truthVtx =
evt->truthVertex(i_vtx);
865 truthPUVertices.push_back(truthVtx);
875 return std::make_pair<const std::vector<const xAOD::TruthVertex*>,
const std::vector<const xAOD::TruthVertex*>>((
const std::vector<const xAOD::TruthVertex*>)truthHSVertices, (
const std::vector<const xAOD::TruthVertex*>)truthPUVertices);
886 std::vector<int>& cutFlow) {
888 if (cutFlow.empty()) {
889 names.emplace_back(
"preCut");
890 cutFlow.push_back(0);
891 for (
unsigned int i = 0;
i !=
accept.getNCuts(); ++
i) {
892 cutFlow.push_back(0);
898 bool cutPositive =
true;
899 for (
unsigned int i = 0;
i != (
accept.getNCuts() + 1); ++
i) {
915 ATH_MSG_INFO(
"Requesting cut value outside of configured eta range: clamping eta = "
916 << std::abs(truth.
eta()) <<
" to eta= " <<
absEta);
927 const std::vector<const xAOD::TruthParticle*>& truthParticles,
930 float beamSpotWeight) {
935 if (truthParticles.empty()) {
936 ATH_MSG_WARNING(
"No entries in TruthParticles truth particle container. Skipping jet plots.");
937 return StatusCode::SUCCESS;
943 return StatusCode::SUCCESS;
956 isBjet = (btagLabel(*thisJet) == 5);
964 if (not
el.isValid())
continue;
975 bool isEfficient(
false);
977 for (
const auto *thisTrack: tracks) {
983 if (associatedTruth and associatedTruth == truth) {
992 bool truthIsFromB =
false;
996 m_monPlots->fillEfficiency(*truth, *thisJet, isEfficient, isBjet, truthIsFromB, beamSpotWeight);
1006 if (thisJet->p4().DeltaR(thisTrack->p4()) >
m_maxTrkJetDR) {
1014 const bool unlinked = (associatedTruth==
nullptr);
1016 bool truthIsFromB =
false;
1018 truthIsFromB =
true;
1020 m_monPlots->fill(*thisTrack, *thisJet, isBjet,
isFake, unlinked, truthIsFromB, beamSpotWeight);
1021 if (associatedTruth){
1022 m_monPlots->fillFakeRate(*thisTrack, *thisJet,
isFake, isBjet, truthIsFromB, beamSpotWeight);
1028 return StatusCode::SUCCESS;
1033 const float jetPt =
jet.pt();
1034 const float jetEta = std::abs(
jet.eta());