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;
306 const EventContext& ctx = Gaudi::Hive::currentContext();
310 if (not trackHandle.
isValid()) {
312 return StatusCode::FAILURE;
323 ATH_MSG_WARNING(
"Shouldn't happen - EventInfo is buggy, setting mu to 0");
331 return StatusCode::SUCCESS;
335 std::vector<const xAOD::TruthParticle*> truthParticlesVec =
getTruthParticles(ctx);
343 unsigned int truthMu = 0;
346 truthMu =
static_cast<int>( truthPileupEventContainer->
size() );
351 float puEvents = truthMu>0 ? truthMu : actualMu;
355 float beamSpotWeight = 1;
358 ATH_MSG_DEBUG(
"Getting number of pu interactings per event");
366 ATH_MSG_DEBUG(
"beamSpotWeight is equal to " << beamSpotWeight);
370 if(readDecorHandle.
isAvailable()) prwWeight = readDecorHandle(*pie);
371 ATH_MSG_DEBUG(
"Applying pileup weight equal to " << prwWeight);
372 beamSpotWeight *= prwWeight;
376 ATH_MSG_DEBUG(
"Number of vertices retrieved for this event " << vertices->
size());
382 ATH_MSG_DEBUG(
"Failed to find a hard scatter vertex in this event.");
388 std::pair<std::vector<const xAOD::TruthVertex*>, std::vector<const xAOD::TruthVertex*>> truthVertices =
getTruthVertices(ctx);
389 std::vector<const xAOD::TruthVertex*> truthHSVertices = truthVertices.first;
390 std::vector<const xAOD::TruthVertex*> truthPUVertices = truthVertices.second;
397 m_monPlots->fill(*vertices, primaryvertex, truthHSVertices, truthPUVertices, actualMu, beamSpotWeight);
401 m_monPlots->fill(*vertices, truthMu, actualMu, beamSpotWeight);
418 const auto& stdVertexContainer = truthVrt->
stdcont();
420 auto findVtx = std::find_if(stdVertexContainer.rbegin(), stdVertexContainer.rend(), acceptTruthVertex);
421 truthVertex = (findVtx == stdVertexContainer.rend()) ?
nullptr : *findVtx;
425 if (not truthVertex)
ATH_MSG_INFO (
"Truth vertex did not pass cuts");
430 unsigned int nSelectedTruthTracks(0), nSelectedRecoTracks(0), nSelectedMatchedTracks(0), nAssociatedTruth(0), nMissingAssociatedTruth(0), nTruths(0);
439 std::map<const xAOD::TruthParticle*, std::vector<const xAOD::TrackParticle*>> cacheTruthMatching {};
441 std::vector<const xAOD::TrackParticle*> selectedTracks {};
442 selectedTracks.reserve(tracks->
size());
443 unsigned int nTrackTOT = 0;
444 unsigned int nTrackCentral = 0;
445 unsigned int nTrackPt1GeV = 0;
446 for (
const auto *
const thisTrack: *tracks) {
452 selectedTracks.push_back(thisTrack);
454 nSelectedRecoTracks++;
460 if (std::abs(thisTrack->eta()) < 2.5)
468 if (associatedTruth) {
479 nSelectedMatchedTracks++;
480 bool truthIsFromB =
false;
484 m_monPlots->fill(*thisTrack, *associatedTruth, truthIsFromB, puEvents, beamSpotWeight);
488 const bool isAssociatedTruth = associatedTruth !=
nullptr;
491 if(!isAssociatedTruth) nMissingAssociatedTruth++;
492 m_monPlots->fillFakeRate(*thisTrack,
isFake, isAssociatedTruth, puEvents, beamSpotWeight);
498 if (isAssociatedTruth) {
503 auto cachedAssoc = cacheTruthMatching.find(associatedTruth);
505 if (cachedAssoc == cacheTruthMatching.end()) {
507 cacheTruthMatching[associatedTruth] = {thisTrack};
511 cachedAssoc->second.push_back(thisTrack);
516 m_monPlots->fillNtuple(*thisTrack, primaryvertex);
524 for (
auto& cachedAssoc: cacheTruthMatching) {
531 std::sort(cachedAssoc.second.begin(), cachedAssoc.second.end(),
537 for (
int itrack = 0; itrack < (
int) cachedAssoc.second.size(); itrack++) {
541 m_monPlots->fillNtuple(*thisTrack, *thisTruth, primaryvertex, itrack);
547 m_monPlots->fill(nTrackTOT, nTrackCentral, nTrackPt1GeV, truthMu, actualMu,
nVertices, beamSpotWeight);
552 std::lock_guard<std::mutex> lock(
m_mutex);
553 m_truthCutFlow.merge(std::move(tmp_truth_cutflow));
559 for (
int itruth = 0; itruth < (
int) truthParticlesVec.size(); itruth++) {
566 ++nSelectedTruthTracks;
567 bool isEfficient(
false);
571 auto cachedAssoc = cacheTruthMatching.find(thisTruth);
573 if (cachedAssoc == cacheTruthMatching.end()) {
575 cacheTruthMatching[thisTruth] = {};
577 m_monPlots->fillDuplicate(*thisTruth, cacheTruthMatching[thisTruth], beamSpotWeight);
584 for (
const auto& thisTrack: selectedTracks) {
586 if (associatedTruth && associatedTruth == thisTruth) {
590 matchedTrack = thisTrack;
596 ATH_MSG_ERROR(
"An error occurred: Truth particle for tracking efficiency calculation is a nullptr");
598 else if (isEfficient && !matchedTrack){
599 ATH_MSG_ERROR(
"Something went wrong - we log a truth particle as reconstructed, but the reco track is a nullptr! Bailing out... ");
602 ATH_MSG_DEBUG(
"Filling efficiency plots info monitoring plots");
603 m_monPlots->fillEfficiency(*thisTruth, matchedTrack, isEfficient, truthMu, actualMu, beamSpotWeight);
605 ATH_MSG_DEBUG(
"Filling technical efficiency plots info monitoring plots");
609 m_monPlots->fillTechnicalEfficiency(*thisTruth, isEfficient,
610 truthMu, actualMu, beamSpotWeight);
613 ATH_MSG_DEBUG(
"Cannot fill technical efficiency. Missing si hit information for truth particle.");
631 if (nSelectedRecoTracks == nMissingAssociatedTruth) {
636 ATH_MSG_DEBUG(nAssociatedTruth <<
" tracks out of " << tracks->size() <<
" had associated truth.");
655 return StatusCode::SUCCESS;
681 ATH_MSG_DEBUG(
"Selected by pileup switch decoration requested from a truth particle but not available");
688 for (
const auto& thisTruth: truthParticles) {
702 std::vector<EfficiencyData> effs =
m_monPlots->retrieveBookedEfficiencies();
703 for (
auto&
eff : effs) {
716 return StatusCode::SUCCESS;
741 return StatusCode::SUCCESS;
744 const std::vector<const xAOD::TruthParticle*>
747 std::vector<const xAOD::TruthParticle*> tempVec {};
754 if (not truthParticleContainer.
isValid()) {
757 tempVec.insert(tempVec.begin(), truthParticleContainer->
begin(), truthParticleContainer->
end());
767 const auto&
links =
event->truthParticleLinks();
768 tempVec.reserve(
event->nTruthParticles());
769 for (
const auto& link :
links) {
771 tempVec.push_back(*link);
780 if (truthPileupEventContainer.
isValid()) {
781 const unsigned int nPileup = truthPileupEventContainer->
size();
782 tempVec.reserve(nPileup * 200);
783 for (
unsigned int i(0);
i != nPileup; ++
i) {
784 const auto *eventPileup = truthPileupEventContainer->
at(
i);
786 int ntruth = eventPileup->nTruthParticles();
787 ATH_MSG_VERBOSE(
"Adding " << ntruth <<
" truth particles from TruthPileupEvents container");
788 const auto&
links = eventPileup->truthParticleLinks();
789 for (
const auto& link :
links) {
791 tempVec.push_back(*link);
806 std::pair<const std::vector<const xAOD::TruthVertex*>,
const std::vector<const xAOD::TruthVertex*>>
809 std::vector<const xAOD::TruthVertex*> truthHSVertices = {};
810 truthHSVertices.reserve(5);
811 std::vector<const xAOD::TruthVertex*> truthPUVertices = {};
812 truthPUVertices.reserve(100);
835 if (truthEventContainer.
isValid()) {
836 for (
const auto *
const evt : *truthEventContainer) {
837 truthVtx =
evt->signalProcessVertex();
839 truthHSVertices.push_back(truthVtx);
853 if (truthPileupEventContainer.
isValid()) {
854 for (
const auto *
const evt : *truthPileupEventContainer) {
859 size_t i_vtx = 0;
size_t n_vtx =
evt->nTruthVertices();
860 while(!truthVtx && i_vtx<n_vtx){
861 truthVtx =
evt->truthVertex(i_vtx);
866 truthPUVertices.push_back(truthVtx);
876 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);
887 std::vector<int>& cutFlow) {
889 if (cutFlow.empty()) {
890 names.emplace_back(
"preCut");
891 cutFlow.push_back(0);
892 for (
unsigned int i = 0;
i !=
accept.getNCuts(); ++
i) {
893 cutFlow.push_back(0);
899 bool cutPositive =
true;
900 for (
unsigned int i = 0;
i != (
accept.getNCuts() + 1); ++
i) {
916 ATH_MSG_INFO(
"Requesting cut value outside of configured eta range: clamping eta = "
917 << std::abs(truth.
eta()) <<
" to eta= " <<
absEta);
928 const std::vector<const xAOD::TruthParticle*>& truthParticles,
931 float beamSpotWeight) {
936 if (truthParticles.empty()) {
937 ATH_MSG_WARNING(
"No entries in TruthParticles truth particle container. Skipping jet plots.");
938 return StatusCode::SUCCESS;
944 return StatusCode::SUCCESS;
957 isBjet = (btagLabel(*thisJet) == 5);
965 if (not
el.isValid())
continue;
976 bool isEfficient(
false);
978 for (
const auto *thisTrack: tracks) {
984 if (associatedTruth and associatedTruth == truth) {
993 bool truthIsFromB =
false;
997 m_monPlots->fillEfficiency(*truth, *thisJet, isEfficient, isBjet, truthIsFromB, beamSpotWeight);
1007 if (thisJet->p4().DeltaR(thisTrack->p4()) >
m_maxTrkJetDR) {
1015 const bool unlinked = (associatedTruth==
nullptr);
1017 bool truthIsFromB =
false;
1019 truthIsFromB =
true;
1021 m_monPlots->fill(*thisTrack, *thisJet, isBjet,
isFake, unlinked, truthIsFromB, beamSpotWeight);
1022 if (associatedTruth){
1023 m_monPlots->fillFakeRate(*thisTrack, *thisJet,
isFake, isBjet, truthIsFromB, beamSpotWeight);
1029 return StatusCode::SUCCESS;
1034 const float jetPt =
jet.pt();
1035 const float jetEta = std::abs(
jet.eta());