ATLAS Offline Software
Loading...
Searching...
No Matches
TrackOverlayDecisionAlg.cxx
Go to the documentation of this file.
1
5
7
8#include "GaudiKernel/SystemOfUnits.h"
12//
15
16#include <Eigen/Core>
17
19 TrackOverlayDecisionAlg::TrackOverlayDecisionAlg( const std::string& name, ISvcLocator* pSvcLocator ) :
20 ::AthReentrantAlgorithm( name, pSvcLocator )
21 {
22 }
23
25{
26 ATH_CHECK(m_filterParams.initialize(false));
27 ATH_CHECK( m_eventInfoContainerName.initialize() );
28 ATH_CHECK( m_truthParticleName.initialize( (m_pileupSwitch == "HardScatter" or m_pileupSwitch == "All") and not m_truthParticleName.key().empty() ) );
29 ATH_CHECK(m_truthSelectionTool.retrieve(EnableTool {not m_truthParticleName.key().empty()} ));
30 ATH_CHECK( m_truthEventName.initialize( (m_pileupSwitch == "HardScatter" or m_pileupSwitch == "All") and not m_truthEventName.key().empty() ) );
31 ATH_CHECK( m_truthPileUpEventName.initialize( (m_pileupSwitch == "PileUp" or m_pileupSwitch == "All") and not m_truthPileUpEventName.key().empty() ) );
32 ATH_CHECK(m_svc.retrieve());
33 std::string this_file = __FILE__;
34 const std::string model_path = PathResolverFindCalibFile("TrackOverlay/TrackOverlay_J7_model.onnx");
35 Ort::SessionOptions session_options;
36
37 m_session = std::make_unique<Ort::Session>(m_svc->env(), model_path.c_str(), session_options);
40 return StatusCode::SUCCESS;
41}
42
44{
45 ATH_MSG_VERBOSE ( "Finalizing ..." );
46 ATH_MSG_VERBOSE("-----------------------------------------------------------------");
47 ATH_MSG_VERBOSE("m_filterParams.summary()" << m_filterParams.summary());
48 ATH_MSG_VERBOSE("-----------------------------------------------------------------");
50 ATH_MSG_VERBOSE(" =====================================================================");
51
52 return StatusCode::SUCCESS;
53}
54
55const std::vector<const xAOD::TruthParticle*> TrackOverlayDecisionAlg::getTruthParticles() const {
56 std::vector<const xAOD::TruthParticle*> tempVec {};
57 if (m_pileupSwitch == "All") {
58 if (m_truthParticleName.key().empty()) {
59 return tempVec;
60 }
62 if (not truthParticleContainer.isValid()) {
63 return tempVec;
64 }
65 tempVec.insert(tempVec.begin(), truthParticleContainer->begin(), truthParticleContainer->end());
66 } else {
67 if (m_pileupSwitch == "HardScatter") {
68 if (not m_truthEventName.key().empty()) {
69 ATH_MSG_VERBOSE("Getting TruthEvents container.");
71 const xAOD::TruthEvent* event = (truthEventContainer.isValid()) ? truthEventContainer->at(0) : nullptr;
72 if (not event) {
73 return tempVec;
74 }
75 const auto& links = event->truthParticleLinks();
76 tempVec.reserve(event->nTruthParticles());
77 for (const auto& link : links) {
78 if (link.isValid()){
79 tempVec.push_back(*link);
80 }
81 }
82 }
83 }else if (m_pileupSwitch == "PileUp") {
84 if (not m_truthPileUpEventName.key().empty()) {
85 ATH_MSG_VERBOSE("getting TruthPileupEvents container");
86 // get truth particles from all pileup events
88 if (truthPileupEventContainer.isValid()) {
89 const unsigned int nPileup = truthPileupEventContainer->size();
90 tempVec.reserve(nPileup * 200); // quick initial guess, will still save some time
91 for (unsigned int i(0); i != nPileup; ++i) {
92 const auto *eventPileup = truthPileupEventContainer->at(i);
93 // get truth particles from each pileup event
94 int ntruth = eventPileup->nTruthParticles();
95 ATH_MSG_VERBOSE("Adding " << ntruth << " truth particles from TruthPileupEvents container");
96 const auto& links = eventPileup->truthParticleLinks();
97 for (const auto& link : links) {
98 if (link.isValid()){
99 tempVec.push_back(*link);
100 }
101 }
102 }
103 } else {
104 ATH_MSG_ERROR("no entries in TruthPileupEvents container!");
105 }
106 }
107 } else {
108 ATH_MSG_ERROR("bad value for PileUpSwitch");
109 }
110 }
111 return tempVec;
112}
113
114StatusCode TrackOverlayDecisionAlg::execute(const EventContext &ctx) const
115{
116 ATH_MSG_DEBUG ("Executing ...");
117
118 std::vector<const xAOD::TruthParticle*> truthParticlesVec = TrackOverlayDecisionAlg::getTruthParticles();
119
120 //Access truth info for the NN input
121 float eventPxSum = 0.0;
122 float eventPySum = 0.0;
123 float eventPt = 0.0;
124 float puEvents = 0.0;
125 std::vector<float> pxValues, pyValues, pzValues, eValues, etaValues, phiValues, ptValues;
126 float truthMultiplicity = 0.0;
127 const int truthParticles = truthParticlesVec.size();
128 bool forceMCOverlay = false;
129 for (int itruth = 0; itruth < truthParticles; itruth++) {
130 const xAOD::TruthParticle* thisTruth = truthParticlesVec[itruth];
131 if (thisTruth->pdgId() == 22 && thisTruth->status() == 1 &&
132 thisTruth->pt() * 0.001 > 25 &&
133 std::abs(thisTruth->eta()) < 2.5 &&
134 thisTruth->e() * 0.001 > 100.0 ) {
135 forceMCOverlay = true;
136 }
137 const IAthSelectionTool::CutResult accept = m_truthSelectionTool->accept(thisTruth);
138 if(accept){
139 pxValues.push_back((thisTruth->px()*0.001-1.46988000e+03)* px_diff); //as MinMaxScaler: 1.46988000e+03 is the lowest value of px from a J7 sample; *(0.001) is used to convert unit rather than *(1/1000) to speed up.
140 pyValues.push_back((thisTruth->py()*0.001-1.35142000e+03)* py_diff); //the lowest value of py: 1.35142000e+03
141 pzValues.push_back((thisTruth->pz()*0.001-1.50464000e+03)* pz_diff); //the lowest value of pz: 1.50464000e+03
142 ptValues.push_back((thisTruth->pt()*0.001-5.00006000e-01)* pt_diff); //the lowest value of pt: 5.00006000e-01
143
144 etaValues.push_back(thisTruth->eta());
145 phiValues.push_back(thisTruth->phi());
146 eValues.push_back((thisTruth->e()*0.001-5.08307000e-01)*e_diff); //the lowest value of energy: 5.08307000e-01
147
148 eventPxSum += thisTruth->px();
149 eventPySum += thisTruth->py();
150 truthMultiplicity++;
151 }//accept
152 }//for itruth
153 SG::ReadHandle<xAOD::TruthPileupEventContainer> truthPileupEventContainer;
155 if (!m_truthPileUpEventName.key().empty()) {
157 }
158 puEvents = !m_truthPileUpEventName.key().empty() and truthPileupEventContainer.isValid() ? static_cast<int>( truthPileupEventContainer->size() ) : pie.isValid() ? pie->actualInteractionsPerCrossing() : 0;
159 eventPt = std::sqrt(eventPxSum*eventPxSum + eventPySum*eventPySum)*0.001;
160
161 std::vector<float> puEventsVec(pxValues.size(), (puEvents-1.55000000e+01)*pu_diff); //min of puEvents= 15.5, max of puEvents=84.5
162 std::vector<float> truthMultiplicityVec(pxValues.size(), (truthMultiplicity-1.80000000e+01)*multi_diff);
163 std::vector<float> eventPtVec(pxValues.size(), (eventPt-3.42359395e-01)*eventPt_diff);
164 std::vector<float> predictions;
165
166 //Compute the distances using Eigen for Eigen's optimized operations. Initialize matrices. Observed a significant improvement on computing calculation.
167 Eigen::VectorXf ptEigen = Eigen::VectorXf::Map(ptValues.data(), ptValues.size());
168 Eigen::VectorXf phiEigen = Eigen::VectorXf::Map(phiValues.data(), phiValues.size());
169 Eigen::VectorXf etaEigen = Eigen::VectorXf::Map(etaValues.data(), etaValues.size());
170 for (std::size_t i = 0; i < truthMultiplicity; ++i) {
171 float multiplicity_0p05 = 0.0, multiplicity_0p2 = 0.0;
172 float sum_0p05 = 0.0, sum_0p2 = 0.0;
173 float pt_0p05 = 0.0, pt_0p2 = 0.0;
174 float deltaEtaI = etaEigen[i];
175 float phiI = phiEigen[i];
176 for (std::size_t j = 0; j < truthMultiplicity; ++j) {
177 if (i == j) continue; // Skip the particle itself
178 float deltaEta = deltaEtaI - etaEigen[j];
179 float deltaPhi = phiI - phiEigen[j];
180 if (deltaPhi > M_PI) {
181 deltaPhi -= 2.0 * M_PI;
182 }
183 else if (deltaPhi < -M_PI) {
184 deltaPhi += 2.0 * M_PI;
185 }
186 float distances = std::sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi);
187 if (distances < 0.05){
188 multiplicity_0p05++;
189 sum_0p05 += distances;
190 pt_0p05 += ptEigen[j];
191 }
192 if (distances < 0.2){
193 multiplicity_0p2++;
194 sum_0p2 += distances;
195 pt_0p2 += ptEigen[j];
196 }
197 }// for j
198
199 std::vector<float> featData;
200 featData.push_back(pxValues[i]);
201 featData.push_back(pyValues[i]);
202 featData.push_back(pzValues[i]);
203 featData.push_back(eValues[i]);
204 featData.push_back(ptValues[i]);
205 featData.push_back((multiplicity_0p2 * area0p2) * constant1);
206 featData.push_back((multiplicity_0p05 * area0p05) * constant2);
207 featData.push_back((sum_0p2 * area0p2) * constant3);
208 featData.push_back((sum_0p05 * area0p05) * constant4);
209 featData.push_back(pt_0p2 * constant5);
210 featData.push_back(pt_0p05 * constant6);
211
212 featData.push_back(puEventsVec[i]);
213 featData.push_back(truthMultiplicityVec[i]);
214 featData.push_back(eventPtVec[i]);
215
216 std::vector<int64_t> input_node_dims;
217 std::vector<char*> input_node_names;
218 input_node_dims = std::get<0>(m_inputInfo);
219 input_node_names = std::get<1>(m_inputInfo);
220
221 std::vector<int64_t> output_node_dims;
222 std::vector<char*> output_node_names;
223 output_node_dims = std::get<0>(m_outputInfo);
224 output_node_names = std::get<1>(m_outputInfo);
225
226 Ort::MemoryInfo memoryInfo = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeCPU);
227 input_node_dims[0]=1;
228 Ort::Value input_data = Ort::Value::CreateTensor(memoryInfo, featData.data(), featData.size(), input_node_dims.data(), input_node_dims.size());
229 Ort::RunOptions run_options(nullptr);
230 //Run the inference
231 Ort::Session& mysession ATLAS_THREAD_SAFE = *m_session;
232 auto output_values = mysession.Run(run_options, input_node_names.data(), &input_data, input_node_names.size(), output_node_names.data(), output_node_names.size());
233 float* predictionData = output_values[0].GetTensorMutableData<float>();
234 float prediction = predictionData[0];
235
236 predictions.push_back(prediction);
237 }//for i
238 float threshold = m_MLthreshold;
239 int badTracks = 0;
240 for (float prediction : predictions) {
241 if (prediction > threshold) {
242 badTracks++;
243 }
244 }
245 if (truthMultiplicity == 0){
246 ATH_MSG_ERROR("truthMultiplicity is zero!");
247 return StatusCode::FAILURE;
248 }
249 float rouletteScore = static_cast<float>(badTracks) / static_cast<float>(truthMultiplicity);
250
251 FilterReporter filter(m_filterParams, false, ctx);
252 bool pass = false;
253 int decision = rouletteScore == 0;
254 if (decision==0 || forceMCOverlay){ //if ML decision is False, it goes to the MC-overlay workflow
255 pass = true;
256 }
257 else{
258 pass = false;
259 }
260
261 if (m_invertfilter) {
262 pass =! pass;
263 }
264 filter.setPassed(pass);
265 ATH_MSG_ALWAYS("End TrackOverlayDecisionAlg, difference in filters: "<<(pass ? "found" : "not found")<<"="<<pass<<", invert="<<m_invertfilter);
266 return StatusCode::SUCCESS;
267}
268
269
270}// end namespace TrackOverlayDecisionAlg
#define M_PI
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_ALWAYS(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_INFO(x,...)
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Handle class for reading from StoreGate.
#define ATLAS_THREAD_SAFE
An algorithm that can be simultaneously executed in multiple threads.
a guard class for use with ref FilterReporterParams
virtual bool isValid() override final
Can the handle be successfully dereferenced?
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoContainerName
std::tuple< std::vector< int64_t >, std::vector< char * > > GetInputNodeInfo(const std::unique_ptr< Ort::Session > &session)
Gaudi::Property< bool > m_invertfilter
invert filter decision at the end
virtual StatusCode execute(const EventContext &ctx) const override final
Athena algorithm's interface method execute().
std::tuple< std::vector< int64_t >, std::vector< char * > > m_outputInfo
SG::ReadHandleKey< xAOD::TruthEventContainer > m_truthEventName
std::tuple< std::vector< int64_t >, std::vector< char * > > GetOutputNodeInfo(const std::unique_ptr< Ort::Session > &session)
std::tuple< std::vector< int64_t >, std::vector< char * > > m_inputInfo
virtual StatusCode finalize() override final
Athena algorithm's interface method finalize().
TrackOverlayDecisionAlg(const std::string &name, ISvcLocator *pSvcLocator)
Constructor with parameters.
virtual StatusCode initialize() override final
Athena algorithm's interface method initialize().
const std::vector< const xAOD::TruthParticle * > getTruthParticles() const
SG::ReadHandleKey< xAOD::TruthParticleContainer > m_truthParticleName
SG::ReadHandleKey< xAOD::TruthPileupEventContainer > m_truthPileUpEventName
ServiceHandle< AthOnnx::IOnnxRuntimeSvc > m_svc
int status() const
Status code.
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.
float pz() const
The z component of the particle's momentum.
Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration.
TruthEvent_v1 TruthEvent
Typedef to implementation.
Definition TruthEvent.h:17
TruthParticle_v1 TruthParticle
Typedef to implementation.