14 #include "GaudiKernel/SystemOfUnits.h"
26 declareInterface<ICaloMuonScoreTool>(
this);
43 "Please make sure it exists in the ATLAS calibration area (https://atlas-groupdata.web.cern.ch/atlas-groupdata/), and provide "
44 "a model file name relative to the root of the calibration area.");
46 return StatusCode::FAILURE;
50 Ort::SessionOptions session_options;
51 Ort::AllocatorWithDefaultOptions allocator;
52 session_options.SetIntraOpNumThreads(1);
53 session_options.SetGraphOptimizationLevel(ORT_ENABLE_BASIC);
55 m_session = std::make_unique<Ort::Session>(
m_svc->env(), model_file_name.c_str(), session_options);
57 ATH_MSG_INFO(
"Created ONNX runtime session with model " << model_file_name);
59 size_t num_input_nodes =
m_session->GetInputCount();
62 for (std::size_t
i = 0;
i < num_input_nodes;
i++) {
64 char* input_name =
m_session->GetInputNameAllocated(
i, allocator).release();
66 <<
" name= " << input_name);
69 Ort::TypeInfo type_info =
m_session->GetInputTypeInfo(
i);
70 auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
71 ONNXTensorElementDataType
type = tensor_info.GetElementType();
73 <<
" type= " <<
type);
85 std::vector<int64_t> output_node_dims;
86 size_t num_output_nodes =
m_session->GetOutputCount();
90 for (std::size_t
i = 0;
i < num_output_nodes;
i++) {
92 char* output_name =
m_session->GetOutputNameAllocated(
i, allocator).release();
94 <<
" name= " << output_name);
97 Ort::TypeInfo type_info =
m_session->GetOutputTypeInfo(
i);
98 auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
99 ONNXTensorElementDataType
type = tensor_info.GetElementType();
101 <<
" type= " <<
type);
104 output_node_dims = tensor_info.GetShape();
105 ATH_MSG_INFO(
"Output " <<
i <<
" : num_dims= " << output_node_dims.size());
106 for (std::size_t j = 0; j < output_node_dims.size(); j++) {
107 if (output_node_dims[j] < 0) output_node_dims[j] = 1;
108 ATH_MSG_INFO(
"Output" <<
i <<
" : dim " << j <<
"= " << output_node_dims[j]);
112 return StatusCode::SUCCESS;
119 std::vector<float>
out(in.size());
123 for (
unsigned int i = 1;
i <
out.size();
i++) {
135 std::vector<float> &
phi, std::vector<float> &
energy, std::vector<int> &samplingId)
const {
139 eta.push_back(cluster->eta());
140 phi.push_back(cluster->phi());
141 samplingId.push_back(cluster->caloDDE()->getSampling());
142 energy.push_back(cluster->energy());
147 ATH_MSG_DEBUG(
"Iterated over " << cell_count <<
" calo cells");
159 double track_eta = trk->
eta();
164 <<
" (eta=" << track_eta <<
")");
168 ATH_MSG_DEBUG(
"Calculating muon score for track particle with eta=" << track_eta);
173 std::unique_ptr<const Rec::ParticleCellAssociation>
association =
183 std::vector<int> sampling;
211 auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
213 Ort::Value input_tensor =
227 float *output_score_array = output_tensors.front().GetTensorMutableData<
float>();
230 float output_score = output_score_array[0];
240 switch (samplingId) {
256 if (
v.empty())
return 0.0;
258 int n =
v.size() / 2;
259 std::nth_element(
v.begin(),
v.begin() +
n,
v.end());
262 if (
v.size() % 2 == 1)
return med;
264 auto max_it = std::max_element(
v.begin(),
v.begin() +
n);
266 return (*max_it + med) / 2.0;
270 if (val < low_edge || val >= up_edge)
272 const float bin_width = (up_edge - low_edge) / (n_bins - 1);
283 std::vector<int> &sampling)
const {
284 int n_cells =
eta.size();
291 float median_phi =
getMedian(unwrappedPhi);
296 int skipped_cells = 0;
298 for (
int i = 0;
i < n_cells;
i++) {
300 float shifted_eta =
eta[
i] - median_eta;
301 float shifted_phi = unwrappedPhi[
i] - median_phi;
317 ATH_MSG_DEBUG(
"Skipping cell because sampling ID does not correspond to low-eta layers. Sampling ID: " << sampling[
i]);
324 tensor[tensor_idx] +=
energy[
i];
327 ATH_MSG_DEBUG(
"Skipped " << skipped_cells <<
" out of " << n_cells <<
" cells");