ATLAS Offline Software
Loading...
Searching...
No Matches
RingerSelector.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Local includes:
8#include <filesystem>
9#include <algorithm>
10#include "TEnv.h"
11
12
13
14namespace Ringer{
15
16 namespace onnx{
17
18
19 //==============================================================================
20 RingerSelector::RingerSelector(const std::string& name):
21 asg::AsgMessaging(name)
22 {;}
23
24
25 //==============================================================================
26 StatusCode RingerSelector::read_from( const std::string& path , AthOnnx::IOnnxRuntimeSvc *svc )
27 {
28
29 std::string configFile = PathResolverFindCalibFile( path );
30 std::string basepath = GetBasePath( path );
31
32 ATH_MSG_INFO( "Loading all tunings configs from " << configFile );
33 ATH_MSG_INFO( "Basepath is "<< basepath);
34
35 if (configFile.empty()){
36 ATH_MSG_ERROR( "Could not locate the config file: " << configFile);
37 return StatusCode::FAILURE;
38 }
39
40 // Read configuration file
41 TEnv env(configFile.c_str());
42
43
44 // Retrieve all models
45 {
46 // Retrieve the size
47 unsigned size = env.GetValue( "Model__size" , 0 );
48 auto PreprocessingMode = GetValues<int>( "Model__barcode", env); // select the input preprocessing mode
49
50 // Retrieve Et bins
51 auto etmin = GetValues<float>( "Model__etmin", env );
52 auto etmax = GetValues<float>( "Model__etmax", env );
53
54 // Retrieve Eta bins
55 auto etamin = GetValues<float>( "Model__etamin", env );
56 auto etamax = GetValues<float>( "Model__etamax", env );
57
58 // Retreive all ONNX model file paths
59 auto model_paths = GetPaths( "Model__path", env );
60
61 // Loop over all models
62 for ( unsigned idx = 0; idx < size; ++idx )
63 {
64 std::string modelPath = PathResolverFindCalibFile( basepath+"/"+model_paths[idx] );
65 ATH_MSG_DEBUG( "Reading Onnx model from: " << modelPath );
66 auto model = Ringer::onnx::Model( modelPath, svc, etmin[idx], etmax[idx], etamin[idx], etamax[idx], PreprocessingMode[idx]) ;
67 // Compile the model
68 model.compile();
69 m_models.push_back(model);
70 }
71 }
72
73 // Retrieve all thresholds
74 {
75 // Retrieve the size
76 unsigned size = env.GetValue( "Threshold__size" , 0);
77 auto max_avgmu = GetValues<float>( "Threshold__MaxAverageMu", env );
78
79 // Retrieve Et bins
80 auto etmin = GetValues<float>( "Threshold__etmin", env );
81 auto etmax = GetValues<float>( "Threshold__etmax", env );
82 // Retrieve Eta bins
83 auto etamin = GetValues<float>( "Threshold__etamin", env );
84 auto etamax = GetValues<float>( "Threshold__etamax", env );
85 // Retrieve slopes
86 auto slopes = GetValues<float>( "Threshold__slope", env );
87 // Retrieve offsets
88 auto offsets = GetValues<float>("Threshold__offset", env );
89
90 for ( unsigned idx = 0; idx <size; ++idx ){
92 etmin[idx],
93 etmax[idx],
94 etamin[idx],
95 etamax[idx],
96 slopes[idx],
97 offsets[idx],
98 max_avgmu[idx])
99 );
100 }
101 }
102
103 return StatusCode::SUCCESS;
104 }
105
106
107
108 //==============================================================================
109 bool RingerSelector::accept( const xAOD::TrigRingerRings *ringsCluster, float discr, float avgmu ) const
110 {
111 float et = ringsCluster->emCluster()->et();
112 float eta = std::abs(ringsCluster->emCluster()->eta());
113
114 ATH_MSG_DEBUG( "Event et = "<< et << ", eta = " << eta );
115 for( auto& cutDef : m_thresholds ){
116 if ( et < cutDef.etMin()*Gaudi::Units::GeV || et >= cutDef.etMax()*Gaudi::Units::GeV ) continue;
117 if ( eta < cutDef.etaMin() || eta >= cutDef.etaMax() ) continue;
118 return cutDef.accept( discr, avgmu );
119 }// loop over all thresholds
120
121 return false;
122 }
123
124
125 //==============================================================================
126 float RingerSelector::predict(const xAOD::TrigRingerRings *ringsCluster , const xAOD::TrigElectron *el ) const
127 {
128 float et = ringsCluster->emCluster()->et();
129 float eta = std::abs(ringsCluster->emCluster()->eta());
130
131 // Find the correct model and predict
132 for( auto& model : m_models ){
133
134 if(et<model.etMin()*Gaudi::Units::GeV || et >= model.etMax()*Gaudi::Units::GeV ) continue;
135 if(eta<model.etaMin() || eta >= model.etaMax()) continue;
136 auto inputs = prepare_inputs( model.barcode(), ringsCluster, el );
137 auto output = model.predict( inputs ); // propagate the input throut the model
138 ATH_MSG_DEBUG( "The current model predict with output: " << output );
139 return output;
140 }
141
142 ATH_MSG_DEBUG("There is no model available for this cluster.");
143 return -999;
144 }
145
146
147
148 //==============================================================================
149 // PreprocessingMode = 0: use only rings normalized by total energy as input
150 // PreprocessingMode = 1: use only a half of total rings and then normalize to use as input
151 std::vector<std::vector<float>> RingerSelector::prepare_inputs( unsigned PreprocessingMode,
152 const xAOD::TrigRingerRings *ringsCluster,
153 const xAOD::TrigElectron */*el*/ ) const
154 {
155 std::vector< std::vector< float > > inputs;
156
157 // Barcode 0 for all rings normalized by the total energy
158 if ( PreprocessingMode == 0 ){
159 const std::vector<float> rings = ringsCluster->rings();
160 std::vector<float> refRings(rings.size());
161 refRings.assign(rings.begin(), rings.end());
162 float energy=0.0;
163 for(auto &ring : refRings ) energy+=ring;
164
165 if (energy > 0){
166 for(auto &ring : refRings ) ring/=energy;
167 }
168
169 inputs.push_back( refRings );
170
171 // Barcode 1 for half rings normalized by the total energy
172 }else if ( PreprocessingMode == 1){
173
174 const std::vector<float> rings = ringsCluster->rings();
175 std::vector<float> refRings(rings.size());
176 refRings.assign(rings.begin(), rings.end());
177
178 std::vector<float> halfRings;
179
180 constexpr int PS = 8;
181 constexpr int EM1 = 64;
182 constexpr int EM2 = 8;
183 constexpr int EM3 = 8;
184 constexpr int HAD1 = 4;
185 constexpr int HAD2 = 4;
186 constexpr int HAD3 = 4;
187
188 halfRings.insert(halfRings.end(), refRings.begin(), refRings.begin() + PS/2);
189 halfRings.insert(halfRings.end(), refRings.begin() + PS, refRings.begin() + PS + (EM1/2));
190 halfRings.insert(halfRings.end(), refRings.begin() + PS + EM1, refRings.begin() + PS + EM1 + (EM2/2));
191 halfRings.insert(halfRings.end(), refRings.begin() + PS + EM1 + EM2, refRings.begin() + PS + EM1 + EM2 + (EM3/2));
192 halfRings.insert(halfRings.end(), refRings.begin() + PS + EM1 + EM2 + EM3, refRings.begin() + PS + EM1 + EM2 + EM3 + (HAD1/2));
193 halfRings.insert(halfRings.end(), refRings.begin() + PS + EM1 + EM2 + EM3 + HAD1, refRings.begin() + PS + EM1 + EM2 + EM3 + HAD1 + (HAD2/2));
194 halfRings.insert(halfRings.end(), refRings.begin() + PS + EM1 + EM2 + EM3 + HAD1 + HAD2, refRings.begin() + PS + EM1 + EM2 + EM3 + HAD1 + HAD2 + (HAD3/2));
195
196 // concatenate
197 float energy=0.0;
198 for(auto &ring : halfRings ) energy+=ring;
199
200 if (energy > 0){
201 for(auto &ring : halfRings ) ring/=energy;
202 }
203
204 inputs.push_back( halfRings );
205 }
206
207 return inputs;
208 }
209
210
211
212
213
214
215 //==============================================================================
216 template <typename T> bool RingerSelector::strtof(const std::string& input, T& f)
217 {
218 int diff = 0 ;
219 std::string tmp = input;
220 std::string::size_type first(0);
221 std::string::size_type last(0);
222 first = ( input.find('#') ) ;
223
224 //if we do not find a comment character "#" we are fine
225 if (first == std::string::npos) {
226 std::istringstream buffer (tmp);
227 buffer>>f;
228 return true;
229 }
230
231 //if we have found comment character check if it is inlined between two "#"
232 last = (input.find('#',first+1) );
233 //if nor error
234 if (last == std::string::npos) {
235 return false;
236 }
237 //else if between two "#" remove this part
238 diff = last - first ;
239 tmp= tmp.erase(first,diff+1);
240 std::istringstream buffer (tmp);
241 buffer>>f;
242 return true;
243 }
244
245
246 //==============================================================================
247 template <typename T> std::vector<T> RingerSelector::GetValues (const std::string& input, TEnv& env)
248 {
249 std::vector<T> CutVector;
250 std::string env_input(env.GetValue(input.c_str(), ""));
251 if (!env_input.empty()) {
252 std::string::size_type end;
253 do {
254 end = env_input.find(';');
255 T myValue(0);
256 if(strtof(env_input.substr(0,end),myValue)){
257 CutVector.push_back(myValue);
258 }
259 if (end != std::string::npos) {
260 env_input= env_input.substr(end+1);
261 }
262 } while (end != std::string::npos);
263 }
264 return CutVector;
265 }
266
267
268 //==============================================================================
269 std::vector<std::string> RingerSelector::GetPaths(const std::string& input, TEnv& env)
270 {
271 std::vector<std::string> CutVector;
272 std::string env_input(env.GetValue(input.c_str(), ""));
273 if (!env_input.empty()) {
274 std::string::size_type end;
275 do {
276 end = env_input.find(';');
277 CutVector.push_back( env_input.substr(0,end) );
278 if (end != std::string::npos) {
279 env_input= env_input.substr(end+2);
280 }
281 } while (end != std::string::npos);
282 }
283 return CutVector;
284 }
285
286 std::string RingerSelector::GetBasePath(const std::string &path) const {
287 // Get the normalized parent path
288 std::string ret = std::filesystem::path(path).parent_path().lexically_normal().string();
289 if (!ret.empty() && ret.front()=='/') ret.erase(0, 1);
290 return ret;
291 }
292
293
294 } // namespace onnx
295} // namespace Ringer
296
297
Scalar eta() const
pseudorapidity method
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
Definition Jet.cxx:631
Service used for managing global objects used by Onnx Runtime.
std::vector< T > GetValues(const std::string &input, TEnv &env)
Get the list of values inside of tenv.
StatusCode read_from(const std::string &, AthOnnx::IOnnxRuntimeSvc *)
read tunings from configuration file
bool accept(const xAOD::TrigRingerRings *, float discr, float mu) const
Accept method.
float predict(const xAOD::TrigRingerRings *, const xAOD::TrigElectron *) const
Calculation of model output.
RingerSelector(const std::string &name)
Standard constructor.
std::vector< std::string > GetPaths(const std::string &input, TEnv &env)
Get the list of paths inside of tenv.
std::vector< Ringer::onnx::Model > m_models
hold all onnx sessions
std::vector< Ringer::onnx::Threshold > m_thresholds
hold all thresholds definitions
bool strtof(const std::string &input, T &f)
parse tenv string into list with type T
std::vector< std::vector< float > > prepare_inputs(unsigned barcode, const xAOD::TrigRingerRings *, const xAOD::TrigElectron *) const
prepare all inputs
std::string GetBasePath(const std::string &path) const
Get basepath from calib path.
AsgMessaging(const std::string &name)
Constructor with a name.
float et() const
get Et (calibrated)
float eta() const
get Eta (calibrated)
const TrigEMCluster * emCluster() const
The associated EM cluster, as a simple pointer.
const std::vector< float > & rings() const
Acessor methods.
Namespace dedicated for Ringer utilities.
TrigRingerRings_v2 TrigRingerRings
Define the latest version of the TrigRingerRings class.
TrigElectron_v1 TrigElectron
Declare the latest version of the class.
Extra patterns decribing particle interation process.