10#include "GaudiKernel/SystemOfUnits.h"
49 float result(std::numeric_limits<float>::quiet_NaN());
52 if (truthMatchProbabilityAcc.isAvailable(trackParticle)) {
53 result = truthMatchProbabilityAcc(trackParticle);
60 safelyGetEta(
const T& pTrk,
const float safePtThreshold = 0.1) {
61 return (pTrk->pt() > safePtThreshold) ? (pTrk->eta()) : std::nan(
"");
67 inRange(
const T& value,
const T& minVal,
const T& maxVal) {
68 return not ((value < minVal)or(value > maxVal));
73 inRange(
const T& value,
const T& absoluteMax) {
74 return not (std::abs(value) > absoluteMax);
82 binIndex(
const T& val,
const std::vector<T>& partitions) {
89 return nf ?
i :
i - 1;
94 const float x(vtx->
x()),
y(vtx->
y()),
z(vtx->
z());
95 const float vrtR2 = (
x *
x +
y *
y);
97 return inRange(
z, 500.f) and not (vrtR2 > 1);
101 2.7, 3.5, std::numeric_limits<float>::infinity()
108 const IInterface* parent) :
133 (
nullptr,
static_cast<std::string
>(
m_dirName) +
static_cast<std::string
>(
m_folder),
144 std::vector<std::string> trk_decorations;
160 std::vector<std::string> required_float_track_decorations {
"d0",
"hitResiduals_residualLocX",
"d0err"};
161 std::vector<std::string> required_int_track_decorations {};
162 std::vector<std::string> required_float_truth_decorations {
"d0"};
163 std::vector<std::string> required_int_truth_decorations {};
164 std::vector<std::string> required_int_jet_decorations {
"HadronConeExclTruthLabelID"};
169 m_datfile <<
"EvtNumber,PdgID,Px,Py,Pz,E,Pt,Eta,Phi,Mass,numPU,numvtx,MatchProb"<<std::endl;
171 std::string empty_prefix;
185 return StatusCode::SUCCESS;
326 const EventContext& ctx = Gaudi::Hive::currentContext();
330 if (not trackHandle.
isValid()) {
332 return StatusCode::FAILURE;
343 ATH_MSG_WARNING(
"Shouldn't happen - EventInfo is buggy, setting mu to 0");
351 return StatusCode::SUCCESS;
355 std::vector<const xAOD::TruthParticle*> truthParticlesVec =
getTruthParticles(ctx);
364 unsigned int truthMu = 0;
367 truthMu =
static_cast<int>( truthPileupEventContainer->size() );
369 if(pie.
isValid()) actualMu = pie->actualInteractionsPerCrossing();
372 float puEvents = truthMu>0 ? truthMu : actualMu;
375 unsigned int nVertices = 0;
376 float beamSpotWeight = 1;
379 ATH_MSG_DEBUG(
"Getting number of pu interactings per event");
385 nVertices = not vertices->empty() ? vertices->size() : 0;
386 beamSpotWeight = pie->beamSpotWeight();
387 ATH_MSG_DEBUG(
"beamSpotWeight is equal to " << beamSpotWeight);
391 if(readDecorHandle.
isAvailable()) prwWeight = readDecorHandle(*pie);
392 ATH_MSG_DEBUG(
"Applying pileup weight equal to " << prwWeight);
393 beamSpotWeight *= prwWeight;
396 if (vertices.
isValid() and not vertices->empty()) {
397 ATH_MSG_DEBUG(
"Number of vertices retrieved for this event " << vertices->size());
403 ATH_MSG_DEBUG(
"Failed to find a hard scatter vertex in this event.");
409 std::pair<std::vector<const xAOD::TruthVertex*>, std::vector<const xAOD::TruthVertex*>> truthVertices =
getTruthVertices(ctx);
410 std::vector<const xAOD::TruthVertex*> truthHSVertices = truthVertices.first;
411 std::vector<const xAOD::TruthVertex*> truthPUVertices = truthVertices.second;
418 m_monPlots->fill(*vertices, primaryvertex, truthHSVertices, truthPUVertices, actualMu, beamSpotWeight);
422 m_monPlots->fill(*vertices, truthMu, actualMu, beamSpotWeight);
439 const auto& stdVertexContainer = truthVrt->stdcont();
441 auto findVtx = std::find_if(stdVertexContainer.rbegin(), stdVertexContainer.rend(), acceptTruthVertex);
442 truthVertex = (findVtx == stdVertexContainer.rend()) ? nullptr : *findVtx;
446 if (not truthVertex)
ATH_MSG_INFO (
"Truth vertex did not pass cuts");
451 unsigned int nSelectedTruthTracks(0), nSelectedRecoTracks(0), nSelectedMatchedTracks(0), nAssociatedTruth(0), nMissingAssociatedTruth(0), nTruths(0);
460 std::map<const xAOD::TruthParticle*, std::vector<const xAOD::TrackParticle*>> cacheTruthMatching {};
462 std::vector<const xAOD::TrackParticle*> selectedTracks {};
463 selectedTracks.reserve(tracks->
size());
464 unsigned int nTrackTOT = 0;
465 unsigned int nTrackCentral = 0;
466 unsigned int nTrackPt1GeV = 0;
467 for (
const auto *
const thisTrack: *tracks) {
473 selectedTracks.push_back(thisTrack);
475 nSelectedRecoTracks++;
479 if (thisTrack->pt() >= (1 * Gaudi::Units::GeV))
481 if (std::abs(thisTrack->eta()) < 2.5)
484 m_monPlots->fill(*thisTrack, puEvents, nVertices, beamSpotWeight);
486 float prob = getMatchingProbability(*thisTrack);
489 if (associatedTruth) {
500 nSelectedMatchedTracks++;
501 bool truthIsFromB =
false;
505 m_monPlots->fill(*thisTrack, *associatedTruth, truthIsFromB, puEvents, beamSpotWeight);
509 const bool isAssociatedTruth = associatedTruth !=
nullptr;
510 const bool isFake = not std::isnan(prob) ? (prob <
m_lowProb) :
true;
512 if(!isAssociatedTruth) nMissingAssociatedTruth++;
513 m_monPlots->fillFakeRate(*thisTrack, isFake, isAssociatedTruth, puEvents, beamSpotWeight);
519 if (isAssociatedTruth) {
524 auto cachedAssoc = cacheTruthMatching.find(associatedTruth);
526 if (cachedAssoc == cacheTruthMatching.end()) {
528 cacheTruthMatching[associatedTruth] = {thisTrack};
532 cachedAssoc->second.push_back(thisTrack);
537 m_monPlots->fillNtuple(*thisTrack, primaryvertex);
545 for (
auto& cachedAssoc: cacheTruthMatching) {
552 std::sort(cachedAssoc.second.begin(), cachedAssoc.second.end(),
558 for (
int itrack = 0; itrack < (int) cachedAssoc.second.size(); itrack++) {
562 m_monPlots->fillNtuple(*thisTrack, *thisTruth, primaryvertex, itrack);
568 m_monPlots->fill(nTrackTOT, nTrackCentral, nTrackPt1GeV, truthMu, actualMu, nVertices, beamSpotWeight);
573 std::lock_guard<std::mutex> lock(
m_mutex);
574 m_truthCutFlow.merge(std::move(tmp_truth_cutflow));
580 for (
int itruth = 0; itruth < (int) truthParticlesVec.size(); itruth++) {
587 ++nSelectedTruthTracks;
588 bool isEfficient(
false);
589 float matchingProbability{};
593 auto cachedAssoc = cacheTruthMatching.find(thisTruth);
595 if (cachedAssoc == cacheTruthMatching.end()) {
597 cacheTruthMatching[thisTruth] = {};
599 m_monPlots->fillDuplicate(*thisTruth, cacheTruthMatching[thisTruth], beamSpotWeight);
606 for (
const auto& thisTrack: selectedTracks) {
608 if (associatedTruth && associatedTruth == thisTruth) {
609 float prob = getMatchingProbability(*thisTrack);
610 if (not std::isnan(prob) && prob >
m_lowProb) {
611 matchingProbability = prob;
613 matchedTrack = thisTrack;
620 <<thisTruth->
py()/ Gaudi::Units::GeV<<
","<<thisTruth->
pz()/ Gaudi::Units::GeV<<
","
621 <<thisTruth->
e()/ Gaudi::Units::GeV<<
","<<thisTruth->
pt()/ Gaudi::Units::GeV<<
","
622 <<thisTruth->
eta()<<
","<<thisTruth->
phi()<<
","<<thisTruth->
m()/ Gaudi::Units::GeV<<
","
623 <<puEvents<<
","<<nVertices<<
","<<matchingProbability<<std::endl;
626 ATH_MSG_ERROR(
"An error occurred: Truth particle for tracking efficiency calculation is a nullptr");
628 else if (isEfficient && !matchedTrack){
629 ATH_MSG_ERROR(
"Something went wrong - we log a truth particle as reconstructed, but the reco track is a nullptr! Bailing out... ");
632 ATH_MSG_DEBUG(
"Filling efficiency plots info monitoring plots");
633 m_monPlots->fillEfficiency(*thisTruth, matchedTrack, isEfficient, truthMu, actualMu, beamSpotWeight);
635 ATH_MSG_DEBUG(
"Filling technical efficiency plots info monitoring plots");
639 m_monPlots->fillTechnicalEfficiency(*thisTruth, isEfficient,
640 truthMu, actualMu, beamSpotWeight);
643 ATH_MSG_DEBUG(
"Cannot fill technical efficiency. Missing si hit information for truth particle.");
661 if (nSelectedRecoTracks == nMissingAssociatedTruth) {
666 ATH_MSG_DEBUG(nAssociatedTruth <<
" tracks out of " << tracks->
size() <<
" had associated truth.");
685 return StatusCode::SUCCESS;
711 ATH_MSG_DEBUG(
"Selected by pileup switch decoration requested from a truth particle but not available");
718 for (
const auto& thisTruth: truthParticles) {
727 std::vector<HistData> hists =
m_monPlots->retrieveBookedHistograms();
728 for (
const auto& hist : hists) {
732 std::vector<EfficiencyData> effs =
m_monPlots->retrieveBookedEfficiencies();
733 for (
auto& eff : effs) {
740 std::vector<TreeData> trees =
m_monPlots->retrieveBookedTrees();
741 for (
auto& t : trees) {
746 return StatusCode::SUCCESS;
771 return StatusCode::SUCCESS;
774const std::vector<const xAOD::TruthParticle*>
777 std::vector<const xAOD::TruthParticle*> tempVec {};
784 if (not truthParticleContainer.
isValid()) {
787 tempVec.insert(tempVec.begin(), truthParticleContainer->begin(), truthParticleContainer->end());
797 const auto& links =
event->truthParticleLinks();
798 tempVec.reserve(event->nTruthParticles());
799 for (
const auto& link : links) {
801 tempVec.push_back(*link);
810 if (truthPileupEventContainer.
isValid()) {
811 const unsigned int nPileup = truthPileupEventContainer->size();
812 tempVec.reserve(nPileup * 200);
813 for (
unsigned int i(0); i != nPileup; ++i) {
814 const auto *eventPileup = truthPileupEventContainer->at(i);
816 int ntruth = eventPileup->nTruthParticles();
817 ATH_MSG_VERBOSE(
"Adding " << ntruth <<
" truth particles from TruthPileupEvents container");
818 const auto& links = eventPileup->truthParticleLinks();
819 for (
const auto& link : links) {
821 tempVec.push_back(*link);
836std::pair<const std::vector<const xAOD::TruthVertex*>,
const std::vector<const xAOD::TruthVertex*>>
839 std::vector<const xAOD::TruthVertex*> truthHSVertices = {};
840 truthHSVertices.reserve(5);
841 std::vector<const xAOD::TruthVertex*> truthPUVertices = {};
842 truthPUVertices.reserve(100);
865 if (truthEventContainer.
isValid()) {
866 for (
const auto *
const evt : *truthEventContainer) {
867 truthVtx = evt->signalProcessVertex();
869 truthHSVertices.push_back(truthVtx);
883 if (truthPileupEventContainer.
isValid()) {
884 for (
const auto *
const evt : *truthPileupEventContainer) {
889 size_t i_vtx = 0;
size_t n_vtx = evt->nTruthVertices();
890 while(!truthVtx && i_vtx<n_vtx){
891 truthVtx = evt->truthVertex(i_vtx);
896 truthPUVertices.push_back(truthVtx);
906 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);
917 std::vector<int>& cutFlow) {
919 if (cutFlow.empty()) {
920 names.emplace_back(
"preCut");
921 cutFlow.push_back(0);
922 for (
unsigned int i = 0; i != accept.getNCuts(); ++i) {
923 cutFlow.push_back(0);
924 names.push_back((std::string) accept.getCutName(i));
929 bool cutPositive =
true;
930 for (
unsigned int i = 0; i != (accept.getNCuts() + 1); ++i) {
934 if (accept.getCutResult(i)) {
943 double absEta = std::abs(truth.
eta());
946 ATH_MSG_INFO(
"Requesting cut value outside of configured eta range: clamping eta = "
947 << std::abs(truth.
eta()) <<
" to eta= " << absEta);
950 const auto pVal = std::lower_bound(
m_etaBins.value().begin(),
m_etaBins.value().end(), absEta);
951 const int bin = std::distance(
m_etaBins.value().begin(), pVal) - 1;
952 ATH_MSG_DEBUG(
"Checking (abs(eta)/bin) = (" << absEta <<
"," <<
bin <<
")");
958 const std::vector<const xAOD::TruthParticle*>& truthParticles,
961 float beamSpotWeight) {
966 if (truthParticles.empty()) {
967 ATH_MSG_WARNING(
"No entries in TruthParticles truth particle container. Skipping jet plots.");
968 return StatusCode::SUCCESS;
974 return StatusCode::SUCCESS;
979 for (
const xAOD::Jet *
const thisJet: *jets) {
987 isBjet = (btagLabel(*thisJet) == 5);
995 if (not el.isValid())
continue;
1004 if(!accept)
continue;
1006 bool isEfficient(
false);
1008 for (
const auto *thisTrack: tracks) {
1014 if (associatedTruth and associatedTruth == truth) {
1015 float prob = getMatchingProbability(*thisTrack);
1016 if (not std::isnan(prob) && prob >
m_lowProb) {
1023 bool truthIsFromB =
false;
1025 truthIsFromB =
true;
1027 m_monPlots->fillEfficiency(*truth, *thisJet, isEfficient, isBjet, truthIsFromB, beamSpotWeight);
1037 if (thisJet->p4().DeltaR(thisTrack->p4()) >
m_maxTrkJetDR) {
1041 float prob = getMatchingProbability(*thisTrack);
1042 if(std::isnan(prob)) prob = 0.0;
1045 const bool unlinked = (associatedTruth==
nullptr);
1046 const bool isFake = (associatedTruth && prob <
m_lowProb);
1047 bool truthIsFromB =
false;
1049 truthIsFromB =
true;
1051 m_monPlots->fill(*thisTrack, *thisJet, isBjet, isFake, unlinked, truthIsFromB, beamSpotWeight);
1052 if (associatedTruth){
1053 m_monPlots->fillFakeRate(*thisTrack, *thisJet, isFake, isBjet, truthIsFromB, beamSpotWeight);
1059 return StatusCode::SUCCESS;
1064 const float jetPt =
jet.pt();
1065 const float jetEta = std::abs(
jet.eta());
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
Helper class to provide constant type-safe access to aux data.
header file for class of same name
bool inRange(const double *boundaries, const double value, const double tolerance=0.02)
ServiceHandle< StoreGateSvc > & evtStore()
size_type size() const noexcept
Returns the number of elements in the collection.
ElementLink implementation for ROOT usage.
static void neededTrackParticleDecorations(std::vector< std::string > &decorations)
const xAOD::TruthParticle * getTruth(const xAOD::TrackParticle *const trackParticle)
Helper class to provide constant type-safe access to aux data.
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
Handle class for reading a decoration on an object.
bool isAvailable()
Test to see if this variable exists in the store, for the referenced object.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
const_pointer_type get() const
Dereference the pointer, but don't cache anything.
@ IS_SIMULATION
true: simulation, false: data
uint64_t eventNumber() const
The current event's event number.
virtual double m() const override final
The mass of the particle.
int pdgId() const
PDG ID code.
float px() const
The x component of the particle's momentum.
virtual double e() const override final
The total energy of the particle.
virtual double pt() const override final
The transverse momentum ( ) of the particle.
float py() const
The y component of the particle's momentum.
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
virtual double phi() const override final
The azimuthal angle ( ) of the particle.
virtual FourMom_t p4() const override final
The full 4-momentum of the particle.
float pz() const
The z component of the particle's momentum.
float z() const
Vertex longitudinal distance along the beam line form the origin.
float y() const
Vertex y displacement.
float x() const
Vertex x displacement.
void addReadDecoratorHandleKeys(T_Parent &parent, const SG::ReadHandleKey< T_Cont > &container_key, const std::string &prefix, const std::vector< std::string > &decor_names, std::vector< SG::ReadDecorHandleKey< T_Cont > > &decor_out)
float safelyGetEta(const T &pTrk, const float safePtThreshold=0.1)
Safely get eta.
unsigned int binIndex(const T &val, const std::vector< T > &partitions)
general utility function to return bin index given a value and the upper endpoints of each bin
HardScatterType classifyHardScatter(const xAOD::VertexContainer &vxContainer)
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
Jet_v1 Jet
Definition of the current "jet version".
EventInfo_v1 EventInfo
Definition of the latest event info version.
TruthVertex_v1 TruthVertex
Typedef to implementation.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
Vertex_v1 Vertex
Define the latest version of the vertex class.
TruthEvent_v1 TruthEvent
Typedef to implementation.
TruthParticle_v1 TruthParticle
Typedef to implementation.
TrackParticleContainer_v1 TrackParticleContainer
Definition of the current "TrackParticle container version".
JetContainer_v1 JetContainer
Definition of the current "jet container version".
implementation file for function of same name
helper struct - steer the configuration from the parent tool's side
bool doTrkInJetPlots_matched_bjets
bool doTrkInJetPlots_unlinked_bjets
bool doHitsFakeTracksPlots
int detailLevel
detail level (kept for compatibility)
bool doNtupleTruthToReco
Ntuple functionality.
bool doEfficienciesPerAuthor
per author plots
bool doMissingTruthFakePlots
bool doHitsRecoTracksPlots
bool doHitsRecoTracksPlotsPerAuthor
bool doEffPlots
Efficiency and duplicate plots - require truth, optionally matching reco.
bool doTrkInJetPlots_bjets
bool doTrkInJetPlots_matched
bool doFakePlots
Fake plots (and unlinked)
bool doResolutionPlotPrim
Resolution and "matched track" plots - filled if both reco and truth exist.
bool doTrkInJetPlots_fake_bjets
bool doVertexTruthMatchingPlots
Vertexing plots - truth requirement.
bool doVertexPlots
Vertexing plots - no truth requirement.
bool doHardScatterVertexTruthMatchingPlots
bool doTrkInJetPlots_truthFromB
bool doTrkInJetPlots_fake
bool doHitsUnlinkedTracksPlots
bool doTrackParametersPerAuthor
bool doTrkInJetPlots_unlinked
bool doTrackParameters
Plots for (selected) tracks, not necessarily truth matched.
bool doTrkInJetPlots
Plots for tracks in jets.
bool doResolutionPlotPrim_truthFromB
bool doHardScatterVertexPlots
bool doResolutionPlotSecd
bool doResolutionsPerAuthor
bool doHitsMatchedTracksPlots