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;
303 const EventContext& ctx = Gaudi::Hive::currentContext();
307 if (not trackHandle.
isValid()) {
309 return StatusCode::FAILURE;
320 ATH_MSG_WARNING(
"Shouldn't happen - EventInfo is buggy, setting mu to 0");
328 return StatusCode::SUCCESS;
332 std::vector<const xAOD::TruthParticle*> truthParticlesVec =
getTruthParticles(ctx);
340 unsigned int truthMu = 0;
343 truthMu =
static_cast<int>( truthPileupEventContainer->
size() );
348 float puEvents = truthMu>0 ? truthMu : actualMu;
352 float beamSpotWeight = 1;
355 ATH_MSG_DEBUG(
"Getting number of pu interactings per event");
363 ATH_MSG_DEBUG(
"beamSpotWeight is equal to " << beamSpotWeight);
367 if(readDecorHandle.
isAvailable()) prwWeight = readDecorHandle(*pie);
368 ATH_MSG_DEBUG(
"Applying pileup weight equal to " << prwWeight);
369 beamSpotWeight *= prwWeight;
373 ATH_MSG_DEBUG(
"Number of vertices retrieved for this event " << vertices->
size());
379 ATH_MSG_DEBUG(
"Failed to find a hard scatter vertex in this event.");
385 std::pair<std::vector<const xAOD::TruthVertex*>, std::vector<const xAOD::TruthVertex*>> truthVertices =
getTruthVertices(ctx);
386 std::vector<const xAOD::TruthVertex*> truthHSVertices = truthVertices.first;
387 std::vector<const xAOD::TruthVertex*> truthPUVertices = truthVertices.second;
394 m_monPlots->fill(*vertices, primaryvertex, truthHSVertices, truthPUVertices, beamSpotWeight);
398 m_monPlots->fill(*vertices, truthMu, actualMu, beamSpotWeight);
416 const auto& stdVertexContainer = truthVrt->
stdcont();
418 auto findVtx = std::find_if(stdVertexContainer.rbegin(), stdVertexContainer.rend(), acceptTruthVertex);
419 truthVertex = (findVtx == stdVertexContainer.rend()) ?
nullptr : *findVtx;
423 if (not truthVertex)
ATH_MSG_INFO (
"Truth vertex did not pass cuts");
428 unsigned int nSelectedTruthTracks(0), nSelectedRecoTracks(0), nSelectedMatchedTracks(0), nAssociatedTruth(0), nMissingAssociatedTruth(0), nTruths(0);
437 std::map<const xAOD::TruthParticle*, std::vector<const xAOD::TrackParticle*>> cacheTruthMatching {};
439 std::vector<const xAOD::TrackParticle*> selectedTracks {};
440 selectedTracks.reserve(tracks->
size());
441 unsigned int nTrackTOT = 0;
442 for (
const auto *
const thisTrack: *tracks) {
448 selectedTracks.push_back(thisTrack);
450 nSelectedRecoTracks++;
460 if (associatedTruth) {
471 nSelectedMatchedTracks++;
472 bool truthIsFromB =
false;
476 m_monPlots->fill(*thisTrack, *associatedTruth, truthIsFromB, puEvents, beamSpotWeight);
480 const bool isAssociatedTruth = associatedTruth !=
nullptr;
483 if(!isAssociatedTruth) nMissingAssociatedTruth++;
484 m_monPlots->fillFakeRate(*thisTrack,
isFake, isAssociatedTruth, puEvents, beamSpotWeight);
490 if (isAssociatedTruth) {
495 auto cachedAssoc = cacheTruthMatching.find(associatedTruth);
497 if (cachedAssoc == cacheTruthMatching.end()) {
499 cacheTruthMatching[associatedTruth] = {thisTrack};
503 cachedAssoc->second.push_back(thisTrack);
508 m_monPlots->fillNtuple(*thisTrack, primaryvertex);
516 for (
auto& cachedAssoc: cacheTruthMatching) {
523 std::sort(cachedAssoc.second.begin(), cachedAssoc.second.end(),
529 for (
int itrack = 0; itrack < (
int) cachedAssoc.second.size(); itrack++) {
533 m_monPlots->fillNtuple(*thisTrack, *thisTruth, primaryvertex, itrack);
544 std::lock_guard<std::mutex> lock(
m_mutex);
545 m_truthCutFlow.merge(std::move(tmp_truth_cutflow));
551 for (
int itruth = 0; itruth < (
int) truthParticlesVec.size(); itruth++) {
558 ++nSelectedTruthTracks;
559 bool isEfficient(
false);
563 auto cachedAssoc = cacheTruthMatching.find(thisTruth);
565 if (cachedAssoc == cacheTruthMatching.end()) {
567 cacheTruthMatching[thisTruth] = {};
569 m_monPlots->fillDuplicate(*thisTruth, cacheTruthMatching[thisTruth], beamSpotWeight);
576 for (
const auto& thisTrack: selectedTracks) {
578 if (associatedTruth && associatedTruth == thisTruth) {
582 matchedTrack = thisTrack;
588 ATH_MSG_ERROR(
"An error occurred: Truth particle for tracking efficiency calculation is a nullptr");
590 else if (isEfficient && !matchedTrack){
591 ATH_MSG_ERROR(
"Something went wrong - we log a truth particle as reconstructed, but the reco track is a nullptr! Bailing out... ");
594 ATH_MSG_DEBUG(
"Filling efficiency plots info monitoring plots");
595 m_monPlots->fillEfficiency(*thisTruth, matchedTrack, isEfficient, truthMu, actualMu, beamSpotWeight);
597 ATH_MSG_DEBUG(
"Filling technical efficiency plots info monitoring plots");
601 m_monPlots->fillTechnicalEfficiency(*thisTruth, isEfficient,
602 truthMu, actualMu, beamSpotWeight);
605 ATH_MSG_DEBUG(
"Cannot fill technical efficiency. Missing si hit information for truth particle.");
623 if (nSelectedRecoTracks == nMissingAssociatedTruth) {
628 ATH_MSG_DEBUG(nAssociatedTruth <<
" tracks out of " << tracks->size() <<
" had associated truth.");
647 return StatusCode::SUCCESS;
673 ATH_MSG_DEBUG(
"Selected by pileup switch decoration requested from a truth particle but not available");
680 for (
const auto& thisTruth: truthParticles) {
694 std::vector<EfficiencyData> effs =
m_monPlots->retrieveBookedEfficiencies();
695 for (
auto&
eff : effs) {
708 return StatusCode::SUCCESS;
733 return StatusCode::SUCCESS;
736 const std::vector<const xAOD::TruthParticle*>
739 std::vector<const xAOD::TruthParticle*> tempVec {};
746 if (not truthParticleContainer.
isValid()) {
749 tempVec.insert(tempVec.begin(), truthParticleContainer->
begin(), truthParticleContainer->
end());
759 const auto&
links =
event->truthParticleLinks();
760 tempVec.reserve(
event->nTruthParticles());
761 for (
const auto& link :
links) {
763 tempVec.push_back(*link);
772 if (truthPileupEventContainer.
isValid()) {
773 const unsigned int nPileup = truthPileupEventContainer->
size();
774 tempVec.reserve(nPileup * 200);
775 for (
unsigned int i(0);
i != nPileup; ++
i) {
776 const auto *eventPileup = truthPileupEventContainer->
at(
i);
778 int ntruth = eventPileup->nTruthParticles();
779 ATH_MSG_VERBOSE(
"Adding " << ntruth <<
" truth particles from TruthPileupEvents container");
780 const auto&
links = eventPileup->truthParticleLinks();
781 for (
const auto& link :
links) {
783 tempVec.push_back(*link);
798 std::pair<const std::vector<const xAOD::TruthVertex*>,
const std::vector<const xAOD::TruthVertex*>>
801 std::vector<const xAOD::TruthVertex*> truthHSVertices = {};
802 truthHSVertices.reserve(5);
803 std::vector<const xAOD::TruthVertex*> truthPUVertices = {};
804 truthPUVertices.reserve(100);
827 if (truthEventContainer.
isValid()) {
828 for (
const auto *
const evt : *truthEventContainer) {
829 truthVtx =
evt->signalProcessVertex();
831 truthHSVertices.push_back(truthVtx);
845 if (truthPileupEventContainer.
isValid()) {
846 for (
const auto *
const evt : *truthPileupEventContainer) {
851 size_t i_vtx = 0;
size_t n_vtx =
evt->nTruthVertices();
852 while(!truthVtx && i_vtx<n_vtx){
853 truthVtx =
evt->truthVertex(i_vtx);
858 truthPUVertices.push_back(truthVtx);
868 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);
879 std::vector<int>& cutFlow) {
881 if (cutFlow.empty()) {
882 names.emplace_back(
"preCut");
883 cutFlow.push_back(0);
884 for (
unsigned int i = 0;
i !=
accept.getNCuts(); ++
i) {
885 cutFlow.push_back(0);
891 bool cutPositive =
true;
892 for (
unsigned int i = 0;
i != (
accept.getNCuts() + 1); ++
i) {
908 ATH_MSG_INFO(
"Requesting cut value outside of configured eta range: clamping eta = "
909 << std::abs(truth.
eta()) <<
" to eta= " <<
absEta);
920 const std::vector<const xAOD::TruthParticle*>& truthParticles,
923 float beamSpotWeight) {
928 if (truthParticles.empty()) {
929 ATH_MSG_WARNING(
"No entries in TruthParticles truth particle container. Skipping jet plots.");
930 return StatusCode::SUCCESS;
936 return StatusCode::SUCCESS;
949 isBjet = (btagLabel(*thisJet) == 5);
957 if (not
el.isValid())
continue;
968 bool isEfficient(
false);
970 for (
const auto *thisTrack: tracks) {
976 if (associatedTruth and associatedTruth == truth) {
985 bool truthIsFromB =
false;
989 m_monPlots->fillEfficiency(*truth, *thisJet, isEfficient, isBjet, truthIsFromB, beamSpotWeight);
1007 const bool unlinked = (associatedTruth==
nullptr);
1009 bool truthIsFromB =
false;
1011 truthIsFromB =
true;
1013 m_monPlots->fill(*thisTrack, *thisJet, isBjet,
isFake, unlinked, truthIsFromB, beamSpotWeight);
1014 if (associatedTruth){
1015 m_monPlots->fillFakeRate(*thisTrack, *thisJet,
isFake, isBjet, truthIsFromB, beamSpotWeight);
1021 return StatusCode::SUCCESS;
1027 const float jetEta = std::abs(
jet.eta());