/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
DQM/EcalMonitorClient/src/MLClient.cc
655 строк
27 KB
Abhirami Harilal
Modify PU condition for MLDQM
31 май 2023, 17:42
31 май 2023, 17:42
9f0a6fd
Код
Авторство
О чём код?
#include "DQM/EcalMonitorClient/interface/MLClient.h" #include "CondFormats/EcalObjects/interface/EcalDQMStatusHelper.h" #include "DQM/EcalCommon/interface/EcalDQMCommonUtils.h" #include "FWCore/ParameterSet/interface/ParameterSet.h" #include "PhysicsTools/ONNXRuntime/interface/ONNXRuntime.h" #include "DQM/EcalCommon/interface/MESetNonObject.h" #include <fstream> #include <string> using namespace cms::Ort; namespace ecaldqm { MLClient::MLClient() : DQWorkerClient() { qualitySummaries_.insert("MLQualitySummary"); } void MLClient::setParams(edm::ParameterSet const& _params) { EBThreshold_ = _params.getUntrackedParameter<double>("EBThreshold"); EEpThreshold_ = _params.getUntrackedParameter<double>("EEpThreshold"); EEmThreshold_ = _params.getUntrackedParameter<double>("EEmThreshold"); EB_PUcorr_slope_ = _params.getUntrackedParameter<double>("EB_PUcorr_slope"); EB_PUcorr_intercept_ = _params.getUntrackedParameter<double>("EB_PUcorr_intercept"); EEp_PUcorr_slope_ = _params.getUntrackedParameter<double>("EEp_PUcorr_slope"); EEp_PUcorr_intercept_ = _params.getUntrackedParameter<double>("EEp_PUcorr_intercept"); EEm_PUcorr_slope_ = _params.getUntrackedParameter<double>("EEm_PUcorr_slope"); EEm_PUcorr_intercept_ = _params.getUntrackedParameter<double>("EEm_PUcorr_intercept"); if (!onlineMode_) { MEs_.erase(std::string("MLQualitySummary")); MEs_.erase(std::string("EventsperMLImage")); sources_.erase(std::string("PU")); sources_.erase(std::string("NumEvents")); sources_.erase(std::string("DigiAllByLumi")); sources_.erase(std::string("AELoss")); sources_.erase(std::string("BadTowerCount")); sources_.erase(std::string("BadTowerCountNorm")); } } void MLClient::producePlots(ProcessType) { if (!onlineMode_) return; nbadtowerEB = 0; nbadtowerEE = 0; using namespace std; MESet& meMLQualitySummary(MEs_.at("MLQualitySummary")); MESet& meEventsperMLImage(MEs_.at("EventsperMLImage")); MESetNonObject const& sPU(static_cast<MESetNonObject&>(sources_.at("PU"))); MESetNonObject const& sNumEvents(static_cast<MESetNonObject&>(sources_.at("NumEvents"))); //Get the no.of events and the PU per LS calculated in OccupancyTask int nEv = sNumEvents.getFloatValue(); double pu = sPU.getFloatValue(); //Do not compute ML quality if PU is non existent. if (pu <= 0.) { return; } uint32_t mask(1 << EcalDQMStatusHelper::PEDESTAL_ONLINE_HIGH_GAIN_RMS_ERROR | 1 << EcalDQMStatusHelper::PHYSICS_BAD_CHANNEL_WARNING | 1 << EcalDQMStatusHelper::PHYSICS_BAD_CHANNEL_ERROR); //////////////// ML Data Preprocessing ////////////////////////////////// //Inorder to feed the data into the ML model we apply some preprocessing. //We use the Digi Occupancy per Lumisection as the input source. //The model was trained on each occupancy plot having 500 events. //In apprehension of the low luminosity in the beginning of Run3, where in online DQM //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, //and require that the total no.of events on this summed occupancy to be atleast 200. //(This no.of LS and the no.of events are parameters which would require tuning later) //This summed occupancy is now the input image, which is then corrected for PileUp(PU) dependence and //change in no.of events, which are derived from training. //The input image is also padded by replicating the top and bottom rows so as to prevent the "edge effect" //wherein the ML model's learning degrades near the edge of the data set it sees. //This padding is then removed during inference on the model output. //Get the histogram of the input digi occupancy per lumisection. TH2F* hEEmDigiMap((sources_.at("DigiAllByLumi")).getME(0)->getTH2F()); TH2F* hEbDigiMap((sources_.at("DigiAllByLumi")).getME(1)->getTH2F()); TH2F* hEEpDigiMap((sources_.at("DigiAllByLumi")).getME(2)->getTH2F()); size_t nEBTowers = nEBEtaTowers * nEBPhiTowers; //Each EB occupancy map is of size 34x72 towers size_t nEETowers = nEEEtaTowers * nEEPhiTowers; //Each EE occupancy map is of size 20x20 towers //Vectors to feed into the ML network std::vector<float> ebOccMap1dCumulPad; std::vector<float> eemOccMap1dCumulPad; std::vector<float> eepOccMap1dCumulPad; //Array to store occupancy maps std::valarray<float> ebOccMap1d(nEBTowers); std::valarray<float> eemOccMap1d(nEETowers); std::valarray<float> eepOccMap1d(nEETowers); //Store the values from the input histogram into the array //to do preprocessing for (int i = 0; i < hEbDigiMap->GetNbinsY(); i++) { //NbinsY = 34, NbinsX = 72 for (int j = 0; j < hEbDigiMap->GetNbinsX(); j++) { int bin = hEbDigiMap->GetBin(j + 1, i + 1); int k = (i * nEBPhiTowers) + j; ebOccMap1d[k] = hEbDigiMap->GetBinContent(bin); } } ebOccMap1dQ.push_back(ebOccMap1d); //Queue which stores input occupancy maps for nLS lumis for (int i = 0; i < hEEpDigiMap->GetNbinsY(); i++) { //NbinsY = 20, NbinsX = 20 for (int j = 0; j < hEEpDigiMap->GetNbinsX(); j++) { int bin = hEEpDigiMap->GetBin(j + 1, i + 1); int k = (i * nEEPhiTowers) + j; eemOccMap1d[k] = hEEmDigiMap->GetBinContent(bin); eepOccMap1d[k] = hEEpDigiMap->GetBinContent(bin); } } //Queue which stores input occupancy maps for nLS lumis eemOccMap1dQ.push_back(eemOccMap1d); eepOccMap1dQ.push_back(eepOccMap1d); NEventQ.push_back(nEv); //Queue which stores the no.of events per LS for nLS lumis if (NEventQ.size() < nLS) { return; //Should have nLS lumis to add the occupancy over. } if (NEventQ.size() > nLS) { NEventQ.pop_front(); //Keep only nLS consecutive LS. Pop the first one if size greater than nLS } if (ebOccMap1dQ.size() > nLS) { ebOccMap1dQ.pop_front(); //Same conditon for the input occupancy maps. eemOccMap1dQ.pop_front(); eepOccMap1dQ.pop_front(); } int TNum = 0; for (size_t i = 0; i < nLS; i++) { TNum += NEventQ[i]; //Total no.of events over nLS lumis } if (TNum < 400) { return; //The total no.of events should be atleast 400 over nLS for meaningful statistics } //Fill the ME to monitor the trend of the total no.of events in each input image to the ML model meEventsperMLImage.fill(getEcalDQMSetupObjects(), EcalBarrel, double(timestamp_.iLumi), double(TNum)); //Array to hold the sum of inputs, which make atleast 400 events. std::valarray<float> ebOccMap1dCumul(0., nEBTowers); std::valarray<float> eemOccMap1dCumul(0., nEETowers); std::valarray<float> eepOccMap1dCumul(0., nEETowers); //Sum the input arrays of nLS. for (size_t i = 0; i < ebOccMap1dQ.size(); i++) { ebOccMap1dCumul += ebOccMap1dQ[i]; eemOccMap1dCumul += eemOccMap1dQ[i]; eepOccMap1dCumul += eepOccMap1dQ[i]; } //Applying PU correction derived from training ebOccMap1dCumul = ebOccMap1dCumul / (EB_PUcorr_slope_ * pu + EB_PUcorr_intercept_); eemOccMap1dCumul = eemOccMap1dCumul / (EEm_PUcorr_slope_ * pu + EEm_PUcorr_intercept_); eepOccMap1dCumul = eepOccMap1dCumul / (EEp_PUcorr_slope_ * pu + EEp_PUcorr_intercept_); //Scaling up to match input dimensions. ebOccMap1dCumul = ebOccMap1dCumul * (nEBEtaTowers * nEBPhiTowers); eemOccMap1dCumul = eemOccMap1dCumul * nEEEtaTowers * nEEPhiTowers; //(nEETowersPad * nEETowersPad); eepOccMap1dCumul = eepOccMap1dCumul * nEEEtaTowers * nEEPhiTowers; //(nEETowersPad * nEETowersPad); //Correction for no.of events in each input image as originally model trained with 500 events per image ebOccMap1dCumul = ebOccMap1dCumul * (500. / TNum); eemOccMap1dCumul = eemOccMap1dCumul * (500. / TNum); eepOccMap1dCumul = eepOccMap1dCumul * (500. / TNum); std::vector<std::vector<float>> ebOccMap2dCumul(nEBEtaTowers, std::vector<float>(nEBPhiTowers, 0.)); //Convert 1dCumul to 2d for (size_t i = 0; i < nEBEtaTowers; i++) { for (size_t j = 0; j < nEBPhiTowers; j++) { int k = (i * nEBPhiTowers) + j; ebOccMap2dCumul[i][j] = ebOccMap1dCumul[k]; } } std::vector<float> pad_top; std::vector<float> pad_bottom; std::vector<float> pad_left; std::vector<float> pad_right; pad_top = ebOccMap2dCumul[0]; pad_bottom = ebOccMap2dCumul[ebOccMap2dCumul.size() - 1]; ebOccMap2dCumul.insert(ebOccMap2dCumul.begin(), pad_top); ebOccMap2dCumul.push_back(pad_bottom); //// Endcaps /// std::vector<std::vector<float>> eemOccMap2dCumul(nEEEtaTowers, std::vector<float>(nEEPhiTowers, 0.)); std::vector<std::vector<float>> eepOccMap2dCumul(nEEEtaTowers, std::vector<float>(nEEPhiTowers, 0.)); for (size_t i = 0; i < nEEEtaTowers; i++) { for (size_t j = 0; j < nEEPhiTowers; j++) { int k = (i * nEEPhiTowers) + j; eemOccMap2dCumul[i][j] = eemOccMap1dCumul[k]; eepOccMap2dCumul[i][j] = eepOccMap1dCumul[k]; } } // EE - // pad_top.clear(); pad_bottom.clear(); pad_left.clear(); pad_right.clear(); pad_top = eemOccMap2dCumul[0]; pad_bottom = eemOccMap2dCumul[eemOccMap2dCumul.size() - 1]; eemOccMap2dCumul.insert(eemOccMap2dCumul.begin(), pad_top); eemOccMap2dCumul.push_back(pad_bottom); for (auto& row : eemOccMap2dCumul) { pad_left.push_back(row[0]); pad_right.push_back(row[row.size() - 1]); } std::size_t Lindex = 0; std::size_t Rindex = 0; for (auto& row : eemOccMap2dCumul) { row.insert(row.begin(), pad_left[Lindex++]); row.insert(row.end(), pad_right[Rindex++]); } // EE + // pad_top.clear(); pad_bottom.clear(); pad_top = eepOccMap2dCumul[0]; pad_bottom = eepOccMap2dCumul[eepOccMap2dCumul.size() - 1]; eepOccMap2dCumul.insert(eepOccMap2dCumul.begin(), pad_top); eepOccMap2dCumul.push_back(pad_bottom); for (auto& row : eepOccMap2dCumul) { pad_left.push_back(row[0]); pad_right.push_back(row[row.size() - 1]); } Lindex = 0; Rindex = 0; for (auto& row : eepOccMap2dCumul) { row.insert(row.begin(), pad_left[Lindex++]); row.insert(row.end(), pad_right[Rindex++]); } //The pre-processed input is now fed into the 1D input tensor vector which will go into the ML model for (auto& row : ebOccMap2dCumul) { ebOccMap1dCumulPad.insert(ebOccMap1dCumulPad.end(), row.begin(), row.end()); } for (auto& row : eemOccMap2dCumul) { eemOccMap1dCumulPad.insert(eemOccMap1dCumulPad.end(), row.begin(), row.end()); } for (auto& row : eepOccMap2dCumul) { eepOccMap1dCumulPad.insert(eepOccMap1dCumulPad.end(), row.begin(), row.end()); } ///// Model Inference ////// //An Autoencoder (AE) network with resnet architecture is used here which is trained on //certified good data (EB digi occupancy) from Run 2018 data. //On giving an input occupancy map, the encoder part of the AE compresses and reduces the input data, learning its features, //and the decoder reconstructs the data from the encoded form into a representation as close to the original input as possible. //We then compute the Mean squared error (MSE) between the input and output image, also called the Reconstruction Loss, //calculated at a tower by tower basis. //Thus, given an anomalous tower the loss should be significantly higher than the loss with respect to good towers, which the model //has already seen --> anomaly detection. //When calculating the loss we also apply a response correction by dividing each input and output image with the average occupancy from //all 2018 data (also to be tuned),to accommodate the difference in response of crystals in different regions of the Ecal Barrel //Further each loss map from each input image is then multiplied by the last N loss maps, ///so that real anomalies which persist with time are enhanced and fluctuations are suppressed. //A quality threshold is then applied on this time multiplied loss map, to mark them as GOOD or BAD, //after which it is stored as a quality summary ME. ///ONNX model running/// std::string instanceName{"AE-DQM-inference"}; std::string modelFilepath = edm::FileInPath("DQM/EcalMonitorClient/data/onnxModels/resnet.onnx").fullPath(); Ort::SessionOptions sessionOptions; sessionOptions.SetIntraOpNumThreads(1); Ort::Env env(OrtLoggingLevel::ORT_LOGGING_LEVEL_WARNING, instanceName.c_str()); Ort::Session session(env, modelFilepath.c_str(), sessionOptions); Ort::AllocatorWithDefaultOptions allocator; // Strings returned by session.GetInputNameAllocated are temporary, need to copy them before they are deallocated std::string inputName{session.GetInputNameAllocated(0, allocator).get()}; Ort::TypeInfo inputTypeInfo = session.GetInputTypeInfo(0); auto inputTensorInfo = inputTypeInfo.GetTensorTypeAndShapeInfo(); std::vector<int64_t> inputDims = inputTensorInfo.GetShape(); std::string outputName{session.GetOutputNameAllocated(0, allocator).get()}; Ort::TypeInfo outputTypeInfo = session.GetOutputTypeInfo(0); auto outputTensorInfo = outputTypeInfo.GetTensorTypeAndShapeInfo(); std::vector<int64_t> outputDims = outputTensorInfo.GetShape(); size_t TensorSize = nEBEtaTowersPad * nEBPhiTowers; std::vector<float> ebRecoOccMap1dPad(TensorSize); //To store the output reconstructed occupancy std::vector<const char*> inputNames{inputName.c_str()}; std::vector<const char*> outputNames{outputName.c_str()}; std::vector<Ort::Value> inputTensors; std::vector<Ort::Value> outputTensors; Ort::MemoryInfo memoryInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); inputTensors.push_back(Ort::Value::CreateTensor<float>( memoryInfo, ebOccMap1dCumulPad.data(), TensorSize, inputDims.data(), inputDims.size())); outputTensors.push_back(Ort::Value::CreateTensor<float>( memoryInfo, ebRecoOccMap1dPad.data(), TensorSize, outputDims.data(), outputDims.size())); session.Run(Ort::RunOptions{nullptr}, inputNames.data(), inputTensors.data(), 1, outputNames.data(), outputTensors.data(), 1); //Endcaps // EE- // inputDims.clear(); outputDims.clear(); inputNames.clear(); outputNames.clear(); inputTensors.clear(); outputTensors.clear(); modelFilepath = edm::FileInPath("DQM/EcalMonitorClient/data/onnxModels/EEm_resnet2018.onnx").fullPath(); Ort::Session EEm_session(env, modelFilepath.c_str(), sessionOptions); inputName = EEm_session.GetInputNameAllocated(0, allocator).get(); inputTypeInfo = EEm_session.GetInputTypeInfo(0); auto EEm_inputTensorInfo = inputTypeInfo.GetTensorTypeAndShapeInfo(); inputDims = EEm_inputTensorInfo.GetShape(); outputName = EEm_session.GetOutputNameAllocated(0, allocator).get(); //Ort::TypeInfo outputTypeInfo = EEm_session.GetOutputTypeInfo(0); auto EEm_outputTensorInfo = outputTypeInfo.GetTensorTypeAndShapeInfo(); outputDims = EEm_outputTensorInfo.GetShape(); size_t EE_TensorSize = nEETowersPad * nEETowersPad; std::vector<float> eemRecoOccMap1dPad(EE_TensorSize); //To store the output reconstructed occupancy inputNames.push_back(inputName.c_str()); outputNames.push_back(outputName.c_str()); //Ort::MemoryInfo memoryInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); inputTensors.push_back(Ort::Value::CreateTensor<float>( memoryInfo, eemOccMap1dCumulPad.data(), EE_TensorSize, inputDims.data(), inputDims.size())); outputTensors.push_back(Ort::Value::CreateTensor<float>( memoryInfo, eemRecoOccMap1dPad.data(), EE_TensorSize, outputDims.data(), outputDims.size())); EEm_session.Run(Ort::RunOptions{nullptr}, inputNames.data(), inputTensors.data(), 1, outputNames.data(), outputTensors.data(), 1); // EE+ // inputDims.clear(); outputDims.clear(); inputNames.clear(); outputNames.clear(); inputTensors.clear(); outputTensors.clear(); modelFilepath = edm::FileInPath("DQM/EcalMonitorClient/data/onnxModels/EEp_resnet2018.onnx").fullPath(); Ort::Session EEp_session(env, modelFilepath.c_str(), sessionOptions); inputName = EEp_session.GetInputNameAllocated(0, allocator).get(); inputTypeInfo = EEp_session.GetInputTypeInfo(0); auto EEp_inputTensorInfo = inputTypeInfo.GetTensorTypeAndShapeInfo(); inputDims = EEp_inputTensorInfo.GetShape(); outputName = EEp_session.GetOutputNameAllocated(0, allocator).get(); outputTypeInfo = EEp_session.GetOutputTypeInfo(0); auto EEp_outputTensorInfo = outputTypeInfo.GetTensorTypeAndShapeInfo(); outputDims = EEp_outputTensorInfo.GetShape(); std::vector<float> eepRecoOccMap1dPad(EE_TensorSize); //To store the output reconstructed occupancy inputNames.push_back(inputName.c_str()); outputNames.push_back(outputName.c_str()); //Ort::MemoryInfo memoryInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); inputTensors.push_back(Ort::Value::CreateTensor<float>( memoryInfo, eepOccMap1dCumulPad.data(), EE_TensorSize, inputDims.data(), inputDims.size())); outputTensors.push_back(Ort::Value::CreateTensor<float>( memoryInfo, eepRecoOccMap1dPad.data(), EE_TensorSize, outputDims.data(), outputDims.size())); EEp_session.Run(Ort::RunOptions{nullptr}, inputNames.data(), inputTensors.data(), 1, outputNames.data(), outputTensors.data(), 1); ///Inference on the output from the model/// //2D Loss map to store tower by tower loss between the output (reconstructed) and input occupancies, //Have same dimensions as the occupancy plot std::valarray<std::valarray<float>> EBlossMap2d(std::valarray<float>(nEBPhiTowers), nEBEtaTowers); std::valarray<std::valarray<float>> EEmlossMap2d(std::valarray<float>(nEEPhiTowers), nEEEtaTowers); std::valarray<std::valarray<float>> EEplossMap2d(std::valarray<float>(nEEPhiTowers), nEEEtaTowers); //1D val arrays to store row wise information corresponding to the reconstructed, input and average occupancies, and loss. //and to do element wise (tower wise) operations on them to calculate the MSE loss between the reco and input occupancy. std::valarray<float> EBrecoOcc1d(0., nEBPhiTowers); std::valarray<float> EBinputOcc1d(0., nEBPhiTowers); std::valarray<float> EBavgOcc1d(0., nEBPhiTowers); std::valarray<float> EBloss_; std::valarray<float> EEmrecoOcc1d(0., nEEPhiTowers); std::valarray<float> EEminputOcc1d(0., nEEPhiTowers); std::valarray<float> EEmavgOcc1d(0., nEEPhiTowers); std::valarray<float> EEmloss_; std::valarray<float> EEprecoOcc1d(0., nEEPhiTowers); std::valarray<float> EEpinputOcc1d(0., nEEPhiTowers); std::valarray<float> EEpavgOcc1d(0., nEEPhiTowers); std::valarray<float> EEploss_; std::string EBOccpath = edm::FileInPath("DQM/EcalMonitorClient/data/MLAvgOccupancy/EB_avgocc_Run2022_500ev.dat").fullPath(); std::ifstream inFile; double val; inFile.open((EBOccpath).c_str()); while (inFile) { inFile >> val; if (inFile.eof()) break; EBavgOcc.push_back(val); } inFile.close(); std::string EEmOccpath = edm::FileInPath("DQM/EcalMonitorClient/data/MLAvgOccupancy/EEm_avgocc_Run2022_500ev.dat").fullPath(); inFile.open((EEmOccpath).c_str()); while (inFile) { inFile >> val; if (inFile.eof()) break; EEmavgOcc.push_back(val); } inFile.close(); std::string EEpOccpath = edm::FileInPath("DQM/EcalMonitorClient/data/MLAvgOccupancy/EEp_avgocc_Run2022_500ev.dat").fullPath(); inFile.open((EEpOccpath).c_str()); while (inFile) { inFile >> val; if (inFile.eof()) break; EEpavgOcc.push_back(val); } inFile.close(); //Loss calculation //Ignore the top and bottom replicated padded rows when doing inference //by making index i run over (1,35) instead of (0,36) for EB, and over (1,21) for EE MESet const& sAEReco(sources_.at("AEReco")); TH2F* hEBRecoMap2d(sAEReco.getME(1)->getTH2F()); for (int i = 1; i < nEBEtaTowersPad - 1; i++) { for (int j = 0; j < nEBPhiTowers; j++) { int k = (i * nEBPhiTowers) + j; int bin_ = hEBRecoMap2d->GetBin(j + 1, i); EBrecoOcc1d[j] = ebRecoOccMap1dPad[k]; EBinputOcc1d[j] = ebOccMap1dCumulPad[k]; EBavgOcc1d[j] = EBavgOcc[k]; double content = ebRecoOccMap1dPad[k]; hEBRecoMap2d->SetBinContent(bin_, content); } //Calculate the MSE loss = (output-input)^2, with avg response correction EBloss_ = std::pow((EBrecoOcc1d / EBavgOcc1d - EBinputOcc1d / EBavgOcc1d), 2); EBlossMap2d[i - 1] = (EBloss_); } TH2F* hEEmRecoMap2d(sAEReco.getME(0)->getTH2F()); TH2F* hEEpRecoMap2d(sAEReco.getME(2)->getTH2F()); for (int i = 1; i < nEETowersPad - 1; i++) { for (int j = 0; j < nEEPhiTowers; j++) { int k = (i * nEETowersPad) + j + 1; int bin_ = hEEmRecoMap2d->GetBin(j + 1, i); EEmrecoOcc1d[j] = eemRecoOccMap1dPad[k]; EEminputOcc1d[j] = eemOccMap1dCumulPad[k]; EEmavgOcc1d[j] = EEmavgOcc[k]; double EEmcontent = eemRecoOccMap1dPad[k]; hEEmRecoMap2d->SetBinContent(bin_, EEmcontent); EEprecoOcc1d[j] = eepRecoOccMap1dPad[k]; EEpinputOcc1d[j] = eepOccMap1dCumulPad[k]; EEpavgOcc1d[j] = EEpavgOcc[k]; double EEpcontent = eepRecoOccMap1dPad[k]; hEEpRecoMap2d->SetBinContent(bin_, EEpcontent); } //Calculate the MSE loss = (output-input)^2, with avg response correction EEmloss_ = std::pow((EEmrecoOcc1d / EEmavgOcc1d - EEminputOcc1d / EEmavgOcc1d), 2); EEmlossMap2d[i - 1] = (EEmloss_); EEploss_ = std::pow((EEprecoOcc1d / EEpavgOcc1d - EEpinputOcc1d / EEpavgOcc1d), 2); EEplossMap2d[i - 1] = (EEploss_); } //Store each loss map from the output in the queue EBlossMap2dQ.push_back(EBlossMap2d); EEmlossMap2dQ.push_back(EEmlossMap2d); EEplossMap2dQ.push_back(EEplossMap2d); //Keep exactly nLSloss loss maps to multiply if (EBlossMap2dQ.size() > nLSloss) { EBlossMap2dQ.pop_front(); EEmlossMap2dQ.pop_front(); EEplossMap2dQ.pop_front(); } if (EBlossMap2dQ.size() < nLSloss) { //Exit if there are not nLSloss loss maps return; } //To hold the final multiplied loss std::valarray<std::valarray<float>> EBlossMap2dMult(std::valarray<float>(1., nEBPhiTowers), nEBEtaTowers); std::valarray<std::valarray<float>> EEmlossMap2dMult(std::valarray<float>(1., nEEPhiTowers), nEEEtaTowers); std::valarray<std::valarray<float>> EEplossMap2dMult(std::valarray<float>(1., nEEPhiTowers), nEEEtaTowers); //Multiply together the last nLSloss loss maps //So that real anomalies which persist with time are enhanced and fluctuations are suppressed. for (size_t i = 0; i < EBlossMap2dQ.size(); i++) { EBlossMap2dMult *= EBlossMap2dQ[i]; EEmlossMap2dMult *= EEmlossMap2dQ[i]; EEplossMap2dMult *= EEplossMap2dQ[i]; } //Fill the AELoss ME with the values of this time multiplied loss map //MESet const& sAELoss(sources_.at("AELoss")); MESet& sAELoss(sources_.at("AELoss")); TH2F* hEBLossMap2dMult(sAELoss.getME(1)->getTH2F()); for (int i = 0; i < hEBLossMap2dMult->GetNbinsY(); i++) { for (int j = 0; j < hEBLossMap2dMult->GetNbinsX(); j++) { int bin_ = hEBLossMap2dMult->GetBin(j + 1, i + 1); double content = EBlossMap2dMult[i][j]; hEBLossMap2dMult->SetBinContent(bin_, content); } } TH2F* hEEmLossMap2dMult(sAELoss.getME(0)->getTH2F()); TH2F* hEEpLossMap2dMult(sAELoss.getME(2)->getTH2F()); for (int i = 0; i < hEEmLossMap2dMult->GetNbinsY(); i++) { for (int j = 0; j < hEEmLossMap2dMult->GetNbinsX(); j++) { int bin_ = hEEmLossMap2dMult->GetBin(j + 1, i + 1); double EEmcontent = EEmlossMap2dMult[i][j]; hEEmLossMap2dMult->SetBinContent(bin_, EEmcontent); double EEpcontent = EEplossMap2dMult[i][j]; hEEpLossMap2dMult->SetBinContent(bin_, EEpcontent); } } ///////////////////// ML Quality Summary ///////////////////// //Apply the quality threshold on the time multiplied loss map stored in the ME AELoss //If anomalous, the tower entry will have a large loss value. If good, the value will be close to zero. MESet& meBadTowerCount(sources_.at("BadTowerCount")); MESet& meBadTowerCountNorm(sources_.at("BadTowerCountNorm")); MESet& meTrendMLBadTower(MEs_.at("TrendMLBadTower")); LScount++; MESet::const_iterator dAEnd(sAELoss.end(GetElectronicsMap())); for (MESet::const_iterator dItr(sAELoss.beginChannel(GetElectronicsMap())); dItr != dAEnd; dItr.toNextChannel(GetElectronicsMap())) { DetId id(dItr->getId()); bool doMaskML(meMLQualitySummary.maskMatches(id, mask, statusManager_, GetTrigTowerMap())); float entries(dItr->getBinContent()); int quality(doMaskML ? kMGood : kGood); float MLThreshold; if (id.subdetId() == EcalEndcap) { EEDetId eeid(id); if (eeid.zside() > 0) MLThreshold = EEpThreshold_; else MLThreshold = EEmThreshold_; } else { MLThreshold = EBThreshold_; } //If a trigger tower entry is greater than the ML threshold, set it to Bad quality, otherwise Good. if (entries > MLThreshold) { quality = doMaskML ? kMBad : kBad; meBadTowerCount.fill(getEcalDQMSetupObjects(), id); if (id.subdetId() == EcalEndcap) nbadtowerEE++; else nbadtowerEB++; } //Fill the quality summary with the quality of the given tower id. meMLQualitySummary.setBinContent(getEcalDQMSetupObjects(), id, double(quality)); double badtowcount(meBadTowerCount.getBinContent(getEcalDQMSetupObjects(), id)); meBadTowerCountNorm.setBinContent(getEcalDQMSetupObjects(), id, double(badtowcount / LScount)); } // ML Quality Summary meTrendMLBadTower.fill(getEcalDQMSetupObjects(), EcalBarrel, double(timestamp_.iLumi), double(nbadtowerEB)); meTrendMLBadTower.fill(getEcalDQMSetupObjects(), EcalEndcap, double(timestamp_.iLumi), double(nbadtowerEE)); } // producePlots() DEFINE_ECALDQM_WORKER(MLClient); } // namespace ecaldqm