ATLAS Offline Software
Loading...
Searching...
No Matches
TrackClassifier.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
8
9#include <numeric>
10
11namespace FlavorTagDiscriminants {
12TrackClassifier :: TrackClassifier (const std::string& name) : AsgTool (name)
13{
14 declareProperty( "NNModelFilepath", m_NNModelFilepath = "neural_net.json", "Trained and exported ltwnn model");
15}
16
18
19StatusCode TrackClassifier :: initialize ()
20{
21 // load the trained model
22 ATH_MSG_INFO ("Loading lwtnn model for track classification: " << m_NNModelFilepath);
23 std::string shortPathToModelFile = m_NNModelFilepath;
24 std::string fullPathToModelFile = PathResolverFindCalibFile(shortPathToModelFile);
25 std::ifstream inFileNN(fullPathToModelFile);
26 lwt::GraphConfig config(lwt::parse_json_graph(inFileNN));
27 m_lwtnn_network.reset(new lwt::LightweightGraph(config));
28 inFileNN.close();
29
30 return StatusCode::SUCCESS;
31}
32
33int TrackClassifier :: get(const xAOD::TrackParticle* track, xAOD::SummaryType info) const {
34 uint8_t val;
35 bool ok = track->summaryValue(val, info);
36 if (!ok) throw std::logic_error("problem getting track summary value");
37 return val;
38}
39
40
41double TrackClassifier :: compute_HF_Score(const xAOD::TrackParticle *track, const xAOD::Jet *jet) const
42{
43 std::map<std::string, double> track_outputs = ComputeScore( track, jet );
44 double HF_score = track_outputs["FromB"]+track_outputs["FromBC"]+track_outputs["FromC"];
45 return HF_score;
46}
47
48
49std::map<std::string, double> TrackClassifier::ComputeScore(const xAOD::TrackParticle* track, const xAOD::Jet* jet) const
50{
51 double dphi = -(jet->p4()).DeltaPhi(track->p4());
52 double deta = -(jet->eta() - track->eta());
53 double dr = (track->p4()).DeltaR(jet->p4());
54 double ptfrac = (track->pt())/(jet->pt());
55
56 static const SG::AuxElement::ConstAccessor<float> AMVFWeightPVAcc ("AMVFWeightPV");
57
58 // Build dictionary of inputs for lwtnn to use
59 // It is ok to fill this with more variables than the model uses
60 // as long as no variables are missing
61 std::map<std::string, double> track_inputs{
62 {"eta_btagJes", (double) jet->eta()},
63 {"log_pt_btagJes", (double) std::log(jet->pt())},
64 {"dphi", (double) dphi},
65 {"deta", (double) deta},
66 {"log_dr", (double) std::log(dr)},
67 {"log_ptfrac", (double) std::log(ptfrac)},
68 {"qOverP", (double) track->qOverP()},
69 {"numberOfPixelHits", (double) get(track, xAOD::numberOfPixelHits)},
70 {"numberOfSCTHits", (double) get(track, xAOD::numberOfSCTHits)},
71 {"numberOfInnermostPixelLayerHits", (double) get(track, xAOD::numberOfInnermostPixelLayerHits)},
72 {"numberOfNextToInnermostPixelLayerHits", (double) get(track, xAOD::numberOfNextToInnermostPixelLayerHits)},
73 {"numberOfInnermostPixelLayerSharedHits", (double) get(track, xAOD::numberOfInnermostPixelLayerSharedHits)},
74 {"numberOfInnermostPixelLayerSplitHits", (double) get(track, xAOD::numberOfInnermostPixelLayerSplitHits)},
75 {"numberOfPixelSharedHits", (double) get(track, xAOD::numberOfPixelSharedHits)},
76 {"numberOfPixelSplitHits", (double) get(track, xAOD::numberOfPixelSplitHits)},
77 {"numberOfSCTSharedHits", (double) get(track, xAOD::numberOfSCTSharedHits)},
78 {"numberOfPixelHoles", (double) get(track, xAOD::numberOfPixelHoles)},
79 {"numberOfSCTHoles", (double) get(track, xAOD::numberOfSCTHoles)},
80 {"AMVFWeightPV", (double) AMVFWeightPVAcc(*track)}
81 };
82
83 // Set up the nodes used for inputs
84 std::map<std::string, std::map<std::string, double> > inputs {
85 {"track_inputs", track_inputs}
86 };
87
88 // Evaluate the network
89 lwt::ValueMap discriminant = m_lwtnn_network->compute(inputs);
90
91 std::map<std::string, double> track_outputs{
92 {"Pileup",(double) discriminant["Pileup"]},
93 {"Fake",(double) discriminant["Fake"]},
94 {"Primary",(double) discriminant["Primary"]},
95 {"FromB",(double) discriminant["FromB"]},
96 {"FromBC",(double) discriminant["FromBC"]},
97 {"FromC",(double) discriminant["FromC"]},
98 {"FromTau",(double) discriminant["FromTau"]},
99 {"OtherSecondary",(double) discriminant["OtherSecondary"]}
100 };
101
102 return track_outputs;
103}
104
105
106bool TrackClassifier::pass_cut(const double score, const xAOD::Jet* jet) const
107{
108 static constexpr float const& MeVtoGeV = 1e-3;
109 double pt=jet->pt()*MeVtoGeV;
110 bool pass=false;
111
112 if(pt>=std::prev(m_WPcuts.end())->first){
113 if(score > std::prev(m_WPcuts.end())->second)
114 pass=true;
115 }
116 else{
117 for(auto it = m_WPcuts.begin(); it != std::prev(m_WPcuts.end()); ++it){
118 auto nit = std::next(it);
119 if(pt>=it->first && pt<nit->first){
120 if(score > nit->second){
121 pass=true;
122 break;
123 }
124 }
125 }
126 }
127
128 return pass;
129}
130
131
133{
134 double HF_nnScore = compute_HF_Score( track, jet );
135 return pass_cut(HF_nnScore, jet);
136}
137
138}
#define ATH_MSG_INFO(x)
Base class for elements of a container that can have aux data.
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
bool pass_cut(const double score, const xAOD::Jet *jet) const
std::unique_ptr< lwt::LightweightGraph > m_lwtnn_network
virtual bool selectTrack(const xAOD::TrackParticle *track, const xAOD::Jet *jet) const override
const std::map< double, double > m_WPcuts
virtual double compute_HF_Score(const xAOD::TrackParticle *track, const xAOD::Jet *jet) const override
int get(const xAOD::TrackParticle *part, xAOD::SummaryType info) const
virtual std::map< std::string, double > ComputeScore(const xAOD::TrackParticle *track, const xAOD::Jet *jet) const override
SG::ConstAccessor< T, ALLOC > ConstAccessor
Definition AuxElement.h:569
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
Jet_v1 Jet
Definition of the current "jet version".
TrackParticle_v1 TrackParticle
Reference the current persistent version:
SummaryType
Enumerates the different types of information stored in Summary.
@ numberOfPixelHoles
number of pixel layers on track with absence of hits [unit8_t].
@ numberOfPixelSplitHits
number of Pixel all-layer hits split by cluster splitting [unit8_t].
@ numberOfInnermostPixelLayerSharedHits
number of Pixel 0th layer barrel hits shared by several tracks.
@ numberOfNextToInnermostPixelLayerHits
these are the hits in the 1st pixel barrel layer
@ numberOfInnermostPixelLayerSplitHits
number of Pixel 0th layer barrel hits split by cluster splitting
@ numberOfSCTHits
number of hits in SCT [unit8_t].
@ numberOfInnermostPixelLayerHits
these are the hits in the 0th pixel barrel layer
@ numberOfPixelHits
these are the pixel hits, including the b-layer [unit8_t].
@ numberOfPixelSharedHits
number of Pixel all-layer hits shared by several tracks [unit8_t].
@ numberOfSCTSharedHits
number of SCT hits shared by several tracks [unit8_t].
@ numberOfSCTHoles
number of SCT holes [unit8_t].