1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
/*
* OnlineDQMDigiAD_cmssw.cpp
*
* Created on: Jun 10, 2023
* Author: Mulugeta W.Asres, UiA, Norway
*
* The implementation follows https://github.com/cms-sw/cmssw/tree/master/PhysicsTools/ONNXRuntime
*/
#ifndef OnlineDQMDigiAD_cmssw_H_
#define OnlineDQMDigiAD_cmssw_H_
#include "PhysicsTools/ONNXRuntime/interface/ONNXRuntime.h"
#include "FWCore/Utilities/interface/Exception.h"
#include "FWCore/Utilities/interface/thread_safety_macros.h"
#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
#include <memory>
#include <numeric>
// Declare OnlineDQMDigiAD class
class OnlineDQMDigiAD {
public:
/**
* @brief Constructor
* @param modelFilepath: path to the .onnx file
* @param Backend: backend selection cpu or gpu
*/
OnlineDQMDigiAD(const std::string model_system_name,
const std::string &modelFilepath,
cms::Ort::Backend backend = cms::Ort::Backend::cpu);
/**
* @brief check whether onnx model integration is added for the selected hcal system
*/
void IsModelExist(std::string hcal_subsystem_name);
/**
* @brief Resets ml model memory states to default and function needs to be called when new collision run starts
*/
void InitializeState();
/**
* @brief Perform inference on a single image
* @param digiHcalMapTW: The input digipccupany maps in time window
* @param numEvents: The input number of events for map renormalization in time window
* @param adThr: The anomaly detection decision threshold
* @param input_model_state_memory_: The model memory states
* @param output_tensors: output arrays
* @return the list of multidimensional arrays
*/
std::vector<std::vector<float>> Inference(std::vector<float> &digiHcalMapTW,
std::vector<float> &numEvents,
std::vector<float> &adThr,
std::vector<float> &input_model_state_memory_e_0_0,
std::vector<float> &input_model_state_memory_e_0_1,
std::vector<float> &input_model_state_memory_e_1_0,
std::vector<float> &input_model_state_memory_e_1_1,
std::vector<float> &input_model_state_memory_d_0_0,
std::vector<float> &input_model_state_memory_d_0_1,
std::vector<float> &input_model_state_memory_d_1_0,
std::vector<float> &input_model_state_memory_d_1_1);
/**
* @brief Perform inference on a single image
* @param digiHcal2DHist_depth_1: 2D histogram digioccupancy of the 1st depth of the hcal-hehb
* @param digiHcal2DHist_depth_2: 2D histogram digioccupancy of the 2nd depth of the hcal-hehb
* @param digiHcal2DHist_depth_3: 2D histogram digioccupancy of the 3rd depth of the hcal-hehb
* @param digiHcal2DHist_depth_4: 2D histogram digioccupancy of the 4th depth of the hcal-hehb
* @param digiHcal2DHist_depth_5: 2D histogram digioccupancy of the 5th depth of the hcal-hehb
* @param digiHcal2DHist_depth_5: 2D histogram digioccupancy of the 6th depth of the hcal-hehb
* @param digiHcal2DHist_depth_7: 2D histogram digioccupancy of the 7th depth of the hcal-hehb
* @param LS_numEvents: The input number of events for digioccupancy map renormalization
* @param flagDecisionThr: The anomaly detection decision threshold, decrease to increase sensitivity
* @return ad_model_output_vectors: the vectors of multidimensional arrays: output_data_0, output_data_1, ...
*/
std::vector<std::vector<float>> Inference_CMSSW(const std::vector<std::vector<float>> &digiHcal2DHist_depth_1,
const std::vector<std::vector<float>> &digiHcal2DHist_depth_2,
const std::vector<std::vector<float>> &digiHcal2DHist_depth_3,
const std::vector<std::vector<float>> &digiHcal2DHist_depth_4,
const std::vector<std::vector<float>> &digiHcal2DHist_depth_5,
const std::vector<std::vector<float>> &digiHcal2DHist_depth_6,
const std::vector<std::vector<float>> &digiHcal2DHist_depth_7,
const float LS_numEvents,
const float flagDecisionThr = 20);
/**
@brief Converts 1D serialized vector output of the onnx into 3d hcal-hehp vector
@param ad_model_output_vectors: vector of 3D histogram maps the hcal-hehb, each vector output from the onnx. e.g 3d map of anomaly score and 3d map of anomaly flag or label
@param selOutputIdx: index to select of the onnx output. e.g. 5 is the anomaly score and 7 is the anomaly flag (1 is with anomaly, 0 is healthy)
@return ad_model_output_vectors: the vectors of multidimensional arrays: output_data_0, output_data_1, ...
*/
std::vector<std::vector<std::vector<float>>> ONNXOutputToDQMHistMap(
const std::vector<std::vector<float>> &ad_model_output_vectors,
const int numDepth,
const int numDIeta = 64,
const int selOutputIdx = 7);
private:
// onnx session
const std::vector<std::string> hcal_modeled_systems = {"he", "hb"};
std::string hcal_subsystem_name;
std::unique_ptr<cms::Ort::ONNXRuntime> ort_mSession = nullptr;
std::string model_path; // onnx model path
// names of onnx model input vectors; do not change
const std::vector<std::string> input_names = {
"input_data",
"input_data_exo",
"anomaly_std_th",
"e_rnn_hidden__layer_0_state_0",
"e_rnn_hidden__layer_0_state_1",
"e_rnn_hidden__layer_1_state_0",
"e_rnn_hidden__layer_1_state_1",
"d_rnn_hidden__layer_0_state_0",
"d_rnn_hidden__layer_0_state_1",
"d_rnn_hidden__layer_1_state_0",
"d_rnn_hidden__layer_1_state_1",
};
// names of onnx model outputs vectors; do not change
const std::vector<std::string> output_names = {
"target_data",
"pred_data",
"pred_err_spatial",
"pred_err_window_spatial",
"pred_err_spatial_scaled",
"pred_err_window_spatial_scaled",
"pred_err_spatial_scaled_aml",
"pred_err_window_spatial_scaled_aml",
"e_rnn_hidden__layer_0_state_0_o",
"e_rnn_hidden__layer_0_state_1_o",
"e_rnn_hidden__layer_1_state_0_o",
"e_rnn_hidden__layer_1_state_1_o",
"d_rnn_hidden__layer_0_state_0_o",
"d_rnn_hidden__layer_0_state_1_o",
"d_rnn_hidden__layer_1_state_0_o",
"d_rnn_hidden__layer_1_state_1_o",
};
// model state network config declaration : encoder and decoder have each two lstm layers(each hold two state vectors, h0, c0)
const size_t num_state_vectors = 8;
const unsigned int model_state_inner_dim = 2; // do not change
const std::vector<std::vector<unsigned int>> model_state_layer_dims = {
{128, 32}, {128, 640}}; // do not change, encoder[layer_0, layer_1] and decoder [layer_0, layer_1]
const std::vector<std::vector<unsigned int>> model_state_layer_serialized_dims = {
{256, 64},
{256,
1280}}; // do not change, model_state_inner_dim*encoder[layer_0, layer_1] and model_state_inner_dim*decoder [layer_0, layer_1]
// unsigned model_state_refresh_counter = 15; // do not change for now. set due to onnx double datatype handling limitation that might cause precision error to propagate.
unsigned model_state_refresh_counter =
1; // DQM multithread returns non-sequential LS. Hence, the model will not keep states (experimental)
std::vector<float> input_model_state_memory_e_0_0{std::vector<float>(model_state_layer_serialized_dims[0][0])};
std::vector<float> input_model_state_memory_e_0_1{std::vector<float>(model_state_layer_serialized_dims[0][0])};
std::vector<float> input_model_state_memory_e_1_0{std::vector<float>(model_state_layer_serialized_dims[0][1])};
std::vector<float> input_model_state_memory_e_1_1{std::vector<float>(model_state_layer_serialized_dims[0][1])};
std::vector<float> input_model_state_memory_d_0_0{std::vector<float>(model_state_layer_serialized_dims[1][0])};
std::vector<float> input_model_state_memory_d_0_1{std::vector<float>(model_state_layer_serialized_dims[1][0])};
std::vector<float> input_model_state_memory_d_1_0{std::vector<float>(model_state_layer_serialized_dims[1][1])};
std::vector<float> input_model_state_memory_d_1_1{std::vector<float>(model_state_layer_serialized_dims[1][1])};
// input and outputs
int64_t batch_size = 1; // number maps to be evaluated at once, a single time-window
std::vector<std::vector<float>> input_values, output_values;
std::vector<std::vector<int64_t>> input_shapes;
/**
* @brief Serializes 2d vectors into 1d
*/
std::vector<float> Serialize2DVector(const std::vector<std::vector<float>> &input_2d_vec);
/**
* @brief Converts serialized 1d vectors into 2d
*/
std::vector<std::vector<float>> Map1DTo2DVector(const std::vector<float> &input_1d_vec, const int numSplits);
/**
* @brief Prepares model input serialized dqm histogram from 2D histogram inputs from the cmssw
* @param digiHcal2DHist_depth_all: 3D vector (depth[ieta[iphi]]) of combined 2D histogram digioccupancy of the any depth of the hcal
*/
std::vector<float> PrepareONNXDQMMapVectors(std::vector<std::vector<std::vector<float>>> &digiHcal2DHist_depth_all);
};
#endif // OnlineDQMDigiAD_cmssw_H_
|