CMS 3D CMS Logo

MLClient.cc
Go to the documentation of this file.
2 
4 
6 
8 
10 
12 
13 #include <fstream>
14 
15 using namespace cms::Ort;
16 
17 namespace ecaldqm {
18  MLClient::MLClient() : DQWorkerClient() { qualitySummaries_.insert("MLQualitySummary"); }
19 
21  EBThreshold_ = _params.getUntrackedParameter<double>("EBThreshold");
22  EEpThreshold_ = _params.getUntrackedParameter<double>("EEpThreshold");
23  EEmThreshold_ = _params.getUntrackedParameter<double>("EEmThreshold");
24  EB_PUcorr_slope_ = _params.getUntrackedParameter<double>("EB_PUcorr_slope");
25  EB_PUcorr_intercept_ = _params.getUntrackedParameter<double>("EB_PUcorr_intercept");
26  EEp_PUcorr_slope_ = _params.getUntrackedParameter<double>("EEp_PUcorr_slope");
27  EEp_PUcorr_intercept_ = _params.getUntrackedParameter<double>("EEp_PUcorr_intercept");
28  EEm_PUcorr_slope_ = _params.getUntrackedParameter<double>("EEm_PUcorr_slope");
29  EEm_PUcorr_intercept_ = _params.getUntrackedParameter<double>("EEm_PUcorr_intercept");
30 
31  if (!onlineMode_) {
32  MEs_.erase(std::string("MLQualitySummary"));
33  MEs_.erase(std::string("EventsperMLImage"));
34  sources_.erase(std::string("PU"));
35  sources_.erase(std::string("NumEvents"));
36  sources_.erase(std::string("DigiAllByLumi"));
37  sources_.erase(std::string("AELoss"));
38  sources_.erase(std::string("BadTowerCount"));
39  sources_.erase(std::string("BadTowerCountNorm"));
40  }
41  }
42 
44  if (!onlineMode_)
45  return;
46  nbadtowerEB = 0;
47  nbadtowerEE = 0;
48 
49  using namespace std;
50  MESet& meMLQualitySummary(MEs_.at("MLQualitySummary"));
51  MESet& meEventsperMLImage(MEs_.at("EventsperMLImage"));
52 
53  MESetNonObject const& sPU(static_cast<MESetNonObject&>(sources_.at("PU")));
54  MESetNonObject const& sNumEvents(static_cast<MESetNonObject&>(sources_.at("NumEvents")));
55 
56  //Get the no.of events and the PU per LS calculated in OccupancyTask
57  int nEv = sNumEvents.getFloatValue();
58  double pu = sPU.getFloatValue();
59 
60  //Do not compute ML quality if PU is non existent.
61  if (pu <= 0.) {
62  return;
63  }
67 
69  //Inorder to feed the data into the ML model we apply some preprocessing.
70  //We use the Digi Occupancy per Lumisection as the input source.
71  //The model was trained on each occupancy plot having 500 events.
72  //In apprehension of the low luminosity in the beginning of Run3, where in online DQM
73  //the no.of events per LS could be lower than 500, we sum the occupancies over a fixed no.of lumisections as a running sum,
74  //and require that the total no.of events on this summed occupancy to be atleast 200.
75  //(This no.of LS and the no.of events are parameters which would require tuning later)
76  //This summed occupancy is now the input image, which is then corrected for PileUp(PU) dependence and
77  //change in no.of events, which are derived from training.
78  //The input image is also padded by replicating the top and bottom rows so as to prevent the "edge effect"
79  //wherein the ML model's learning degrades near the edge of the data set it sees.
80  //This padding is then removed during inference on the model output.
81 
82  //Get the histogram of the input digi occupancy per lumisection.
83  TH2F* hEEmDigiMap((sources_.at("DigiAllByLumi")).getME(0)->getTH2F());
84  TH2F* hEbDigiMap((sources_.at("DigiAllByLumi")).getME(1)->getTH2F());
85  TH2F* hEEpDigiMap((sources_.at("DigiAllByLumi")).getME(2)->getTH2F());
86 
87  size_t nEBTowers = nEBEtaTowers * nEBPhiTowers; //Each EB occupancy map is of size 34x72 towers
88  size_t nEETowers = nEEEtaTowers * nEEPhiTowers; //Each EE occupancy map is of size 20x20 towers
89 
90  //Vectors to feed into the ML network
91  std::vector<float> ebOccMap1dCumulPad;
92  std::vector<float> eemOccMap1dCumulPad;
93  std::vector<float> eepOccMap1dCumulPad;
94 
95  //Array to store occupancy maps
96  std::valarray<float> ebOccMap1d(nEBTowers);
97  std::valarray<float> eemOccMap1d(nEETowers);
98  std::valarray<float> eepOccMap1d(nEETowers);
99 
100  //Store the values from the input histogram into the array
101  //to do preprocessing
102  for (int i = 0; i < hEbDigiMap->GetNbinsY(); i++) { //NbinsY = 34, NbinsX = 72
103  for (int j = 0; j < hEbDigiMap->GetNbinsX(); j++) {
104  int bin = hEbDigiMap->GetBin(j + 1, i + 1);
105  int k = (i * nEBPhiTowers) + j;
106  ebOccMap1d[k] = hEbDigiMap->GetBinContent(bin);
107  }
108  }
109  ebOccMap1dQ.push_back(ebOccMap1d); //Queue which stores input occupancy maps for nLS lumis
110 
111  for (int i = 0; i < hEEpDigiMap->GetNbinsY(); i++) { //NbinsY = 20, NbinsX = 20
112  for (int j = 0; j < hEEpDigiMap->GetNbinsX(); j++) {
113  int bin = hEEpDigiMap->GetBin(j + 1, i + 1);
114  int k = (i * nEEPhiTowers) + j;
115  eemOccMap1d[k] = hEEmDigiMap->GetBinContent(bin);
116  eepOccMap1d[k] = hEEpDigiMap->GetBinContent(bin);
117  }
118  }
119 
120  //Queue which stores input occupancy maps for nLS lumis
121  eemOccMap1dQ.push_back(eemOccMap1d);
122  eepOccMap1dQ.push_back(eepOccMap1d);
123 
124  NEventQ.push_back(nEv); //Queue which stores the no.of events per LS for nLS lumis
125 
126  if (NEventQ.size() < nLS) {
127  return; //Should have nLS lumis to add the occupancy over.
128  }
129  if (NEventQ.size() > nLS) {
130  NEventQ.pop_front(); //Keep only nLS consecutive LS. Pop the first one if size greater than nLS
131  }
132  if (ebOccMap1dQ.size() > nLS) {
133  ebOccMap1dQ.pop_front(); //Same conditon for the input occupancy maps.
134  eemOccMap1dQ.pop_front();
135  eepOccMap1dQ.pop_front();
136  }
137 
138  int TNum = 0;
139  for (size_t i = 0; i < nLS; i++) {
140  TNum += NEventQ[i]; //Total no.of events over nLS lumis
141  }
142 
143  if (TNum < 400) {
144  return; //The total no.of events should be atleast 400 over nLS for meaningful statistics
145  }
146  //Fill the ME to monitor the trend of the total no.of events in each input image to the ML model
147  meEventsperMLImage.fill(getEcalDQMSetupObjects(), EcalBarrel, double(timestamp_.iLumi), double(TNum));
148 
149  //Array to hold the sum of inputs, which make atleast 400 events.
150  std::valarray<float> ebOccMap1dCumul(0., nEBTowers);
151  std::valarray<float> eemOccMap1dCumul(0., nEETowers);
152  std::valarray<float> eepOccMap1dCumul(0., nEETowers);
153 
154  //Sum the input arrays of nLS.
155  for (size_t i = 0; i < ebOccMap1dQ.size(); i++) {
156  ebOccMap1dCumul += ebOccMap1dQ[i];
157  eemOccMap1dCumul += eemOccMap1dQ[i];
158  eepOccMap1dCumul += eepOccMap1dQ[i];
159  }
160 
161  //Applying PU correction derived from training
162  ebOccMap1dCumul = ebOccMap1dCumul / (EB_PUcorr_slope_ * pu + EB_PUcorr_intercept_);
163  eemOccMap1dCumul = eemOccMap1dCumul / (EEm_PUcorr_slope_ * pu + EEm_PUcorr_intercept_);
164  eepOccMap1dCumul = eepOccMap1dCumul / (EEp_PUcorr_slope_ * pu + EEp_PUcorr_intercept_);
165 
166  //Scaling up to match input dimensions.
167  ebOccMap1dCumul = ebOccMap1dCumul * (nEBEtaTowers * nEBPhiTowers);
168  eemOccMap1dCumul = eemOccMap1dCumul * nEEEtaTowers * nEEPhiTowers; //(nEETowersPad * nEETowersPad);
169  eepOccMap1dCumul = eepOccMap1dCumul * nEEEtaTowers * nEEPhiTowers; //(nEETowersPad * nEETowersPad);
170 
171  //Correction for no.of events in each input image as originally model trained with 500 events per image
172  ebOccMap1dCumul = ebOccMap1dCumul * (500. / TNum);
173  eemOccMap1dCumul = eemOccMap1dCumul * (500. / TNum);
174  eepOccMap1dCumul = eepOccMap1dCumul * (500. / TNum);
175 
176  std::vector<std::vector<float>> ebOccMap2dCumul(nEBEtaTowers, std::vector<float>(nEBPhiTowers, 0.));
177  //Convert 1dCumul to 2d
178  for (size_t i = 0; i < nEBEtaTowers; i++) {
179  for (size_t j = 0; j < nEBPhiTowers; j++) {
180  int k = (i * nEBPhiTowers) + j;
181  ebOccMap2dCumul[i][j] = ebOccMap1dCumul[k];
182  }
183  }
184 
185  std::vector<float> pad_top;
186  std::vector<float> pad_bottom;
187  std::vector<float> pad_left;
188  std::vector<float> pad_right;
189 
190  pad_top = ebOccMap2dCumul[0];
191  pad_bottom = ebOccMap2dCumul[ebOccMap2dCumul.size() - 1];
192 
193  ebOccMap2dCumul.insert(ebOccMap2dCumul.begin(), pad_top);
194  ebOccMap2dCumul.push_back(pad_bottom);
195 
197  std::vector<std::vector<float>> eemOccMap2dCumul(nEEEtaTowers, std::vector<float>(nEEPhiTowers, 0.));
198  std::vector<std::vector<float>> eepOccMap2dCumul(nEEEtaTowers, std::vector<float>(nEEPhiTowers, 0.));
199 
200  for (size_t i = 0; i < nEEEtaTowers; i++) {
201  for (size_t j = 0; j < nEEPhiTowers; j++) {
202  int k = (i * nEEPhiTowers) + j;
203  eemOccMap2dCumul[i][j] = eemOccMap1dCumul[k];
204  eepOccMap2dCumul[i][j] = eepOccMap1dCumul[k];
205  }
206  }
207 
208  // EE - //
209  pad_top.clear();
210  pad_bottom.clear();
211  pad_left.clear();
212  pad_right.clear();
213 
214  pad_top = eemOccMap2dCumul[0];
215  pad_bottom = eemOccMap2dCumul[eemOccMap2dCumul.size() - 1];
216 
217  eemOccMap2dCumul.insert(eemOccMap2dCumul.begin(), pad_top);
218  eemOccMap2dCumul.push_back(pad_bottom);
219 
220  for (auto& row : eemOccMap2dCumul) {
221  pad_left.push_back(row[0]);
222  pad_right.push_back(row[row.size() - 1]);
223  }
224 
225  std::size_t Lindex = 0;
226  std::size_t Rindex = 0;
227 
228  for (auto& row : eemOccMap2dCumul) {
229  row.insert(row.begin(), pad_left[Lindex++]);
230  row.insert(row.end(), pad_right[Rindex++]);
231  }
232 
233  // EE + //
234  pad_top.clear();
235  pad_bottom.clear();
236 
237  pad_top = eepOccMap2dCumul[0];
238  pad_bottom = eepOccMap2dCumul[eepOccMap2dCumul.size() - 1];
239 
240  eepOccMap2dCumul.insert(eepOccMap2dCumul.begin(), pad_top);
241  eepOccMap2dCumul.push_back(pad_bottom);
242 
243  for (auto& row : eepOccMap2dCumul) {
244  pad_left.push_back(row[0]);
245  pad_right.push_back(row[row.size() - 1]);
246  }
247 
248  Lindex = 0;
249  Rindex = 0;
250 
251  for (auto& row : eepOccMap2dCumul) {
252  row.insert(row.begin(), pad_left[Lindex++]);
253  row.insert(row.end(), pad_right[Rindex++]);
254  }
255 
256  //The pre-processed input is now fed into the 1D input tensor vector which will go into the ML model
257  for (auto& row : ebOccMap2dCumul) {
258  ebOccMap1dCumulPad.insert(ebOccMap1dCumulPad.end(), row.begin(), row.end());
259  }
260 
261  for (auto& row : eemOccMap2dCumul) {
262  eemOccMap1dCumulPad.insert(eemOccMap1dCumulPad.end(), row.begin(), row.end());
263  }
264 
265  for (auto& row : eepOccMap2dCumul) {
266  eepOccMap1dCumulPad.insert(eepOccMap1dCumulPad.end(), row.begin(), row.end());
267  }
268 
270  //An Autoencoder (AE) network with resnet architecture is used here which is trained on
271  //certified good data (EB digi occupancy) from Run 2018 data.
272  //On giving an input occupancy map, the encoder part of the AE compresses and reduces the input data, learning its features,
273  //and the decoder reconstructs the data from the encoded form into a representation as close to the original input as possible.
274  //We then compute the Mean squared error (MSE) between the input and output image, also called the Reconstruction Loss,
275  //calculated at a tower by tower basis.
276  //Thus, given an anomalous tower the loss should be significantly higher than the loss with respect to good towers, which the model
277  //has already seen --> anomaly detection.
278  //When calculating the loss we also apply a response correction by dividing each input and output image with the average occupancy from
279  //all 2018 data (also to be tuned),to accommodate the difference in response of crystals in different regions of the Ecal Barrel
280  //Further each loss map from each input image is then multiplied by the last N loss maps,
282  //A quality threshold is then applied on this time multiplied loss map, to mark them as GOOD or BAD,
283  //after which it is stored as a quality summary ME.
284 
286  std::string instanceName{"AE-DQM-inference"};
287  std::string modelFilepath = edm::FileInPath("DQM/EcalMonitorClient/data/onnxModels/resnet.onnx").fullPath();
288 
289  Ort::SessionOptions sessionOptions;
290  sessionOptions.SetIntraOpNumThreads(1);
291  Ort::Env env(OrtLoggingLevel::ORT_LOGGING_LEVEL_WARNING, instanceName.c_str());
292  Ort::Session session(env, modelFilepath.c_str(), sessionOptions);
293 
294  Ort::AllocatorWithDefaultOptions allocator;
295 
296  const char* inputName = session.GetInputName(0, allocator);
297 
298  Ort::TypeInfo inputTypeInfo = session.GetInputTypeInfo(0);
299  auto inputTensorInfo = inputTypeInfo.GetTensorTypeAndShapeInfo();
300 
301  std::vector<int64_t> inputDims = inputTensorInfo.GetShape();
302 
303  const char* outputName = session.GetOutputName(0, allocator);
304 
305  Ort::TypeInfo outputTypeInfo = session.GetOutputTypeInfo(0);
306  auto outputTensorInfo = outputTypeInfo.GetTensorTypeAndShapeInfo();
307 
308  std::vector<int64_t> outputDims = outputTensorInfo.GetShape();
309 
310  size_t TensorSize = nEBEtaTowersPad * nEBPhiTowers;
311  std::vector<float> ebRecoOccMap1dPad(TensorSize); //To store the output reconstructed occupancy
312 
313  std::vector<const char*> inputNames{inputName};
314  std::vector<const char*> outputNames{outputName};
315  std::vector<Ort::Value> inputTensors;
316  std::vector<Ort::Value> outputTensors;
317 
318  Ort::MemoryInfo memoryInfo =
319  Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault);
320  inputTensors.push_back(Ort::Value::CreateTensor<float>(
321  memoryInfo, ebOccMap1dCumulPad.data(), TensorSize, inputDims.data(), inputDims.size()));
322 
323  outputTensors.push_back(Ort::Value::CreateTensor<float>(
324  memoryInfo, ebRecoOccMap1dPad.data(), TensorSize, outputDims.data(), outputDims.size()));
325 
326  session.Run(Ort::RunOptions{nullptr},
327  inputNames.data(),
328  inputTensors.data(),
329  1,
330  outputNames.data(),
331  outputTensors.data(),
332  1);
333 
334  //Endcaps
335  // EE- //
336 
337  inputDims.clear();
338  outputDims.clear();
339  inputNames.clear();
340  outputNames.clear();
341  inputTensors.clear();
342  outputTensors.clear();
343 
344  modelFilepath = edm::FileInPath("DQM/EcalMonitorClient/data/onnxModels/EEm_resnet2018.onnx").fullPath();
345 
346  Ort::Session EEm_session(env, modelFilepath.c_str(), sessionOptions);
347 
348  inputName = EEm_session.GetInputName(0, allocator);
349 
350  inputTypeInfo = EEm_session.GetInputTypeInfo(0);
351  auto EEm_inputTensorInfo = inputTypeInfo.GetTensorTypeAndShapeInfo();
352 
353  inputDims = EEm_inputTensorInfo.GetShape();
354 
355  outputName = EEm_session.GetOutputName(0, allocator);
356 
357  //Ort::TypeInfo
358  outputTypeInfo = EEm_session.GetOutputTypeInfo(0);
359  auto EEm_outputTensorInfo = outputTypeInfo.GetTensorTypeAndShapeInfo();
360 
361  outputDims = EEm_outputTensorInfo.GetShape();
362 
363  size_t EE_TensorSize = nEETowersPad * nEETowersPad;
364  std::vector<float> eemRecoOccMap1dPad(EE_TensorSize); //To store the output reconstructed occupancy
365 
366  inputNames.push_back(inputName);
367  outputNames.push_back(outputName);
368 
369  //Ort::MemoryInfo
370  memoryInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault);
371  inputTensors.push_back(Ort::Value::CreateTensor<float>(
372  memoryInfo, eemOccMap1dCumulPad.data(), EE_TensorSize, inputDims.data(), inputDims.size()));
373 
374  outputTensors.push_back(Ort::Value::CreateTensor<float>(
375  memoryInfo, eemRecoOccMap1dPad.data(), EE_TensorSize, outputDims.data(), outputDims.size()));
376 
377  EEm_session.Run(Ort::RunOptions{nullptr},
378  inputNames.data(),
379  inputTensors.data(),
380  1,
381  outputNames.data(),
382  outputTensors.data(),
383  1);
384 
385  // EE+ //
386  inputDims.clear();
387  outputDims.clear();
388  inputNames.clear();
389  outputNames.clear();
390  inputTensors.clear();
391  outputTensors.clear();
392 
393  modelFilepath = edm::FileInPath("DQM/EcalMonitorClient/data/onnxModels/EEp_resnet2018.onnx").fullPath();
394 
395  Ort::Session EEp_session(env, modelFilepath.c_str(), sessionOptions);
396 
397  inputName = EEp_session.GetInputName(0, allocator);
398 
399  inputTypeInfo = EEp_session.GetInputTypeInfo(0);
400  auto EEp_inputTensorInfo = inputTypeInfo.GetTensorTypeAndShapeInfo();
401 
402  inputDims = EEp_inputTensorInfo.GetShape();
403 
404  outputName = EEp_session.GetOutputName(0, allocator);
405 
406  outputTypeInfo = EEp_session.GetOutputTypeInfo(0);
407 
408  auto EEp_outputTensorInfo = outputTypeInfo.GetTensorTypeAndShapeInfo();
409 
410  outputDims = EEp_outputTensorInfo.GetShape();
411 
412  std::vector<float> eepRecoOccMap1dPad(EE_TensorSize); //To store the output reconstructed occupancy
413 
414  inputNames.push_back(inputName);
415  outputNames.push_back(outputName);
416 
417  //Ort::MemoryInfo
418  memoryInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault);
419  inputTensors.push_back(Ort::Value::CreateTensor<float>(
420  memoryInfo, eepOccMap1dCumulPad.data(), EE_TensorSize, inputDims.data(), inputDims.size()));
421 
422  outputTensors.push_back(Ort::Value::CreateTensor<float>(
423  memoryInfo, eepRecoOccMap1dPad.data(), EE_TensorSize, outputDims.data(), outputDims.size()));
424 
425  EEp_session.Run(Ort::RunOptions{nullptr},
426  inputNames.data(),
427  inputTensors.data(),
428  1,
429  outputNames.data(),
430  outputTensors.data(),
431  1);
432 
434  //2D Loss map to store tower by tower loss between the output (reconstructed) and input occupancies,
435  //Have same dimensions as the occupancy plot
436  std::valarray<std::valarray<float>> EBlossMap2d(std::valarray<float>(nEBPhiTowers), nEBEtaTowers);
437  std::valarray<std::valarray<float>> EEmlossMap2d(std::valarray<float>(nEEPhiTowers), nEEEtaTowers);
438  std::valarray<std::valarray<float>> EEplossMap2d(std::valarray<float>(nEEPhiTowers), nEEEtaTowers);
439 
440  //1D val arrays to store row wise information corresponding to the reconstructed, input and average occupancies, and loss.
441  //and to do element wise (tower wise) operations on them to calculate the MSE loss between the reco and input occupancy.
442  std::valarray<float> EBrecoOcc1d(0., nEBPhiTowers);
443  std::valarray<float> EBinputOcc1d(0., nEBPhiTowers);
444  std::valarray<float> EBavgOcc1d(0., nEBPhiTowers);
445  std::valarray<float> EBloss_;
446 
447  std::valarray<float> EEmrecoOcc1d(0., nEEPhiTowers);
448  std::valarray<float> EEminputOcc1d(0., nEEPhiTowers);
449  std::valarray<float> EEmavgOcc1d(0., nEEPhiTowers);
450  std::valarray<float> EEmloss_;
451 
452  std::valarray<float> EEprecoOcc1d(0., nEEPhiTowers);
453  std::valarray<float> EEpinputOcc1d(0., nEEPhiTowers);
454  std::valarray<float> EEpavgOcc1d(0., nEEPhiTowers);
455  std::valarray<float> EEploss_;
456 
457  std::string EBOccpath =
458  edm::FileInPath("DQM/EcalMonitorClient/data/MLAvgOccupancy/EB_avgocc_Run2022_500ev.dat").fullPath();
459  std::ifstream inFile;
460  double val;
461  inFile.open((EBOccpath).c_str());
462  while (inFile) {
463  inFile >> val;
464  if (inFile.eof())
465  break;
466  EBavgOcc.push_back(val);
467  }
468  inFile.close();
469 
470  std::string EEmOccpath =
471  edm::FileInPath("DQM/EcalMonitorClient/data/MLAvgOccupancy/EEm_avgocc_Run2022_500ev.dat").fullPath();
472  inFile.open((EEmOccpath).c_str());
473  while (inFile) {
474  inFile >> val;
475  if (inFile.eof())
476  break;
477  EEmavgOcc.push_back(val);
478  }
479  inFile.close();
480 
481  std::string EEpOccpath =
482  edm::FileInPath("DQM/EcalMonitorClient/data/MLAvgOccupancy/EEp_avgocc_Run2022_500ev.dat").fullPath();
483  inFile.open((EEpOccpath).c_str());
484  while (inFile) {
485  inFile >> val;
486  if (inFile.eof())
487  break;
488  EEpavgOcc.push_back(val);
489  }
490  inFile.close();
491 
492  //Loss calculation
493  //Ignore the top and bottom replicated padded rows when doing inference
494  //by making index i run over (1,35) instead of (0,36) for EB, and over (1,21) for EE
495 
496  MESet const& sAEReco(sources_.at("AEReco"));
497  TH2F* hEBRecoMap2d(sAEReco.getME(1)->getTH2F());
498 
499  for (int i = 1; i < nEBEtaTowersPad - 1; i++) {
500  for (int j = 0; j < nEBPhiTowers; j++) {
501  int k = (i * nEBPhiTowers) + j;
502  int bin_ = hEBRecoMap2d->GetBin(j + 1, i);
503  EBrecoOcc1d[j] = ebRecoOccMap1dPad[k];
504  EBinputOcc1d[j] = ebOccMap1dCumulPad[k];
505  EBavgOcc1d[j] = EBavgOcc[k];
506  double content = ebRecoOccMap1dPad[k];
507  hEBRecoMap2d->SetBinContent(bin_, content);
508  }
509  //Calculate the MSE loss = (output-input)^2, with avg response correction
510  EBloss_ = std::pow((EBrecoOcc1d / EBavgOcc1d - EBinputOcc1d / EBavgOcc1d), 2);
511  EBlossMap2d[i - 1] = (EBloss_);
512  }
513 
514  TH2F* hEEmRecoMap2d(sAEReco.getME(0)->getTH2F());
515  TH2F* hEEpRecoMap2d(sAEReco.getME(2)->getTH2F());
516 
517  for (int i = 1; i < nEETowersPad - 1; i++) {
518  for (int j = 0; j < nEEPhiTowers; j++) {
519  int k = (i * nEETowersPad) + j + 1;
520  int bin_ = hEEmRecoMap2d->GetBin(j + 1, i);
521 
522  EEmrecoOcc1d[j] = eemRecoOccMap1dPad[k];
523  EEminputOcc1d[j] = eemOccMap1dCumulPad[k];
524  EEmavgOcc1d[j] = EEmavgOcc[k];
525  double EEmcontent = eemRecoOccMap1dPad[k];
526  hEEmRecoMap2d->SetBinContent(bin_, EEmcontent);
527 
528  EEprecoOcc1d[j] = eepRecoOccMap1dPad[k];
529  EEpinputOcc1d[j] = eepOccMap1dCumulPad[k];
530  EEpavgOcc1d[j] = EEpavgOcc[k];
531  double EEpcontent = eepRecoOccMap1dPad[k];
532  hEEpRecoMap2d->SetBinContent(bin_, EEpcontent);
533  }
534  //Calculate the MSE loss = (output-input)^2, with avg response correction
535  EEmloss_ = std::pow((EEmrecoOcc1d / EEmavgOcc1d - EEminputOcc1d / EEmavgOcc1d), 2);
536  EEmlossMap2d[i - 1] = (EEmloss_);
537 
538  EEploss_ = std::pow((EEprecoOcc1d / EEpavgOcc1d - EEpinputOcc1d / EEpavgOcc1d), 2);
539  EEplossMap2d[i - 1] = (EEploss_);
540  }
541 
542  //Store each loss map from the output in the queue
543  EBlossMap2dQ.push_back(EBlossMap2d);
544  EEmlossMap2dQ.push_back(EEmlossMap2d);
545  EEplossMap2dQ.push_back(EEplossMap2d);
546 
547  //Keep exactly nLSloss loss maps to multiply
548  if (EBlossMap2dQ.size() > nLSloss) {
549  EBlossMap2dQ.pop_front();
550  EEmlossMap2dQ.pop_front();
551  EEplossMap2dQ.pop_front();
552  }
553  if (EBlossMap2dQ.size() < nLSloss) { //Exit if there are not nLSloss loss maps
554  return;
555  }
556 
557  //To hold the final multiplied loss
558  std::valarray<std::valarray<float>> EBlossMap2dMult(std::valarray<float>(1., nEBPhiTowers), nEBEtaTowers);
559  std::valarray<std::valarray<float>> EEmlossMap2dMult(std::valarray<float>(1., nEEPhiTowers), nEEEtaTowers);
560  std::valarray<std::valarray<float>> EEplossMap2dMult(std::valarray<float>(1., nEEPhiTowers), nEEEtaTowers);
561 
562  //Multiply together the last nLSloss loss maps
563  //So that real anomalies which persist with time are enhanced and fluctuations are suppressed.
564  for (size_t i = 0; i < EBlossMap2dQ.size(); i++) {
565  EBlossMap2dMult *= EBlossMap2dQ[i];
566  EEmlossMap2dMult *= EEmlossMap2dQ[i];
567  EEplossMap2dMult *= EEplossMap2dQ[i];
568  }
569 
570  //Fill the AELoss ME with the values of this time multiplied loss map
571  //MESet const& sAELoss(sources_.at("AELoss"));
572  MESet& sAELoss(sources_.at("AELoss"));
573 
574  TH2F* hEBLossMap2dMult(sAELoss.getME(1)->getTH2F());
575 
576  for (int i = 0; i < hEBLossMap2dMult->GetNbinsY(); i++) {
577  for (int j = 0; j < hEBLossMap2dMult->GetNbinsX(); j++) {
578  int bin_ = hEBLossMap2dMult->GetBin(j + 1, i + 1);
579  double content = EBlossMap2dMult[i][j];
580  hEBLossMap2dMult->SetBinContent(bin_, content);
581  }
582  }
583 
584  TH2F* hEEmLossMap2dMult(sAELoss.getME(0)->getTH2F());
585  TH2F* hEEpLossMap2dMult(sAELoss.getME(2)->getTH2F());
586 
587  for (int i = 0; i < hEEmLossMap2dMult->GetNbinsY(); i++) {
588  for (int j = 0; j < hEEmLossMap2dMult->GetNbinsX(); j++) {
589  int bin_ = hEEmLossMap2dMult->GetBin(j + 1, i + 1);
590 
591  double EEmcontent = EEmlossMap2dMult[i][j];
592  hEEmLossMap2dMult->SetBinContent(bin_, EEmcontent);
593 
594  double EEpcontent = EEplossMap2dMult[i][j];
595  hEEpLossMap2dMult->SetBinContent(bin_, EEpcontent);
596  }
597  }
598 
600  //Apply the quality threshold on the time multiplied loss map stored in the ME AELoss
601  //If anomalous, the tower entry will have a large loss value. If good, the value will be close to zero.
602 
603  MESet& meBadTowerCount(sources_.at("BadTowerCount"));
604  MESet& meBadTowerCountNorm(sources_.at("BadTowerCountNorm"));
605  MESet& meTrendMLBadTower(MEs_.at("TrendMLBadTower"));
606 
607  LScount++;
608 
609  MESet::const_iterator dAEnd(sAELoss.end(GetElectronicsMap()));
610  for (MESet::const_iterator dItr(sAELoss.beginChannel(GetElectronicsMap())); dItr != dAEnd;
612  DetId id(dItr->getId());
613 
614  bool doMaskML(meMLQualitySummary.maskMatches(id, mask, statusManager_, GetTrigTowerMap()));
615 
616  float entries(dItr->getBinContent());
617 
618  int quality(doMaskML ? kMGood : kGood);
619  float MLThreshold;
620 
621  if (id.subdetId() == EcalEndcap) {
622  EEDetId eeid(id);
623  if (eeid.zside() > 0)
624  MLThreshold = EEpThreshold_;
625  else
626  MLThreshold = EEmThreshold_;
627  } else {
628  MLThreshold = EBThreshold_;
629  }
630 
631  //If a trigger tower entry is greater than the ML threshold, set it to Bad quality, otherwise Good.
632  if (entries > MLThreshold) {
633  quality = doMaskML ? kMBad : kBad;
634  meBadTowerCount.fill(getEcalDQMSetupObjects(), id);
635  if (id.subdetId() == EcalEndcap)
636  nbadtowerEE++;
637  else
638  nbadtowerEB++;
639  }
640  //Fill the quality summary with the quality of the given tower id.
641  meMLQualitySummary.setBinContent(getEcalDQMSetupObjects(), id, double(quality));
642 
643  double badtowcount(meBadTowerCount.getBinContent(getEcalDQMSetupObjects(), id));
644  meBadTowerCountNorm.setBinContent(getEcalDQMSetupObjects(), id, double(badtowcount / LScount));
645  } // ML Quality Summary
646 
647  meTrendMLBadTower.fill(getEcalDQMSetupObjects(), EcalBarrel, double(timestamp_.iLumi), double(nbadtowerEB));
648  meTrendMLBadTower.fill(getEcalDQMSetupObjects(), EcalEndcap, double(timestamp_.iLumi), double(nbadtowerEE));
649 
650  } // producePlots()
651 
653 } // namespace ecaldqm
std::deque< std::valarray< std::valarray< float > > > EBlossMap2dQ
Definition: MLClient.h:60
static const int nEEPhiTowers
Definition: MLClient.h:27
float EEm_PUcorr_slope_
Definition: MLClient.h:38
void setParams(edm::ParameterSet const &) override
Definition: MLClient.cc:20
#define DEFINE_ECALDQM_WORKER(TYPE)
Definition: DQWorker.h:168
static const int nEBEtaTowers
Definition: MLClient.h:23
edm::LuminosityBlockNumber_t iLumi
Definition: DQWorker.h:48
static const int PHYSICS_BAD_CHANNEL_WARNING
std::string fullPath() const
Definition: FileInPath.cc:161
MESet & at(const std::string &key)
Definition: MESet.h:399
std::deque< std::valarray< std::valarray< float > > > EEplossMap2dQ
Definition: MLClient.h:61
static const int PEDESTAL_ONLINE_HIGH_GAIN_RMS_ERROR
static const int PHYSICS_BAD_CHANNEL_ERROR
void producePlots(ProcessType) override
Definition: MLClient.cc:43
static const int nEBEtaTowersPad
Definition: MLClient.h:31
constexpr uint32_t mask
Definition: gpuClustering.h:26
string quality
double getFloatValue() const
std::set< std::string > qualitySummaries_
std::vector< double > EEpavgOcc
Definition: MLClient.h:57
float EEpThreshold_
Definition: MLClient.h:34
std::deque< std::valarray< float > > eemOccMap1dQ
Definition: MLClient.h:54
StatusManager const * statusManager_
float EEp_PUcorr_intercept_
Definition: MLClient.h:40
size_t nLSloss
Definition: MLClient.h:44
std::deque< std::valarray< float > > eepOccMap1dQ
Definition: MLClient.h:53
std::deque< std::valarray< std::valarray< float > > > EEmlossMap2dQ
Definition: MLClient.h:62
static const int nEETowersPad
Definition: MLClient.h:32
MESetCollection sources_
float EB_PUcorr_slope_
Definition: MLClient.h:36
float EEm_PUcorr_intercept_
Definition: MLClient.h:41
EcalElectronicsMapping const * GetElectronicsMap()
Definition: DQWorker.cc:150
EcalDQMSetupObjects const getEcalDQMSetupObjects()
Definition: DQWorker.cc:170
Definition: DetId.h:17
Timestamp timestamp_
Definition: DQWorker.h:134
int zside() const
Definition: EEDetId.h:71
std::vector< double > EEmavgOcc
Definition: MLClient.h:58
float EEmThreshold_
Definition: MLClient.h:35
static const int nEBPhiTowers
Definition: MLClient.h:24
MESetCollection MEs_
Definition: DQWorker.h:131
std::deque< int > NEventQ
Definition: MLClient.h:49
float EB_PUcorr_intercept_
Definition: MLClient.h:39
const_iterator & toNextChannel(EcalElectronicsMapping const *)
Definition: MESet.cc:413
std::vector< double > EBavgOcc
Definition: MLClient.h:56
EcalTrigTowerConstituentsMap const * GetTrigTowerMap()
Definition: DQWorker.cc:155
float EBThreshold_
Definition: MLClient.h:33
float EEp_PUcorr_slope_
Definition: MLClient.h:37
static const int nEEEtaTowers
Definition: MLClient.h:26
void erase(const std::string &key)
Definition: MESet.h:390
std::deque< std::valarray< float > > ebOccMap1dQ
Definition: MLClient.h:52
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29