ATLAS Offline Software
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 
14 namespace Ringer{
15 
16  namespace onnx{
17 
18 
19  //==============================================================================
20  RingerSelector::RingerSelector(const std::string& name):
21  asg::AsgMessaging(name)
22  {;}
23 
24 
25  //==============================================================================
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 
AthOnnx::IOnnxRuntimeSvc
Service used for managing global objects used by Onnx Runtime.
Definition: IOnnxRuntimeSvc.h:25
xAOD::TrigElectron_v1
Class describing an electron reconstructed in the HLT.
Definition: TrigElectron_v1.h:39
python.CaloRecoConfig.f
f
Definition: CaloRecoConfig.py:127
et
Extra patterns decribing particle interation process.
Ringer::HAD2
@ HAD2
Definition: CaloRingsDefs.h:51
xAOD::TrigEMCluster_v1::eta
float eta() const
get Eta (calibrated)
taskman.configFile
configFile
Definition: taskman.py:311
athena.path
path
python interpreter configuration --------------------------------------—
Definition: athena.py:126
Ringer::EM3
@ EM3
Definition: CaloRingsDefs.h:49
Ringer::onnx::RingerSelector::m_thresholds
std::vector< Ringer::onnx::Threshold > m_thresholds
hold all thresholds definitions
Definition: RingerSelector.h:68
Ringer::HAD3
@ HAD3
Definition: CaloRingsDefs.h:52
Ringer::HAD1
@ HAD1
Definition: CaloRingsDefs.h:50
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
xAOD::TrigRingerRings_v2::emCluster
const TrigEMCluster * emCluster() const
The associated EM cluster, as a simple pointer.
Definition: TrigRingerRings_v2.cxx:41
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:79
RingerSelector.h
Ringer::EM2
@ EM2
Definition: CaloRingsDefs.h:48
xAOD::TrigRingerRings_v2::rings
const std::vector< float > & rings() const
Acessor methods.
asg
Definition: DataHandleTestTool.h:28
mc.diff
diff
Definition: mc.SFGenPy8_MuMu_DD.py:14
Ringer::onnx::RingerSelector::predict
float predict(const xAOD::TrigRingerRings *, const xAOD::TrigElectron *) const
Calculation of model output.
Definition: RingerSelector.cxx:126
Ringer::onnx::RingerSelector::GetBasePath
std::string GetBasePath(const std::string &path) const
Get basepath from calib path.
Definition: RingerSelector.cxx:286
Ringer::onnx::RingerSelector::strtof
bool strtof(const std::string &input, T &f)
parse tenv string into list with type T
Definition: RingerSelector.cxx:216
postInclude.inputs
inputs
Definition: postInclude.SortInput.py:15
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
Ringer::PS
@ PS
Definition: CaloRingsDefs.h:46
createCoolChannelIdFile.buffer
buffer
Definition: createCoolChannelIdFile.py:12
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
ParticleGun_FastCalo_ChargeFlip_Config.energy
energy
Definition: ParticleGun_FastCalo_ChargeFlip_Config.py:78
Ringer::onnx::RingerSelector::GetValues
std::vector< T > GetValues(const std::string &input, TEnv &env)
Get the list of values inside of tenv.
Definition: RingerSelector.cxx:247
Ringer::onnx::RingerSelector::accept
bool accept(const xAOD::TrigRingerRings *, float discr, float mu) const
Accept method.
Definition: RingerSelector.cxx:109
ret
T ret(T t)
Definition: rootspy.cxx:260
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Epos_Base_Fragment.Model
Model
Definition: Epos_Base_Fragment.py:10
PlotPulseshapeFromCool.input
input
Definition: PlotPulseshapeFromCool.py:106
plotIsoValidation.el
el
Definition: plotIsoValidation.py:197
Handler::svc
AthROOTErrorHandlerSvc * svc
Definition: AthROOTErrorHandlerSvc.cxx:10
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
Ringer::onnx::Threshold
Definition: Threshold.h:14
beamspotman.basepath
string basepath
Definition: beamspotman.py:1018
merge.output
output
Definition: merge.py:17
Ringer::onnx::RingerSelector::read_from
StatusCode read_from(const std::string &, AthOnnx::IOnnxRuntimeSvc *)
read tunings from configuration file
Definition: RingerSelector.cxx:26
PathResolver.h
Ringer::onnx::RingerSelector::RingerSelector
RingerSelector(const std::string &name)
Standard constructor.
Definition: RingerSelector.cxx:20
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
Ringer::onnx::RingerSelector::GetPaths
std::vector< std::string > GetPaths(const std::string &input, TEnv &env)
Get the list of paths inside of tenv.
Definition: RingerSelector.cxx:269
xAOD::TrigRingerRings_v2
Definition: TrigRingerRings_v2.h:24
PathResolverFindCalibFile
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Definition: PathResolver.cxx:431
Ringer::onnx::RingerSelector::m_models
std::vector< Ringer::onnx::Model > m_models
hold all onnx sessions
Definition: RingerSelector.h:66
correlationModel::model
model
Definition: AsgElectronEfficiencyCorrectionTool.cxx:46
DeMoScan.first
bool first
Definition: DeMoScan.py:534
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
xAOD::TrigEMCluster_v1::et
float et() const
get Et (calibrated)
Ringer::onnx::RingerSelector::prepare_inputs
std::vector< std::vector< float > > prepare_inputs(unsigned barcode, const xAOD::TrigRingerRings *, const xAOD::TrigElectron *) const
prepare all inputs
Definition: RingerSelector.cxx:151
python.DataFormatRates.env
env
Definition: DataFormatRates.py:32
LArCellBinning.etamin
etamin
Definition: LArCellBinning.py:137
Ringer::EM1
@ EM1
Definition: CaloRingsDefs.h:47
GeV
#define GeV
Definition: CaloTransverseBalanceVecMon.cxx:30
Ringer
Namespace dedicated for Ringer utilities.
Definition: CaloRingsDefs.h:9